private void SetUsedTextureOrImage( Dictionary <TextureInfo, TextureMeta> dict, int cbufSlot, int handle, SamplerType type, TextureFormat format, bool intCoords, bool write, bool accurateType) { var dimensions = type.GetDimensions(); var isIndexed = type.HasFlag(SamplerType.Indexed); var usageFlags = TextureUsageFlags.None; if (intCoords) { usageFlags |= TextureUsageFlags.NeedsScaleValue; var canScale = (Stage == ShaderStage.Fragment || Stage == ShaderStage.Compute) && !isIndexed && !write && dimensions == 2; if (!canScale) { // Resolution scaling cannot be applied to this texture right now. // Flag so that we know to blacklist scaling on related textures when binding them. usageFlags |= TextureUsageFlags.ResScaleUnsupported; } } if (write) { usageFlags |= TextureUsageFlags.ImageStore; } int arraySize = isIndexed ? SamplerArraySize : 1; for (int layer = 0; layer < arraySize; layer++) { var info = new TextureInfo(cbufSlot, handle + layer * 2, isIndexed, format); var meta = new TextureMeta() { AccurateType = accurateType, Type = type, UsageFlags = usageFlags }; if (dict.TryGetValue(info, out var existingMeta)) { dict[info] = MergeTextureMeta(meta, existingMeta); } else { dict.Add(info, meta); } } }
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; } } } }
public static void Sust(EmitterContext context) { OpCodeImage op = (OpCodeImage)context.CurrOp; SamplerType type = ConvertSamplerType(op.Dimensions); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("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))); } 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 (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; } 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 = context.Config.GetTextureFormat(op.HandleOffset); } } 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.HandleOffset : 0; TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None; TextureOperation operation = context.CreateTextureOperation( Instruction.ImageStore, type, format, flags, handle, 0, null, sources); context.Add(operation); }
public static void Suld(EmitterContext context) { context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); OpCodeImage op = (OpCodeImage)context.CurrOp; SamplerType type = ConvertSamplerType(op.Dimensions); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("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))); } 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 (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; } Operand[] sources = sourcesList.ToArray(); int handle = !op.IsBindless ? op.HandleOffset : 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 = context.CreateTextureOperation( Instruction.ImageLoad, type, flags, handle, compIndex, rd, sources); if (!op.IsBindless) { operation.Format = context.Config.GetTextureFormat(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 = context.CreateTextureOperation( Instruction.ImageLoad, type, GetTextureFormat(op.Size), flags, handle, compIndex, rd, sources); 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; } } } }
private static void SetUsedTextureOrImage( Dictionary <TextureInfo, TextureMeta> dict, int cbufSlot, int handle, SamplerType type, TextureFormat format, bool intCoords, bool write, bool accurateType) { var dimensions = type.GetDimensions(); var isArray = type.HasFlag(SamplerType.Array); var isIndexed = type.HasFlag(SamplerType.Indexed); var usageFlags = TextureUsageFlags.None; if (intCoords) { usageFlags |= TextureUsageFlags.NeedsScaleValue; var canScale = (dimensions == 2 && !isArray) || (dimensions == 3 && isArray); if (!canScale) { // Resolution scaling cannot be applied to this texture right now. // Flag so that we know to blacklist scaling on related textures when binding them. usageFlags |= TextureUsageFlags.ResScaleUnsupported; } } if (write) { usageFlags |= TextureUsageFlags.ImageStore; } int arraySize = isIndexed ? SamplerArraySize : 1; for (int layer = 0; layer < arraySize; layer++) { var info = new TextureInfo(cbufSlot, handle + layer * 2, isIndexed, format); var meta = new TextureMeta() { AccurateType = accurateType, Type = type, UsageFlags = usageFlags }; if (dict.TryGetValue(info, out var existingMeta)) { meta.UsageFlags |= existingMeta.UsageFlags; // If the texture we have has inaccurate type information, then // we prefer the most accurate one. if (existingMeta.AccurateType) { meta.AccurateType = true; meta.Type = existingMeta.Type; } dict[info] = meta; } else { dict.Add(info, meta); } } }