private static void EmitTextureMipMapLevel(EmitterContext context, bool isBindless) { OpCodeTexture op = (OpCodeTexture)context.CurrOp; if (op.Rd.IsRZ) { return; } int raIndex = op.Ra.Index; int rbIndex = op.Rb.Index; Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(raIndex++, RegisterType.Gpr))); } Operand Rb() { if (rbIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(rbIndex++, RegisterType.Gpr))); } TextureFlags flags = TextureFlags.None; List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(Rb()); flags |= TextureFlags.Bindless; } SamplerType type = ConvertSamplerType(op.Dimensions); int coordsCount = type.GetDimensions(); Operand arrayIndex = op.IsArray ? Ra() : null; for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (op.IsArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } Operand[] sources = sourcesList.ToArray(); int rdIndex = op.Rd.Index; Operand GetDest() { if (rdIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(Register(rdIndex++, RegisterType.Gpr)); } int handle = !isBindless ? op.Immediate : 0; for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { Operand dest = GetDest(); // Components z and w aren't standard, we return 0 in this case and add a comment. if (compIndex >= 2) { context.Add(new CommentNode("Unsupported component z or w found")); context.Copy(dest, Const(0)); } else { Operand tempDest = Local(); TextureOperation operation = new TextureOperation( Instruction.Lod, type, flags, handle, compIndex, tempDest, sources); context.Add(operation); tempDest = context.FPMultiply(tempDest, ConstF(256.0f)); Operand finalValue = context.FPConvertToS32(tempDest); context.Copy(dest, finalValue); } } } }
private static void EmitTextureSample(EmitterContext context, TextureFlags flags) { OpCodeTexture op = (OpCodeTexture)context.CurrOp; bool isBindless = (flags & TextureFlags.Bindless) != 0; if (op.Rd.IsRZ) { return; } int raIndex = op.Ra.Index; int rbIndex = op.Rb.Index; Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(raIndex++, RegisterType.Gpr))); } Operand Rb() { if (rbIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(rbIndex++, RegisterType.Gpr))); } Operand arrayIndex = op.IsArray ? Ra() : null; List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(Rb()); } SamplerType type = ConvertSamplerType(op.Dimensions); int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (op.IsArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } bool hasLod = op.LodMode > TextureLodMode.LodZero; Operand lodValue = hasLod ? Rb() : ConstF(0); Operand packedOffs = op.HasOffset ? Rb() : null; if (op.HasDepthCompare) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } if ((op.LodMode == TextureLodMode.LodZero || op.LodMode == TextureLodMode.LodLevel || op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample) { sourcesList.Add(lodValue); flags |= TextureFlags.LodLevel; } if (op.HasOffset) { for (int index = 0; index < coordsCount; index++) { sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4))); } flags |= TextureFlags.Offset; } if (op.LodMode == TextureLodMode.LodBias || op.LodMode == TextureLodMode.LodBiasA) { sourcesList.Add(lodValue); flags |= TextureFlags.LodBias; } if (op.IsMultisample) { sourcesList.Add(Rb()); type |= SamplerType.Multisample; } Operand[] sources = sourcesList.ToArray(); int rdIndex = op.Rd.Index; Operand GetDest() { if (rdIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(Register(rdIndex++, RegisterType.Gpr)); } int handle = !isBindless ? op.Immediate : 0; for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { Operand dest = GetDest(); TextureOperation operation = new TextureOperation( Instruction.TextureSample, type, flags, handle, compIndex, dest, sources); context.Add(operation); } } }
private static void EmitTextureSample(EmitterContext context, TextureFlags flags) { OpCodeTexture op = (OpCodeTexture)context.CurrOp; bool isBindless = (flags & TextureFlags.Bindless) != 0; if (op.Rd.IsRZ) { return; } int raIndex = op.Ra.Index; int rbIndex = op.Rb.Index; Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(raIndex++, RegisterType.Gpr))); } Operand Rb() { if (rbIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(rbIndex++, RegisterType.Gpr))); } Operand arrayIndex = op.IsArray ? Ra() : null; List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(Rb()); } SamplerType type = ConvertSamplerType(op.Dimensions); bool hasLod = op.LodMode > TextureLodMode.LodZero; if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !(hasLod || op.HasDepthCompare || op.HasOffset || op.IsArray || op.IsMultisample)) { // For bindless, we don't have any way to know the texture type, // so we assume it's texture buffer when the sampler type is 1D, since that's more common. bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QueryIsTextureBuffer(op.Immediate); if (isTypeBuffer) { type = SamplerType.TextureBuffer; } } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (op.IsArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } Operand lodValue = hasLod ? Rb() : ConstF(0); Operand packedOffs = op.HasOffset ? Rb() : null; if (op.HasDepthCompare) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } if ((op.LodMode == TextureLodMode.LodZero || op.LodMode == TextureLodMode.LodLevel || op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample && type != SamplerType.TextureBuffer) { sourcesList.Add(lodValue); flags |= TextureFlags.LodLevel; } if (op.HasOffset) { for (int index = 0; index < coordsCount; index++) { sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4))); } flags |= TextureFlags.Offset; } if (op.LodMode == TextureLodMode.LodBias || op.LodMode == TextureLodMode.LodBiasA) { sourcesList.Add(lodValue); flags |= TextureFlags.LodBias; } if (op.IsMultisample) { sourcesList.Add(Rb()); type |= SamplerType.Multisample; } Operand[] sources = sourcesList.ToArray(); int rdIndex = op.Rd.Index; Operand GetDest() { if (rdIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(Register(rdIndex++, RegisterType.Gpr)); } int handle = !isBindless ? op.Immediate : 0; for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { Operand dest = GetDest(); TextureOperation operation = new TextureOperation( Instruction.TextureSample, type, flags, handle, compIndex, dest, sources); context.Add(operation); } } }