public static void Txd(EmitterContext context) { OpCodeTxd op = (OpCodeTxd)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.Derivatives; List <Operand> sourcesList = new List <Operand>(); if (op.IsBindless) { sourcesList.Add(Ra()); } SamplerType type = ConvertSamplerType(op.Dimensions); int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } Operand packedParams = Ra(); if (op.IsArray) { sourcesList.Add(context.BitwiseAnd(packedParams, Const(0xffff))); type |= SamplerType.Array; } // Derivatives (X and Y). for (int dIndex = 0; dIndex < 2 * coordsCount; dIndex++) { sourcesList.Add(Rb()); } if (op.HasOffset) { for (int index = 0; index < coordsCount; index++) { sourcesList.Add(context.BitfieldExtractS32(packedParams, Const(16 + index * 4), Const(4))); } flags |= TextureFlags.Offset; } 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 = !op.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); } } }
public static void Texs(EmitterContext context) { OpCodeTextureScalar op = (OpCodeTextureScalar)context.CurrOp; if (op.Rd0.IsRZ && op.Rd1.IsRZ) { return; } List <Operand> sourcesList = new List <Operand>(); 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))); } void AddTextureOffset(int coordsCount, int stride, int size) { Operand packedOffs = Rb(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * stride), Const(size))); } } SamplerType type; TextureFlags flags; if (op is OpCodeTexs texsOp) { type = ConvertSamplerType(texsOp.Target); if (type == SamplerType.None) { context.Config.PrintLog("Invalid texture sampler type."); return; } flags = ConvertTextureFlags(texsOp.Target); if ((type & SamplerType.Array) != 0) { Operand arrayIndex = Ra(); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(arrayIndex); if ((type & SamplerType.Shadow) != 0) { sourcesList.Add(Rb()); } if ((flags & TextureFlags.LodLevel) != 0) { sourcesList.Add(ConstF(0)); } } else { switch (texsOp.Target) { case TextureTarget.Texture1DLodZero: sourcesList.Add(Ra()); sourcesList.Add(ConstF(0)); break; case TextureTarget.Texture2D: sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; case TextureTarget.Texture2DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; case TextureTarget.Texture2DLodLevel: case TextureTarget.Texture2DDepthCompare: case TextureTarget.Texture3D: case TextureTarget.TextureCube: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; case TextureTarget.Texture2DLodZeroDepthCompare: case TextureTarget.Texture3DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; case TextureTarget.Texture2DLodLevelDepthCompare: case TextureTarget.TextureCubeLodLevel: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(Rb()); break; } } } else if (op is OpCodeTlds tldsOp) { type = ConvertSamplerType(tldsOp.Target); if (type == SamplerType.None) { context.Config.PrintLog("Invalid texel fetch sampler type."); return; } flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords; if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.QueryInfoBool(QueryInfoName.IsTextureBuffer, tldsOp.Immediate)) { type = SamplerType.TextureBuffer; flags &= ~TextureFlags.LodLevel; } switch (tldsOp.Target) { case TexelLoadTarget.Texture1DLodZero: sourcesList.Add(Ra()); if (type != SamplerType.TextureBuffer) { sourcesList.Add(Const(0)); } break; case TexelLoadTarget.Texture1DLodLevel: sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; case TexelLoadTarget.Texture2DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(Const(0)); break; case TexelLoadTarget.Texture2DLodZeroOffset: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Const(0)); break; case TexelLoadTarget.Texture2DLodZeroMultisample: case TexelLoadTarget.Texture2DLodLevel: case TexelLoadTarget.Texture2DLodLevelOffset: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; case TexelLoadTarget.Texture3DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(Const(0)); break; case TexelLoadTarget.Texture2DArrayLodZero: sourcesList.Add(Rb()); sourcesList.Add(Rb()); sourcesList.Add(Ra()); sourcesList.Add(Const(0)); break; } if ((flags & TextureFlags.Offset) != 0) { AddTextureOffset(type.GetDimensions(), 4, 4); } } else if (op is OpCodeTld4s tld4sOp) { if (!(tld4sOp.HasDepthCompare || tld4sOp.HasOffset)) { sourcesList.Add(Ra()); sourcesList.Add(Rb()); } else { sourcesList.Add(Ra()); sourcesList.Add(Ra()); } type = SamplerType.Texture2D; flags = TextureFlags.Gather; if (tld4sOp.HasDepthCompare) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } if (tld4sOp.HasOffset) { AddTextureOffset(type.GetDimensions(), 8, 6); flags |= TextureFlags.Offset; } sourcesList.Add(Const(tld4sOp.GatherCompIndex)); } else { throw new InvalidOperationException($"Invalid opcode type \"{op.GetType().Name}\"."); } Operand[] sources = sourcesList.ToArray(); Operand[] rd0 = new Operand[2] { ConstF(0), ConstF(0) }; Operand[] rd1 = new Operand[2] { ConstF(0), ConstF(0) }; int destIncrement = 0; Operand GetDest() { int high = destIncrement >> 1; int low = destIncrement & 1; destIncrement++; if (op.IsFp16) { return(high != 0 ? (rd1[low] = Local()) : (rd0[low] = Local())); } else { int rdIndex = high != 0 ? op.Rd1.Index : op.Rd0.Index; if (rdIndex < RegisterConsts.RegisterZeroIndex) { rdIndex += low; } return(Register(rdIndex, RegisterType.Gpr)); } } int handle = op.Immediate; 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); } } if (op.IsFp16) { context.Copy(Register(op.Rd0), context.PackHalf2x16(rd0[0], rd0[1])); context.Copy(Register(op.Rd1), context.PackHalf2x16(rd1[0], rd1[1])); } }
public static void Tld4(EmitterContext context) { IOpCodeTld4 op = (IOpCodeTld4)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))); } Operand arrayIndex = op.IsArray ? Ra() : null; List <Operand> sourcesList = new List <Operand>(); SamplerType type = ConvertSamplerType(op.Dimensions); TextureFlags flags = TextureFlags.Gather; if (op.Bindless) { sourcesList.Add(Rb()); flags |= TextureFlags.Bindless; } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (op.IsArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } Operand[] packedOffs = new Operand[2]; packedOffs[0] = op.Offset != TextureGatherOffset.None ? Rb() : null; packedOffs[1] = op.Offset == TextureGatherOffset.Offsets ? Rb() : null; if (op.HasDepthCompare) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } if (op.Offset != TextureGatherOffset.None) { int offsetTexelsCount = op.Offset == TextureGatherOffset.Offsets ? 4 : 1; for (int index = 0; index < coordsCount * offsetTexelsCount; index++) { Operand packed = packedOffs[(index >> 2) & 1]; sourcesList.Add(context.BitfieldExtractS32(packed, Const((index & 3) * 8), Const(6))); } flags |= op.Offset == TextureGatherOffset.Offsets ? TextureFlags.Offsets : TextureFlags.Offset; } sourcesList.Add(Const(op.GatherCompIndex)); 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 = op.Immediate; 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); } } }
public static void Suld(EmitterContext context) { OpCodeImage op = (OpCodeImage)context.CurrOp; SamplerType type = ConvertSamplerType(op.Dimensions); if (type == SamplerType.None) { context.Config.PrintLog("Invalid image store sampler type."); return; } // Rb is Rd on the SULD instruction. int rdIndex = op.Rb.Index; int raIndex = op.Ra.Index; Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(raIndex++, RegisterType.Gpr))); } bool isArray = op.Dimensions == ImageDimensions.Image1DArray || op.Dimensions == ImageDimensions.Image2DArray; Operand arrayIndex = isArray ? Ra() : null; List <Operand> sourcesList = new List <Operand>(); if (op.IsBindless) { sourcesList.Add(context.Copy(Register(op.Rc))); } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (isArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } Operand[] sources = sourcesList.ToArray(); int handle = !op.IsBindless ? op.Immediate : 0; TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None; if (op.UseComponents) { int componentMask = (int)op.Components; for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) == 0) { continue; } if (rdIndex == RegisterConsts.RegisterZeroIndex) { break; } Operand rd = Register(rdIndex++, RegisterType.Gpr); TextureOperation operation = new TextureOperation( Instruction.ImageLoad, type, flags, handle, compIndex, rd, sources); if (!op.IsBindless) { operation.Format = GetTextureFormat(context, handle); } context.Add(operation); } } else { if (op.ByteAddress) { int xIndex = op.IsBindless ? 1 : 0; sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(op.Size))); } int components = GetComponents(op.Size); for (int compIndex = 0; compIndex < components; compIndex++) { if (rdIndex == RegisterConsts.RegisterZeroIndex) { break; } Operand rd = Register(rdIndex++, RegisterType.Gpr); TextureOperation operation = new TextureOperation( Instruction.ImageLoad, type, flags, handle, compIndex, rd, sources) { Format = GetTextureFormat(op.Size) }; context.Add(operation); switch (op.Size) { case IntegerSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break; case IntegerSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break; case IntegerSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break; case IntegerSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break; } } } }
public static void Sust(EmitterContext context) { OpCodeImage op = (OpCodeImage)context.CurrOp; SamplerType type = ConvertSamplerType(op.Dimensions); if (type == SamplerType.None) { context.Config.PrintLog("Invalid image store sampler type."); 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))); } bool isArray = op.Dimensions == ImageDimensions.Image1DArray || op.Dimensions == ImageDimensions.Image2DArray; Operand arrayIndex = isArray ? Ra() : null; List <Operand> sourcesList = new List <Operand>(); if (op.IsBindless) { sourcesList.Add(context.Copy(Register(op.Rc))); } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (isArray) { sourcesList.Add(arrayIndex); type |= SamplerType.Array; } TextureFormat format = TextureFormat.Unknown; if (op.UseComponents) { int componentMask = (int)op.Components; for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { sourcesList.Add(Rb()); } } if (!op.IsBindless) { format = GetTextureFormat(context, op.Immediate); } } else { if (op.ByteAddress) { int xIndex = op.IsBindless ? 1 : 0; sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Size))); } int components = GetComponents(op.Size); for (int compIndex = 0; compIndex < components; compIndex++) { sourcesList.Add(Rb()); } format = GetTextureFormat(op.Size); } Operand[] sources = sourcesList.ToArray(); int handle = !op.IsBindless ? op.Immediate : 0; TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None; TextureOperation operation = new TextureOperation( Instruction.ImageStore, type, flags, handle, 0, null, sources) { Format = format }; context.Add(operation); }
private static void Txq(EmitterContext context, bool bindless) { OpCodeTex op = (OpCodeTex)context.CurrOp; if (op.Rd.IsRZ) { return; } TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6); // TODO: Validate and use property. Instruction inst = Instruction.TextureSize; TextureType type = TextureType.Texture2D; TextureFlags flags = bindless ? TextureFlags.Bindless : TextureFlags.None; int raIndex = op.Ra.Index; Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(raIndex++, RegisterType.Gpr))); } List <Operand> sourcesList = new List <Operand>(); if (bindless) { sourcesList.Add(Ra()); } sourcesList.Add(Ra()); 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 = !bindless ? 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( inst, type, flags, handle, compIndex, dest, sources); context.Add(operation); } } }
private static void Tex(EmitterContext context, TextureFlags flags) { OpCodeTexture op = (OpCodeTexture)context.CurrOp; bool isBindless = (flags & TextureFlags.Bindless) != 0; bool intCoords = (flags & TextureFlags.IntCoords) != 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()); } TextureType type = GetTextureType(op.Dimensions); int coordsCount = type.GetCoordsCount(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (op.IsArray) { sourcesList.Add(arrayIndex); type |= TextureType.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 |= TextureType.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 |= TextureType.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 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); 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); } } }
private static void EmitSust( EmitterContext context, CacheOpSt cacheOp, SuDim dimensions, SuSize size, int imm, SuRgba componentMask, int srcA, int srcB, int srcC, bool useComponents, bool byteAddress, bool isBindless) { SamplerType type = ConvertSamplerType(dimensions); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("Invalid image store sampler type."); return; } Operand Ra() { if (srcA > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(srcA++, RegisterType.Gpr))); } Operand Rb() { if (srcB > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(srcB++, RegisterType.Gpr))); } List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) { sourcesList.Add(Const(0)); type &= ~SamplerType.Mask; type |= SamplerType.Texture2D; } if (type.HasFlag(SamplerType.Array)) { sourcesList.Add(Ra()); } TextureFormat format = TextureFormat.Unknown; if (useComponents) { for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { sourcesList.Add(Rb()); } } if (!isBindless) { format = context.Config.GetTextureFormat(imm); } } else { if (byteAddress) { int xIndex = isBindless ? 1 : 0; sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); } int components = GetComponents(size); for (int compIndex = 0; compIndex < components; compIndex++) { sourcesList.Add(Rb()); } format = GetTextureFormat(size); } Operand[] sources = sourcesList.ToArray(); int handle = imm; TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; if (cacheOp == CacheOpSt.Cg) { flags |= TextureFlags.Coherent; } TextureOperation operation = context.CreateTextureOperation( Instruction.ImageStore, type, format, flags, handle, 0, null, sources); context.Add(operation); }
private static void EmitSured( EmitterContext context, SuDim dimensions, RedOp atomicOp, SuatomSize size, int imm, int srcA, int srcB, int srcC, bool byteAddress, bool isBindless) { SamplerType type = ConvertSamplerType(dimensions); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("Invalid image reduction sampler type."); return; } Operand Ra() { if (srcA > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(srcA++, RegisterType.Gpr))); } Operand Rb() { if (srcB > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(srcB++, RegisterType.Gpr))); } List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) { sourcesList.Add(Const(0)); type &= ~SamplerType.Mask; type |= SamplerType.Texture2D; } if (type.HasFlag(SamplerType.Array)) { sourcesList.Add(Ra()); type |= SamplerType.Array; } if (byteAddress) { int xIndex = isBindless ? 1 : 0; sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); } // TODO: FP and 64-bit formats. TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm)) : GetTextureFormat(size); sourcesList.Add(Rb()); Operand[] sources = sourcesList.ToArray(); TextureFlags flags = GetAtomicOpFlags((SuatomOp)atomicOp); if (isBindless) { flags |= TextureFlags.Bindless; } TextureOperation operation = context.CreateTextureOperation( Instruction.ImageAtomic, type, format, flags, imm, 0, null, sources); context.Add(operation); }
private static void EmitSuld( EmitterContext context, CacheOpLd cacheOp, SuDim dimensions, SuSize size, int imm, SuRgba componentMask, int srcA, int srcB, int srcC, bool useComponents, bool byteAddress, bool isBindless) { context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); SamplerType type = ConvertSamplerType(dimensions); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("Invalid image store sampler type."); return; } Operand Ra() { if (srcA > RegisterConsts.RegisterZeroIndex) { return(Const(0)); } return(context.Copy(Register(srcA++, RegisterType.Gpr))); } List <Operand> sourcesList = new List <Operand>(); if (isBindless) { sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); } int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) { sourcesList.Add(Const(0)); type &= ~SamplerType.Mask; type |= SamplerType.Texture2D; } if (type.HasFlag(SamplerType.Array)) { sourcesList.Add(Ra()); } Operand[] sources = sourcesList.ToArray(); int handle = imm; TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; if (cacheOp == CacheOpLd.Cg) { flags |= TextureFlags.Coherent; } if (useComponents) { for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) == 0) { continue; } if (srcB == RegisterConsts.RegisterZeroIndex) { break; } Operand rd = Register(srcB++, RegisterType.Gpr); TextureOperation operation = context.CreateTextureOperation( Instruction.ImageLoad, type, flags, handle, compIndex, rd, sources); if (!isBindless) { operation.Format = context.Config.GetTextureFormat(handle); } context.Add(operation); } } else { if (byteAddress) { int xIndex = isBindless ? 1 : 0; sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(size))); } int components = GetComponents(size); for (int compIndex = 0; compIndex < components; compIndex++) { if (srcB == RegisterConsts.RegisterZeroIndex) { break; } Operand rd = Register(srcB++, RegisterType.Gpr); TextureOperation operation = context.CreateTextureOperation( Instruction.ImageLoad, type, GetTextureFormat(size), flags, handle, compIndex, rd, sources); context.Add(operation); switch (size) { case SuSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break; case SuSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break; case SuSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break; case SuSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break; } } } }