mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-28 06:46:24 +02:00
Allow texture arrays to use separate descriptor sets on Vulkan (#6870)
* Report base and extra sets from the backend * Pass texture set index everywhere * Key textures using set and binding (rather than just binding) * Start using extra sets for array textures * Shader cache version bump * Separate new commands, some PR feedback * Introduce new manual descriptor set reservation method that prevents it from being used by something else while owned by an array * Move bind extra sets logic to new method * Should only use separate array is MaximumExtraSets is not zero * Format whitespace
This commit is contained in:
parent
4cc00bb4b1
commit
53d096e392
47 changed files with 996 additions and 262 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
4
src/Ryujinx.Graphics.Shader/SetBindingPair.cs
Normal file
4
src/Ryujinx.Graphics.Shader/SetBindingPair.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace Ryujinx.Graphics.Shader
|
||||
{
|
||||
public readonly record struct SetBindingPair(int SetIndex, int Binding);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) });
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = isImage
|
||||
? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer)
|
||||
: _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer);
|
||||
binding = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||
|
||||
SetBindingPair setAndBinding = 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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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] },
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue