diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Shader')
23 files changed, 300 insertions, 134 deletions
diff --git a/src/Ryujinx.Graphics.Shader/BufferDescriptor.cs b/src/Ryujinx.Graphics.Shader/BufferDescriptor.cs index ead1c5e6..11d4e3c1 100644 --- a/src/Ryujinx.Graphics.Shader/BufferDescriptor.cs +++ b/src/Ryujinx.Graphics.Shader/BufferDescriptor.cs @@ -4,14 +4,16 @@ namespace Ryujinx.Graphics.Shader { // New fields should be added to the end of the struct to keep disk shader cache compatibility. + public readonly int Set; public readonly int Binding; public readonly byte Slot; public readonly byte SbCbSlot; public readonly ushort SbCbOffset; public readonly BufferUsageFlags Flags; - public BufferDescriptor(int binding, int slot) + public BufferDescriptor(int set, int binding, int slot) { + Set = set; Binding = binding; Slot = (byte)slot; SbCbSlot = 0; @@ -19,8 +21,9 @@ namespace Ryujinx.Graphics.Shader Flags = BufferUsageFlags.None; } - public BufferDescriptor(int binding, int slot, int sbCbSlot, int sbCbOffset, BufferUsageFlags flags) + public BufferDescriptor(int set, int binding, int slot, int sbCbSlot, int sbCbOffset, BufferUsageFlags flags) { + Set = set; Binding = binding; Slot = (byte)slot; SbCbSlot = (byte)sbCbSlot; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index f0e57b53..4308b08f 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -462,7 +462,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } else { - context.Properties.Textures.TryGetValue(texOp.Binding, out TextureDefinition definition); + context.Properties.Textures.TryGetValue(texOp.GetTextureSetAndBinding(), out TextureDefinition definition); bool hasLod = !definition.Type.HasFlag(SamplerType.Multisample) && (definition.Type & SamplerType.Mask) != SamplerType.TextureBuffer; string texCall; @@ -639,7 +639,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions private static string GetSamplerName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex) { - TextureDefinition textureDefinition = context.Properties.Textures[texOp.Binding]; + TextureDefinition textureDefinition = context.Properties.Textures[texOp.GetTextureSetAndBinding()]; string name = textureDefinition.Name; if (textureDefinition.ArrayLength != 1) @@ -649,7 +649,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions if (texOp.IsSeparate) { - TextureDefinition samplerDefinition = context.Properties.Textures[texOp.SamplerBinding]; + TextureDefinition samplerDefinition = context.Properties.Textures[texOp.GetSamplerSetAndBinding()]; string samplerName = samplerDefinition.Name; if (samplerDefinition.ArrayLength != 1) @@ -665,7 +665,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions private static string GetImageName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex) { - TextureDefinition definition = context.Properties.Images[texOp.Binding]; + TextureDefinition definition = context.Properties.Images[texOp.GetTextureSetAndBinding()]; string name = definition.Name; if (definition.ArrayLength != 1) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs index 2b1fdf44..f3be29bb 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs @@ -33,9 +33,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv public Dictionary<int, Instruction> LocalMemories { get; } = new(); public Dictionary<int, Instruction> SharedMemories { get; } = new(); - public Dictionary<int, SamplerType> SamplersTypes { get; } = new(); - public Dictionary<int, SamplerDeclaration> Samplers { get; } = new(); - public Dictionary<int, ImageDeclaration> Images { get; } = new(); + public Dictionary<SetBindingPair, SamplerType> SamplersTypes { get; } = new(); + public Dictionary<SetBindingPair, SamplerDeclaration> Samplers { get; } = new(); + public Dictionary<SetBindingPair, ImageDeclaration> Images { get; } = new(); public Dictionary<IoDefinition, Instruction> Inputs { get; } = new(); public Dictionary<IoDefinition, Instruction> Outputs { get; } = new(); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs index 37df4df8..55d35bf0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs @@ -208,13 +208,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv var sampledImageVariable = context.Variable(sampledImageArrayPointerType, StorageClass.UniformConstant); - context.Samplers.Add(sampler.Binding, new SamplerDeclaration( + context.Samplers.Add(new(sampler.Set, sampler.Binding), new SamplerDeclaration( imageType, sampledImageType, sampledImagePointerType, sampledImageVariable, sampler.ArrayLength != 1)); - context.SamplersTypes.Add(sampler.Binding, sampler.Type); + context.SamplersTypes.Add(new(sampler.Set, sampler.Binding), sampler.Type); context.Name(sampledImageVariable, sampler.Name); context.Decorate(sampledImageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex); @@ -256,7 +256,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv var imageVariable = context.Variable(imageArrayPointerType, StorageClass.UniformConstant); - context.Images.Add(image.Binding, new ImageDeclaration(imageType, imagePointerType, imageVariable, image.ArrayLength != 1)); + context.Images.Add(new(image.Set, image.Binding), new ImageDeclaration(imageType, imagePointerType, imageVariable, image.ArrayLength != 1)); context.Name(imageVariable, image.Name); context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 34f8532a..6206985d 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -602,7 +602,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return context.Get(type, texOp.GetSource(srcIndex++)); } - ImageDeclaration declaration = context.Images[texOp.Binding]; + ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()]; SpvInstruction image = declaration.Image; SpvInstruction resultType = context.GetType(componentType); @@ -681,7 +681,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return context.Get(type, texOp.GetSource(srcIndex++)); } - ImageDeclaration declaration = context.Images[texOp.Binding]; + ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()]; SpvInstruction image = declaration.Image; if (declaration.IsIndexed) @@ -738,7 +738,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return context.Get(type, texOp.GetSource(srcIndex++)); } - ImageDeclaration declaration = context.Images[texOp.Binding]; + ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()]; SpvInstruction image = declaration.Image; if (declaration.IsIndexed) @@ -837,7 +837,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return context.Get(type, texOp.GetSource(srcIndex++)); } - SamplerDeclaration declaration = context.Samplers[texOp.Binding]; + SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); int pCount = texOp.Type.GetDimensions(); @@ -1161,7 +1161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return context.Get(type, texOp.GetSource(srcIndex++)); } - SamplerDeclaration declaration = context.Samplers[texOp.Binding]; + SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); int coordsCount = texOp.Type.GetDimensions(); @@ -1433,7 +1433,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv int srcIndex = 0; - SamplerDeclaration declaration = context.Samplers[texOp.Binding]; + SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); image = context.Image(declaration.ImageType, image); @@ -1449,7 +1449,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv int srcIndex = 0; - SamplerDeclaration declaration = context.Samplers[texOp.Binding]; + SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); image = context.Image(declaration.ImageType, image); @@ -1460,7 +1460,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv } else { - var type = context.SamplersTypes[texOp.Binding]; + var type = context.SamplersTypes[texOp.GetTextureSetAndBinding()]; bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer; int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.GetDimensions(); @@ -1889,7 +1889,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv { image = context.Load(declaration.ImageType, image); - SamplerDeclaration samplerDeclaration = context.Samplers[texOp.SamplerBinding]; + SamplerDeclaration samplerDeclaration = context.Samplers[texOp.GetSamplerSetAndBinding()]; SpvInstruction sampler = samplerDeclaration.Image; diff --git a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs index 3dc4ad90..4e6d6edf 100644 --- a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs +++ b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs @@ -27,34 +27,43 @@ namespace Ryujinx.Graphics.Shader ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize); /// <summary> - /// Queries the binding number of a constant buffer. + /// Gets the binding number of a constant buffer. /// </summary> /// <param name="index">Constant buffer index</param> /// <returns>Binding number</returns> - int CreateConstantBufferBinding(int index); + SetBindingPair CreateConstantBufferBinding(int index); /// <summary> - /// Queries the binding number of an image. + /// Gets the binding number of an image. /// </summary> /// <param name="count">For array of images, the number of elements of the array, otherwise it should be 1</param> /// <param name="isBuffer">Indicates if the image is a buffer image</param> /// <returns>Binding number</returns> - int CreateImageBinding(int count, bool isBuffer); + SetBindingPair CreateImageBinding(int count, bool isBuffer); /// <summary> - /// Queries the binding number of a storage buffer. + /// Gets the binding number of a storage buffer. /// </summary> /// <param name="index">Storage buffer index</param> /// <returns>Binding number</returns> - int CreateStorageBufferBinding(int index); + SetBindingPair CreateStorageBufferBinding(int index); /// <summary> - /// Queries the binding number of a texture. + /// Gets the binding number of a texture. /// </summary> /// <param name="count">For array of textures, the number of elements of the array, otherwise it should be 1</param> /// <param name="isBuffer">Indicates if the texture is a buffer texture</param> /// <returns>Binding number</returns> - int CreateTextureBinding(int count, bool isBuffer); + SetBindingPair CreateTextureBinding(int count, bool isBuffer); + + /// <summary> + /// Gets the set index for an additional set, or -1 if there's no extra set available. + /// </summary> + /// <returns>Extra set index, or -1 if not available</returns> + int CreateExtraSet() + { + return -1; + } /// <summary> /// Queries Local Size X for compute shaders. diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs index 0aac0ffa..383e82c6 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs @@ -278,7 +278,7 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Bindless; } - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.ImageAtomic, type, format, @@ -286,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, imm); - Operand res = context.ImageAtomic(type, format, flags, binding, sources); + Operand res = context.ImageAtomic(type, format, flags, setAndBinding, sources); context.Copy(d, res); } @@ -389,7 +389,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureFormat format = isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormat(context.TranslatorContext.GpuAccessor, handle); - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.ImageLoad, type, format, @@ -397,7 +397,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, handle); - context.ImageLoad(type, format, flags, binding, (int)componentMask, dests, sources); + context.ImageLoad(type, format, flags, setAndBinding, (int)componentMask, dests, sources); } else { @@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureFormat format = GetTextureFormat(size); - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.ImageLoad, type, format, @@ -440,7 +440,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, handle); - context.ImageLoad(type, format, flags, binding, compMask, dests, sources); + context.ImageLoad(type, format, flags, setAndBinding, compMask, dests, sources); switch (size) { @@ -552,7 +552,7 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Bindless; } - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.ImageAtomic, type, format, @@ -560,7 +560,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, imm); - context.ImageAtomic(type, format, flags, binding, sources); + context.ImageAtomic(type, format, flags, setAndBinding, sources); } private static void EmitSust( @@ -679,7 +679,7 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Coherent; } - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.ImageStore, type, format, @@ -687,7 +687,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, handle); - context.ImageStore(type, format, flags, binding, sources); + context.ImageStore(type, format, flags, setAndBinding, sources); } private static int GetComponentSizeInBytesLog2(SuatomSize size) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 06daa26a..2076262d 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -885,7 +885,7 @@ namespace Ryujinx.Graphics.Shader.Instructions return Register(dest++, RegisterType.Gpr); } - int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.Lod, type, TextureFormat.Unknown, @@ -913,7 +913,7 @@ namespace Ryujinx.Graphics.Shader.Instructions else { // The instruction component order is the inverse of GLSL's. - Operand res = context.Lod(type, flags, binding, compIndex ^ 1, sources); + Operand res = context.Lod(type, flags, setAndBinding, compIndex ^ 1, sources); res = context.FPMultiply(res, ConstF(256.0f)); @@ -1116,12 +1116,12 @@ namespace Ryujinx.Graphics.Shader.Instructions } TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; - int binding; + SetBindingPair setAndBinding; switch (query) { case TexQuery.TexHeaderDimension: - binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.TextureQuerySize, type, TextureFormat.Unknown, @@ -1140,13 +1140,13 @@ namespace Ryujinx.Graphics.Shader.Instructions break; } - context.Copy(d, context.TextureQuerySize(type, flags, binding, compIndex, sources)); + context.Copy(d, context.TextureQuerySize(type, flags, setAndBinding, compIndex, sources)); } } break; case TexQuery.TexHeaderTextureType: - binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding( + setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.TextureQuerySamples, type, TextureFormat.Unknown, @@ -1171,7 +1171,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (d != null) { - context.Copy(d, context.TextureQuerySamples(type, flags, binding, sources)); + context.Copy(d, context.TextureQuerySamples(type, flags, setAndBinding, sources)); } } break; @@ -1191,7 +1191,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand[] dests, Operand[] sources) { - int binding = flags.HasFlag(TextureFlags.Bindless) ? 0 : context.ResourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = flags.HasFlag(TextureFlags.Bindless) ? default : context.ResourceManager.GetTextureOrImageBinding( Instruction.TextureSample, type, TextureFormat.Unknown, @@ -1199,7 +1199,7 @@ namespace Ryujinx.Graphics.Shader.Instructions TextureOperation.DefaultCbufSlot, handle); - context.TextureSample(type, flags, binding, componentMask, dests, sources); + context.TextureSample(type, flags, setAndBinding, componentMask, dests, sources); } private static SamplerType ConvertSamplerType(TexDim dimensions) diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs index 74ec5ca6..7eee8f2e 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs @@ -8,7 +8,9 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation public TextureFormat Format { get; set; } public TextureFlags Flags { get; private set; } + public int Set { get; private set; } public int Binding { get; private set; } + public int SamplerSet { get; private set; } public int SamplerBinding { get; private set; } public TextureOperation( @@ -16,6 +18,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation SamplerType type, TextureFormat format, TextureFlags flags, + int set, int binding, int compIndex, Operand[] dests, @@ -24,24 +27,28 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation Type = type; Format = format; Flags = flags; + Set = set; Binding = binding; + SamplerSet = -1; SamplerBinding = -1; } - public void TurnIntoArray(int binding) + public void TurnIntoArray(SetBindingPair setAndBinding) { Flags &= ~TextureFlags.Bindless; - Binding = binding; + Set = setAndBinding.SetIndex; + Binding = setAndBinding.Binding; } - public void TurnIntoArray(int textureBinding, int samplerBinding) + public void TurnIntoArray(SetBindingPair textureSetAndBinding, SetBindingPair samplerSetAndBinding) { - TurnIntoArray(textureBinding); + TurnIntoArray(textureSetAndBinding); - SamplerBinding = samplerBinding; + SamplerSet = samplerSetAndBinding.SetIndex; + SamplerBinding = samplerSetAndBinding.Binding; } - public void SetBinding(int binding) + public void SetBinding(SetBindingPair setAndBinding) { if ((Flags & TextureFlags.Bindless) != 0) { @@ -50,7 +57,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation RemoveSource(0); } - Binding = binding; + Set = setAndBinding.SetIndex; + Binding = setAndBinding.Binding; } public void SetLodLevelFlag() diff --git a/src/Ryujinx.Graphics.Shader/SetBindingPair.cs b/src/Ryujinx.Graphics.Shader/SetBindingPair.cs new file mode 100644 index 00000000..1e8a4f9c --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/SetBindingPair.cs @@ -0,0 +1,4 @@ +namespace Ryujinx.Graphics.Shader +{ + public readonly record struct SetBindingPair(int SetIndex, int Binding); +} diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs index 4068c412..867cae85 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs @@ -8,7 +8,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr public TextureFormat Format { get; } public TextureFlags Flags { get; } + public int Set { get; } public int Binding { get; } + public int SamplerSet { get; } public int SamplerBinding { get; } public bool IsSeparate => SamplerBinding >= 0; @@ -18,7 +20,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr SamplerType type, TextureFormat format, TextureFlags flags, + int set, int binding, + int samplerSet, int samplerBinding, int index, params IAstNode[] sources) : base(inst, StorageKind.None, false, index, sources, sources.Length) @@ -26,8 +30,20 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Type = type; Format = format; Flags = flags; + Set = set; Binding = binding; + SamplerSet = samplerSet; SamplerBinding = samplerBinding; } + + public SetBindingPair GetTextureSetAndBinding() + { + return new SetBindingPair(Set, Binding); + } + + public SetBindingPair GetSamplerSetAndBinding() + { + return new SetBindingPair(SamplerSet, SamplerBinding); + } } } diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs index 8c12c2aa..53ed6bfc 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs @@ -6,15 +6,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { private readonly Dictionary<int, BufferDefinition> _constantBuffers; private readonly Dictionary<int, BufferDefinition> _storageBuffers; - private readonly Dictionary<int, TextureDefinition> _textures; - private readonly Dictionary<int, TextureDefinition> _images; + private readonly Dictionary<SetBindingPair, TextureDefinition> _textures; + private readonly Dictionary<SetBindingPair, TextureDefinition> _images; private readonly Dictionary<int, MemoryDefinition> _localMemories; private readonly Dictionary<int, MemoryDefinition> _sharedMemories; public IReadOnlyDictionary<int, BufferDefinition> ConstantBuffers => _constantBuffers; public IReadOnlyDictionary<int, BufferDefinition> StorageBuffers => _storageBuffers; - public IReadOnlyDictionary<int, TextureDefinition> Textures => _textures; - public IReadOnlyDictionary<int, TextureDefinition> Images => _images; + public IReadOnlyDictionary<SetBindingPair, TextureDefinition> Textures => _textures; + public IReadOnlyDictionary<SetBindingPair, TextureDefinition> Images => _images; public IReadOnlyDictionary<int, MemoryDefinition> LocalMemories => _localMemories; public IReadOnlyDictionary<int, MemoryDefinition> SharedMemories => _sharedMemories; @@ -22,8 +22,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { _constantBuffers = new Dictionary<int, BufferDefinition>(); _storageBuffers = new Dictionary<int, BufferDefinition>(); - _textures = new Dictionary<int, TextureDefinition>(); - _images = new Dictionary<int, TextureDefinition>(); + _textures = new Dictionary<SetBindingPair, TextureDefinition>(); + _images = new Dictionary<SetBindingPair, TextureDefinition>(); _localMemories = new Dictionary<int, MemoryDefinition>(); _sharedMemories = new Dictionary<int, MemoryDefinition>(); } @@ -40,12 +40,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr public void AddOrUpdateTexture(TextureDefinition definition) { - _textures[definition.Binding] = definition; + _textures[new(definition.Set, definition.Binding)] = definition; } public void AddOrUpdateImage(TextureDefinition definition) { - _images[definition.Binding] = definition; + _images[new(definition.Set, definition.Binding)] = definition; } public int AddLocalMemory(MemoryDefinition definition) diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs index c4ebaee7..88053658 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs @@ -169,7 +169,17 @@ namespace Ryujinx.Graphics.Shader.StructuredIr AstTextureOperation GetAstTextureOperation(TextureOperation texOp) { - return new AstTextureOperation(inst, texOp.Type, texOp.Format, texOp.Flags, texOp.Binding, texOp.SamplerBinding, texOp.Index, sources); + return new AstTextureOperation( + inst, + texOp.Type, + texOp.Format, + texOp.Flags, + texOp.Set, + texOp.Binding, + texOp.SamplerSet, + texOp.SamplerBinding, + texOp.Index, + sources); } int componentsCount = BitOperations.PopCount((uint)operation.Index); diff --git a/src/Ryujinx.Graphics.Shader/TextureDescriptor.cs b/src/Ryujinx.Graphics.Shader/TextureDescriptor.cs index d287a1aa..1e387407 100644 --- a/src/Ryujinx.Graphics.Shader/TextureDescriptor.cs +++ b/src/Ryujinx.Graphics.Shader/TextureDescriptor.cs @@ -4,6 +4,7 @@ namespace Ryujinx.Graphics.Shader { // New fields should be added to the end of the struct to keep disk shader cache compatibility. + public readonly int Set; public readonly int Binding; public readonly SamplerType Type; @@ -18,6 +19,7 @@ namespace Ryujinx.Graphics.Shader public readonly TextureUsageFlags Flags; public TextureDescriptor( + int set, int binding, SamplerType type, TextureFormat format, @@ -27,6 +29,7 @@ namespace Ryujinx.Graphics.Shader bool separate, TextureUsageFlags flags) { + Set = set; Binding = binding; Type = type; Format = format; diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs index e1157eea..5e07b39f 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs @@ -124,7 +124,7 @@ namespace Ryujinx.Graphics.Shader.Translation this.TextureSample( SamplerType.TextureBuffer, TextureFlags.IntCoords, - ResourceManager.Reservations.IndexBufferTextureBinding, + ResourceManager.Reservations.GetIndexBufferTextureSetAndBinding(), 1, new[] { vertexIndexVr }, new[] { this.IAdd(ibBaseOffset, outputVertexOffset) }); @@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Translation this.TextureSample( SamplerType.TextureBuffer, TextureFlags.IntCoords, - ResourceManager.Reservations.TopologyRemapBufferTextureBinding, + ResourceManager.Reservations.GetTopologyRemapBufferTextureSetAndBinding(), 1, new[] { vertexIndex }, new[] { this.IAdd(baseVertex, Const(index)) }); diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index 9e314c62..5bdbb002 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -618,12 +618,21 @@ namespace Ryujinx.Graphics.Shader.Translation SamplerType type, TextureFormat format, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, Operand[] sources) { Operand dest = Local(); - context.Add(new TextureOperation(Instruction.ImageAtomic, type, format, flags, binding, 0, new[] { dest }, sources)); + context.Add(new TextureOperation( + Instruction.ImageAtomic, + type, + format, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + 0, + new[] { dest }, + sources)); return dest; } @@ -633,12 +642,21 @@ namespace Ryujinx.Graphics.Shader.Translation SamplerType type, TextureFormat format, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, int compMask, Operand[] dests, Operand[] sources) { - context.Add(new TextureOperation(Instruction.ImageLoad, type, format, flags, binding, compMask, dests, sources)); + context.Add(new TextureOperation( + Instruction.ImageLoad, + type, + format, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + compMask, + dests, + sources)); } public static void ImageStore( @@ -646,10 +664,19 @@ namespace Ryujinx.Graphics.Shader.Translation SamplerType type, TextureFormat format, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, Operand[] sources) { - context.Add(new TextureOperation(Instruction.ImageStore, type, format, flags, binding, 0, null, sources)); + context.Add(new TextureOperation( + Instruction.ImageStore, + type, + format, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + 0, + null, + sources)); } public static Operand IsNan(this EmitterContext context, Operand a, Instruction fpType = Instruction.FP32) @@ -718,13 +745,22 @@ namespace Ryujinx.Graphics.Shader.Translation this EmitterContext context, SamplerType type, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, int compIndex, Operand[] sources) { Operand dest = Local(); - context.Add(new TextureOperation(Instruction.Lod, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources)); + context.Add(new TextureOperation( + Instruction.Lod, + type, + TextureFormat.Unknown, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + compIndex, + new[] { dest }, + sources)); return dest; } @@ -889,24 +925,42 @@ namespace Ryujinx.Graphics.Shader.Translation this EmitterContext context, SamplerType type, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, int compMask, Operand[] dests, Operand[] sources) { - context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources)); + context.Add(new TextureOperation( + Instruction.TextureSample, + type, + TextureFormat.Unknown, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + compMask, + dests, + sources)); } public static Operand TextureQuerySamples( this EmitterContext context, SamplerType type, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, Operand[] sources) { Operand dest = Local(); - context.Add(new TextureOperation(Instruction.TextureQuerySamples, type, TextureFormat.Unknown, flags, binding, 0, new[] { dest }, sources)); + context.Add(new TextureOperation( + Instruction.TextureQuerySamples, + type, + TextureFormat.Unknown, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + 0, + new[] { dest }, + sources)); return dest; } @@ -915,13 +969,22 @@ namespace Ryujinx.Graphics.Shader.Translation this EmitterContext context, SamplerType type, TextureFlags flags, - int binding, + SetBindingPair setAndBinding, int compIndex, Operand[] sources) { Operand dest = Local(); - context.Add(new TextureOperation(Instruction.TextureQuerySize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources)); + context.Add(new TextureOperation( + Instruction.TextureQuerySize, + type, + TextureFormat.Unknown, + flags, + setAndBinding.SetIndex, + setAndBinding.Binding, + compIndex, + new[] { dest }, + sources)); return dest; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs index 4128af24..29501b71 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations bool hasSampler = !texOp.Inst.IsImage(); - int textureBinding = resourceManager.GetTextureOrImageBinding( + SetBindingPair textureSetAndBinding = resourceManager.GetTextureOrImageBinding( texOp.Inst, texOp.Type, texOp.Format, @@ -111,7 +111,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations texOp.InsertSource(1, samplerIndex); - int samplerBinding = resourceManager.GetTextureOrImageBinding( + SetBindingPair samplerSetAndBinding = resourceManager.GetTextureOrImageBinding( texOp.Inst, SamplerType.None, texOp.Format, @@ -120,11 +120,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations TextureHandle.PackOffsets(0, 0, TextureHandleType.Direct), samplerPoolLength); - texOp.TurnIntoArray(textureBinding, samplerBinding); + texOp.TurnIntoArray(textureSetAndBinding, samplerSetAndBinding); } else { - texOp.TurnIntoArray(textureBinding); + texOp.TurnIntoArray(textureSetAndBinding); } return true; @@ -445,7 +445,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations } } - int binding = resourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = resourceManager.GetTextureOrImageBinding( texOp.Inst, texOp.Type, texOp.Format, @@ -453,7 +453,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations cbufSlot, cbufOffset); - texOp.SetBinding(binding); + texOp.SetBinding(setAndBinding); } } } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs index f2be7975..8eed139d 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs @@ -221,7 +221,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static void TurnIntoArray(ResourceManager resourceManager, TextureOperation texOp, int cbufSlot, int handleIndex, int length) { - int binding = resourceManager.GetTextureOrImageBinding( + SetBindingPair setAndBinding = resourceManager.GetTextureOrImageBinding( texOp.Inst, texOp.Type, texOp.Format, @@ -230,7 +230,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations handleIndex, length); - texOp.TurnIntoArray(binding); + texOp.TurnIntoArray(setAndBinding); } } } diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs index 890501c9..94691a5b 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs @@ -20,8 +20,8 @@ namespace Ryujinx.Graphics.Shader.Translation private readonly ShaderStage _stage; private readonly string _stagePrefix; - private readonly int[] _cbSlotToBindingMap; - private readonly int[] _sbSlotToBindingMap; + private readonly SetBindingPair[] _cbSlotToBindingMap; + private readonly SetBindingPair[] _sbSlotToBindingMap; private uint _sbSlotWritten; private readonly Dictionary<int, int> _sbSlots; @@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation private struct TextureMeta { + public int Set; public int Binding; public bool AccurateType; public SamplerType Type; @@ -64,10 +65,10 @@ namespace Ryujinx.Graphics.Shader.Translation _stage = stage; _stagePrefix = GetShaderStagePrefix(stage); - _cbSlotToBindingMap = new int[18]; - _sbSlotToBindingMap = new int[16]; - _cbSlotToBindingMap.AsSpan().Fill(-1); - _sbSlotToBindingMap.AsSpan().Fill(-1); + _cbSlotToBindingMap = new SetBindingPair[18]; + _sbSlotToBindingMap = new SetBindingPair[16]; + _cbSlotToBindingMap.AsSpan().Fill(new(-1, -1)); + _sbSlotToBindingMap.AsSpan().Fill(new(-1, -1)); _sbSlots = new(); _sbSlotsReverse = new(); @@ -146,16 +147,16 @@ namespace Ryujinx.Graphics.Shader.Translation public int GetConstantBufferBinding(int slot) { - int binding = _cbSlotToBindingMap[slot]; - if (binding < 0) + SetBindingPair setAndBinding = _cbSlotToBindingMap[slot]; + if (setAndBinding.Binding < 0) { - binding = _gpuAccessor.CreateConstantBufferBinding(slot); - _cbSlotToBindingMap[slot] = binding; + setAndBinding = _gpuAccessor.CreateConstantBufferBinding(slot); + _cbSlotToBindingMap[slot] = setAndBinding; string slotNumber = slot.ToString(CultureInfo.InvariantCulture); - AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}"); + AddNewConstantBuffer(setAndBinding.SetIndex, setAndBinding.Binding, $"{_stagePrefix}_c{slotNumber}"); } - return binding; + return setAndBinding.Binding; } public bool TryGetStorageBufferBinding(int sbCbSlot, int sbCbOffset, bool write, out int binding) @@ -166,14 +167,14 @@ namespace Ryujinx.Graphics.Shader.Translation return false; } - binding = _sbSlotToBindingMap[slot]; + SetBindingPair setAndBinding = _sbSlotToBindingMap[slot]; - if (binding < 0) + if (setAndBinding.Binding < 0) { - binding = _gpuAccessor.CreateStorageBufferBinding(slot); - _sbSlotToBindingMap[slot] = binding; + setAndBinding = _gpuAccessor.CreateStorageBufferBinding(slot); + _sbSlotToBindingMap[slot] = setAndBinding; string slotNumber = slot.ToString(CultureInfo.InvariantCulture); - AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}"); + AddNewStorageBuffer(setAndBinding.SetIndex, setAndBinding.Binding, $"{_stagePrefix}_s{slotNumber}"); } if (write) @@ -181,6 +182,7 @@ namespace Ryujinx.Graphics.Shader.Translation _sbSlotWritten |= 1u << slot; } + binding = setAndBinding.Binding; return true; } @@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.Translation { for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++) { - if (_cbSlotToBindingMap[slot] == binding) + if (_cbSlotToBindingMap[slot].Binding == binding) { return true; } @@ -218,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.Translation return false; } - public int GetTextureOrImageBinding( + public SetBindingPair GetTextureOrImageBinding( Instruction inst, SamplerType type, TextureFormat format, @@ -240,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.Translation format = TextureFormat.Unknown; } - int binding = GetTextureOrImageBinding( + SetBindingPair setAndBinding = GetTextureOrImageBinding( cbufSlot, handle, arrayLength, @@ -255,10 +257,10 @@ namespace Ryujinx.Graphics.Shader.Translation _gpuAccessor.RegisterTexture(handle, cbufSlot); - return binding; + return setAndBinding; } - private int GetTextureOrImageBinding( + private SetBindingPair GetTextureOrImageBinding( int cbufSlot, int handle, int arrayLength, @@ -311,21 +313,38 @@ namespace Ryujinx.Graphics.Shader.Translation UsageFlags = usageFlags, }; + int setIndex; int binding; if (dict.TryGetValue(info, out var existingMeta)) { dict[info] = MergeTextureMeta(meta, existingMeta); + setIndex = existingMeta.Set; binding = existingMeta.Binding; } else { - bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer; + if (arrayLength > 1 && (setIndex = _gpuAccessor.CreateExtraSet()) >= 0) + { + // We reserved an "extra set" for the array. + // In this case the binding is always the first one (0). + // Using separate sets for array is better as we need to do less descriptor set updates. + + binding = 0; + } + else + { + bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer; + + SetBindingPair setAndBinding = isImage + ? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer) + : _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer); - binding = isImage - ? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer) - : _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer); + setIndex = setAndBinding.SetIndex; + binding = setAndBinding.Binding; + } + meta.Set = setIndex; meta.Binding = binding; dict.Add(info, meta); @@ -355,7 +374,7 @@ namespace Ryujinx.Graphics.Shader.Translation } var definition = new TextureDefinition( - isImage ? 3 : 2, + setIndex, binding, arrayLength, separate, @@ -373,11 +392,12 @@ namespace Ryujinx.Graphics.Shader.Translation Properties.AddOrUpdateTexture(definition); } - return binding; + return new SetBindingPair(setIndex, binding); } private static TextureMeta MergeTextureMeta(TextureMeta meta, TextureMeta existingMeta) { + meta.Set = existingMeta.Set; meta.Binding = existingMeta.Binding; meta.UsageFlags |= existingMeta.UsageFlags; @@ -440,11 +460,11 @@ namespace Ryujinx.Graphics.Shader.Translation for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++) { - int binding = _cbSlotToBindingMap[slot]; + SetBindingPair setAndBinding = _cbSlotToBindingMap[slot]; - if (binding >= 0 && _usedConstantBufferBindings.Contains(binding)) + if (setAndBinding.Binding >= 0 && _usedConstantBufferBindings.Contains(setAndBinding.Binding)) { - descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot); + descriptors[descriptorIndex++] = new BufferDescriptor(setAndBinding.SetIndex, setAndBinding.Binding, slot); } } @@ -464,13 +484,13 @@ namespace Ryujinx.Graphics.Shader.Translation foreach ((int key, int slot) in _sbSlots) { - int binding = _sbSlotToBindingMap[slot]; + SetBindingPair setAndBinding = _sbSlotToBindingMap[slot]; - if (binding >= 0) + if (setAndBinding.Binding >= 0) { (int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key); BufferUsageFlags flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None; - descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset, flags); + descriptors[descriptorIndex++] = new BufferDescriptor(setAndBinding.SetIndex, setAndBinding.Binding, slot, sbCbSlot, sbCbOffset, flags); } } @@ -507,6 +527,7 @@ namespace Ryujinx.Graphics.Shader.Translation } descriptors.Add(new TextureDescriptor( + meta.Set, meta.Binding, meta.Type, info.Format, @@ -527,6 +548,7 @@ namespace Ryujinx.Graphics.Shader.Translation } descriptors.Add(new TextureDescriptor( + meta.Set, meta.Binding, meta.Type, info.Format, @@ -587,24 +609,24 @@ namespace Ryujinx.Graphics.Shader.Translation return false; } - private void AddNewConstantBuffer(int binding, string name) + private void AddNewConstantBuffer(int setIndex, int binding, string name) { StructureType type = new(new[] { new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16), }); - Properties.AddOrUpdateConstantBuffer(new(BufferLayout.Std140, 0, binding, name, type)); + Properties.AddOrUpdateConstantBuffer(new(BufferLayout.Std140, setIndex, binding, name, type)); } - private void AddNewStorageBuffer(int binding, string name) + private void AddNewStorageBuffer(int setIndex, int binding, string name) { StructureType type = new(new[] { new StructureField(AggregateType.Array | AggregateType.U32, "data", 0), }); - Properties.AddOrUpdateStorageBuffer(new(BufferLayout.Std430, 1, binding, name, type)); + Properties.AddOrUpdateStorageBuffer(new(BufferLayout.Std430, setIndex, binding, name, type)); } public static string GetShaderStagePrefix(ShaderStage stage) diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceReservations.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceReservations.cs index d559f669..c89c4d0b 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ResourceReservations.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceReservations.cs @@ -11,6 +11,8 @@ namespace Ryujinx.Graphics.Shader.Translation public const int MaxVertexBufferTextures = 32; + private const int TextureSetIndex = 2; // TODO: Get from GPU accessor. + public int VertexInfoConstantBufferBinding { get; } public int VertexOutputStorageBufferBinding { get; } public int GeometryVertexOutputStorageBufferBinding { get; } @@ -163,6 +165,21 @@ namespace Ryujinx.Graphics.Shader.Translation return _vertexBufferTextureBaseBinding + vaLocation; } + public SetBindingPair GetVertexBufferTextureSetAndBinding(int vaLocation) + { + return new SetBindingPair(TextureSetIndex, GetVertexBufferTextureBinding(vaLocation)); + } + + public SetBindingPair GetIndexBufferTextureSetAndBinding() + { + return new SetBindingPair(TextureSetIndex, IndexBufferTextureBinding); + } + + public SetBindingPair GetTopologyRemapBufferTextureSetAndBinding() + { + return new SetBindingPair(TextureSetIndex, TopologyRemapBufferTextureBinding); + } + internal bool TryGetOffset(StorageKind storageKind, int location, int component, out int offset) { return _offsets.TryGetValue(new IoDefinition(storageKind, IoVariable.UserDefined, location, component), out offset); diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs index 072b4569..6ba8cb44 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs @@ -182,6 +182,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags, + texOp.Set, texOp.Binding, index, new[] { coordSize }, @@ -251,6 +252,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags, + texOp.Set, texOp.Binding, index, new[] { coordSize }, @@ -471,6 +473,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets), + texOp.Set, texOp.Binding, 1 << 3, // W component: i=0, j=0 new[] { dests[destIndex++] }, @@ -527,6 +530,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets), + texOp.Set, texOp.Binding, componentIndex, dests, @@ -573,6 +577,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags, + texOp.Set, texOp.Binding, index, new[] { texSizes[index] }, @@ -603,6 +608,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags, + texOp.Set, texOp.Binding, 0, new[] { lod }, @@ -633,6 +639,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texOp.Type, texOp.Format, texOp.Flags, + texOp.Set, texOp.Binding, index, new[] { texSizes[index] }, diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs index d71ada86..ddd2134d 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs @@ -54,6 +54,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { bool needsSextNorm = context.Definitions.IsAttributePackedRgb10A2Signed(location); + SetBindingPair setAndBinding = context.ResourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location); Operand temp = needsSextNorm ? Local() : dest; Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0); @@ -62,7 +63,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms SamplerType.TextureBuffer, TextureFormat.Unknown, TextureFlags.IntCoords, - context.ResourceManager.Reservations.GetVertexBufferTextureBinding(location), + setAndBinding.SetIndex, + setAndBinding.Binding, 1 << component, new[] { temp }, new[] { vertexElemOffset })); @@ -75,6 +77,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms } else { + SetBindingPair setAndBinding = context.ResourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location); Operand temp = component > 0 ? Local() : dest; Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component); @@ -83,7 +86,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms SamplerType.TextureBuffer, TextureFormat.Unknown, TextureFlags.IntCoords, - context.ResourceManager.Reservations.GetVertexBufferTextureBinding(location), + setAndBinding.SetIndex, + setAndBinding.Binding, 1, new[] { temp }, new[] { vertexElemOffset })); diff --git a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs index 10653558..59914736 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs @@ -412,8 +412,8 @@ namespace Ryujinx.Graphics.Shader.Translation if (Stage == ShaderStage.Vertex) { - int ibBinding = resourceManager.Reservations.IndexBufferTextureBinding; - TextureDefinition indexBuffer = new(2, ibBinding, "ib_data", SamplerType.TextureBuffer); + SetBindingPair ibSetAndBinding = resourceManager.Reservations.GetIndexBufferTextureSetAndBinding(); + TextureDefinition indexBuffer = new(ibSetAndBinding.SetIndex, ibSetAndBinding.Binding, "ib_data", SamplerType.TextureBuffer); resourceManager.Properties.AddOrUpdateTexture(indexBuffer); int inputMap = _program.AttributeUsage.UsedInputAttributes; @@ -421,8 +421,8 @@ namespace Ryujinx.Graphics.Shader.Translation while (inputMap != 0) { int location = BitOperations.TrailingZeroCount(inputMap); - int binding = resourceManager.Reservations.GetVertexBufferTextureBinding(location); - TextureDefinition vaBuffer = new(2, binding, $"vb_data{location}", SamplerType.TextureBuffer); + SetBindingPair setAndBinding = resourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location); + TextureDefinition vaBuffer = new(setAndBinding.SetIndex, setAndBinding.Binding, $"vb_data{location}", SamplerType.TextureBuffer); resourceManager.Properties.AddOrUpdateTexture(vaBuffer); inputMap &= ~(1 << location); @@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Shader.Translation } else if (Stage == ShaderStage.Geometry) { - int trbBinding = resourceManager.Reservations.TopologyRemapBufferTextureBinding; - TextureDefinition remapBuffer = new(2, trbBinding, "trb_data", SamplerType.TextureBuffer); + SetBindingPair trbSetAndBinding = resourceManager.Reservations.GetTopologyRemapBufferTextureSetAndBinding(); + TextureDefinition remapBuffer = new(trbSetAndBinding.SetIndex, trbSetAndBinding.Binding, "trb_data", SamplerType.TextureBuffer); resourceManager.Properties.AddOrUpdateTexture(remapBuffer); int geometryVbOutputSbBinding = resourceManager.Reservations.GeometryVertexOutputStorageBufferBinding; |
