Report base and extra sets from the backend

This commit is contained in:
Gabriel A 2024-05-24 17:32:53 -03:00
commit f83a4739ce
9 changed files with 141 additions and 36 deletions

View file

@ -51,6 +51,13 @@ namespace Ryujinx.Graphics.GAL
public readonly bool SupportsIndirectParameters; public readonly bool SupportsIndirectParameters;
public readonly bool SupportsDepthClipControl; public readonly bool SupportsDepthClipControl;
public readonly int UniformBufferSetIndex;
public readonly int StorageBufferSetIndex;
public readonly int TextureSetIndex;
public readonly int ImageSetIndex;
public readonly int ExtraSetBaseIndex;
public readonly int MaximumExtraSets;
public readonly uint MaximumUniformBuffersPerStage; public readonly uint MaximumUniformBuffersPerStage;
public readonly uint MaximumStorageBuffersPerStage; public readonly uint MaximumStorageBuffersPerStage;
public readonly uint MaximumTexturesPerStage; public readonly uint MaximumTexturesPerStage;
@ -109,6 +116,12 @@ namespace Ryujinx.Graphics.GAL
bool supportsViewportSwizzle, bool supportsViewportSwizzle,
bool supportsIndirectParameters, bool supportsIndirectParameters,
bool supportsDepthClipControl, bool supportsDepthClipControl,
int uniformBufferSetIndex,
int storageBufferSetIndex,
int textureSetIndex,
int imageSetIndex,
int extraSetBaseIndex,
int maximumExtraSets,
uint maximumUniformBuffersPerStage, uint maximumUniformBuffersPerStage,
uint maximumStorageBuffersPerStage, uint maximumStorageBuffersPerStage,
uint maximumTexturesPerStage, uint maximumTexturesPerStage,
@ -164,6 +177,12 @@ namespace Ryujinx.Graphics.GAL
SupportsViewportSwizzle = supportsViewportSwizzle; SupportsViewportSwizzle = supportsViewportSwizzle;
SupportsIndirectParameters = supportsIndirectParameters; SupportsIndirectParameters = supportsIndirectParameters;
SupportsDepthClipControl = supportsDepthClipControl; SupportsDepthClipControl = supportsDepthClipControl;
UniformBufferSetIndex = uniformBufferSetIndex;
StorageBufferSetIndex = storageBufferSetIndex;
TextureSetIndex = textureSetIndex;
ImageSetIndex = imageSetIndex;
ExtraSetBaseIndex = extraSetBaseIndex;
MaximumExtraSets = maximumExtraSets;
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage; MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage; MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
MaximumTexturesPerStage = maximumTexturesPerStage; MaximumTexturesPerStage = maximumTexturesPerStage;

View file

@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
_reservedImages = rrc.ReservedImages; _reservedImages = rrc.ReservedImages;
} }
public int CreateConstantBufferBinding(int index) public SetBindingPair CreateConstantBufferBinding(int index)
{ {
int binding; int binding;
@ -64,10 +64,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
binding = _resourceCounts.UniformBuffersCount++; binding = _resourceCounts.UniformBuffersCount++;
} }
return binding + _reservedConstantBuffers; return new SetBindingPair(_context.Capabilities.UniformBufferSetIndex, binding + _reservedConstantBuffers);
} }
public int CreateImageBinding(int count, bool isBuffer) public SetBindingPair CreateImageBinding(int count, bool isBuffer)
{ {
int binding; int binding;
@ -96,10 +96,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
_resourceCounts.ImagesCount += count; _resourceCounts.ImagesCount += count;
} }
return binding + _reservedImages; return new SetBindingPair(_context.Capabilities.ImageSetIndex, binding + _reservedImages);
} }
public int CreateStorageBufferBinding(int index) public SetBindingPair CreateStorageBufferBinding(int index)
{ {
int binding; int binding;
@ -112,10 +112,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
binding = _resourceCounts.StorageBuffersCount++; binding = _resourceCounts.StorageBuffersCount++;
} }
return binding + _reservedStorageBuffers; return new SetBindingPair(_context.Capabilities.StorageBufferSetIndex, binding + _reservedStorageBuffers);
} }
public int CreateTextureBinding(int count, bool isBuffer) public SetBindingPair CreateTextureBinding(int count, bool isBuffer)
{ {
int binding; int binding;
@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
_resourceCounts.TexturesCount += count; _resourceCounts.TexturesCount += count;
} }
return binding + _reservedTextures; return new SetBindingPair(_context.Capabilities.TextureSetIndex, binding + _reservedTextures);
} }
private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName) private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName)
@ -183,6 +183,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
return maxPerStage * Constants.ShaderStages; return maxPerStage * Constants.ShaderStages;
} }
public int CreateExtraSet()
{
if (_resourceCounts.SetsCount >= _context.Capabilities.MaximumExtraSets)
{
return -1;
}
return _context.Capabilities.ExtraSetBaseIndex + _resourceCounts.SetsCount++;
}
public int QueryHostGatherBiasPrecision() => _context.Capabilities.GatherBiasPrecision; public int QueryHostGatherBiasPrecision() => _context.Capabilities.GatherBiasPrecision;
public bool QueryHostReducedPrecision() => _context.Capabilities.ReduceShaderPrecision; public bool QueryHostReducedPrecision() => _context.Capabilities.ReduceShaderPrecision;

View file

@ -24,5 +24,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Total of images used by the shaders. /// Total of images used by the shaders.
/// </summary> /// </summary>
public int ImagesCount; public int ImagesCount;
/// <summary>
/// Total of extra sets used by the shaders.
/// </summary>
public int SetsCount;
} }
} }

View file

@ -187,6 +187,12 @@ namespace Ryujinx.Graphics.OpenGL
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
supportsDepthClipControl: true, supportsDepthClipControl: true,
uniformBufferSetIndex: 0,
storageBufferSetIndex: 1,
textureSetIndex: 2,
imageSetIndex: 3,
extraSetBaseIndex: 0,
maximumExtraSets: 0,
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver? maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
maximumStorageBuffersPerStage: 16, maximumStorageBuffersPerStage: 16,
maximumTexturesPerStage: 32, maximumTexturesPerStage: 32,

View file

@ -1,4 +1,4 @@
using Ryujinx.Graphics.Shader.CodeGen; using Ryujinx.Graphics.Shader.CodeGen;
using System; using System;
namespace Ryujinx.Graphics.Shader namespace Ryujinx.Graphics.Shader
@ -27,34 +27,43 @@ namespace Ryujinx.Graphics.Shader
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize); ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
/// <summary> /// <summary>
/// Queries the binding number of a constant buffer. /// Gets the binding number of a constant buffer.
/// </summary> /// </summary>
/// <param name="index">Constant buffer index</param> /// <param name="index">Constant buffer index</param>
/// <returns>Binding number</returns> /// <returns>Binding number</returns>
int CreateConstantBufferBinding(int index); SetBindingPair CreateConstantBufferBinding(int index);
/// <summary> /// <summary>
/// Queries the binding number of an image. /// Gets the binding number of an image.
/// </summary> /// </summary>
/// <param name="count">For array of images, the number of elements of the array, otherwise it should be 1</param> /// <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> /// <param name="isBuffer">Indicates if the image is a buffer image</param>
/// <returns>Binding number</returns> /// <returns>Binding number</returns>
int CreateImageBinding(int count, bool isBuffer); SetBindingPair CreateImageBinding(int count, bool isBuffer);
/// <summary> /// <summary>
/// Queries the binding number of a storage buffer. /// Gets the binding number of a storage buffer.
/// </summary> /// </summary>
/// <param name="index">Storage buffer index</param> /// <param name="index">Storage buffer index</param>
/// <returns>Binding number</returns> /// <returns>Binding number</returns>
int CreateStorageBufferBinding(int index); SetBindingPair CreateStorageBufferBinding(int index);
/// <summary> /// <summary>
/// Queries the binding number of a texture. /// Gets the binding number of a texture.
/// </summary> /// </summary>
/// <param name="count">For array of textures, the number of elements of the array, otherwise it should be 1</param> /// <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> /// <param name="isBuffer">Indicates if the texture is a buffer texture</param>
/// <returns>Binding number</returns> /// <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> /// <summary>
/// Queries Local Size X for compute shaders. /// Queries Local Size X for compute shaders.

View file

@ -0,0 +1,41 @@
using System;
namespace Ryujinx.Graphics.Shader
{
public readonly struct SetBindingPair : IEquatable<SetBindingPair>
{
public readonly int SetIndex;
public readonly int Binding;
public SetBindingPair(int setIndex, int binding)
{
SetIndex = setIndex;
Binding = binding;
}
public override bool Equals(object obj)
{
return obj is SetBindingPair other && Equals(other);
}
public bool Equals(SetBindingPair other)
{
return SetIndex == other.SetIndex && Binding == other.Binding;
}
public override int GetHashCode()
{
return (((ulong)(uint)SetIndex << 32) | (uint)Binding).GetHashCode();
}
public static bool operator ==(SetBindingPair left, SetBindingPair right)
{
return left.Equals(right);
}
public static bool operator !=(SetBindingPair left, SetBindingPair right)
{
return !(left == right);
}
}
}

View file

@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private struct TextureMeta private struct TextureMeta
{ {
public int Set;
public int Binding; public int Binding;
public bool AccurateType; public bool AccurateType;
public SamplerType Type; public SamplerType Type;
@ -149,10 +150,11 @@ namespace Ryujinx.Graphics.Shader.Translation
int binding = _cbSlotToBindingMap[slot]; int binding = _cbSlotToBindingMap[slot];
if (binding < 0) if (binding < 0)
{ {
binding = _gpuAccessor.CreateConstantBufferBinding(slot); SetBindingPair setAndBinding = _gpuAccessor.CreateConstantBufferBinding(slot);
binding = setAndBinding.Binding;
_cbSlotToBindingMap[slot] = binding; _cbSlotToBindingMap[slot] = binding;
string slotNumber = slot.ToString(CultureInfo.InvariantCulture); string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}"); AddNewConstantBuffer(setAndBinding.SetIndex, binding, $"{_stagePrefix}_c{slotNumber}");
} }
return binding; return binding;
@ -170,10 +172,11 @@ namespace Ryujinx.Graphics.Shader.Translation
if (binding < 0) if (binding < 0)
{ {
binding = _gpuAccessor.CreateStorageBufferBinding(slot); SetBindingPair setAndBinding = _gpuAccessor.CreateStorageBufferBinding(slot);
binding = setAndBinding.Binding;
_sbSlotToBindingMap[slot] = binding; _sbSlotToBindingMap[slot] = binding;
string slotNumber = slot.ToString(CultureInfo.InvariantCulture); string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}"); AddNewStorageBuffer(setAndBinding.SetIndex, binding, $"{_stagePrefix}_s{slotNumber}");
} }
if (write) if (write)
@ -311,21 +314,26 @@ namespace Ryujinx.Graphics.Shader.Translation
UsageFlags = usageFlags, UsageFlags = usageFlags,
}; };
int setIndex;
int binding; int binding;
if (dict.TryGetValue(info, out var existingMeta)) if (dict.TryGetValue(info, out var existingMeta))
{ {
dict[info] = MergeTextureMeta(meta, existingMeta); dict[info] = MergeTextureMeta(meta, existingMeta);
setIndex = existingMeta.Set;
binding = existingMeta.Binding; binding = existingMeta.Binding;
} }
else else
{ {
bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer; bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer;
binding = isImage SetBindingPair setAndBinding = isImage
? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer) ? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer)
: _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer); : _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer);
setIndex = setAndBinding.SetIndex;
binding = setAndBinding.Binding;
meta.Set = setIndex;
meta.Binding = binding; meta.Binding = binding;
dict.Add(info, meta); dict.Add(info, meta);
@ -355,7 +363,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
var definition = new TextureDefinition( var definition = new TextureDefinition(
isImage ? 3 : 2, setIndex,
binding, binding,
arrayLength, arrayLength,
separate, separate,
@ -378,6 +386,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private static TextureMeta MergeTextureMeta(TextureMeta meta, TextureMeta existingMeta) private static TextureMeta MergeTextureMeta(TextureMeta meta, TextureMeta existingMeta)
{ {
meta.Set = existingMeta.Set;
meta.Binding = existingMeta.Binding; meta.Binding = existingMeta.Binding;
meta.UsageFlags |= existingMeta.UsageFlags; meta.UsageFlags |= existingMeta.UsageFlags;
@ -587,24 +596,24 @@ namespace Ryujinx.Graphics.Shader.Translation
return false; return false;
} }
private void AddNewConstantBuffer(int binding, string name) private void AddNewConstantBuffer(int setIndex, int binding, string name)
{ {
StructureType type = new(new[] StructureType type = new(new[]
{ {
new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16), 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[] StructureType type = new(new[]
{ {
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0), 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) public static string GetShaderStagePrefix(ShaderStage stage)

View file

@ -728,6 +728,12 @@ namespace Ryujinx.Graphics.Vulkan
supportsViewportSwizzle: false, supportsViewportSwizzle: false,
supportsIndirectParameters: true, supportsIndirectParameters: true,
supportsDepthClipControl: Capabilities.SupportsDepthClipControl, supportsDepthClipControl: Capabilities.SupportsDepthClipControl,
uniformBufferSetIndex: PipelineBase.UniformSetIndex,
storageBufferSetIndex: PipelineBase.StorageSetIndex,
textureSetIndex: PipelineBase.TextureSetIndex,
imageSetIndex: PipelineBase.ImageSetIndex,
extraSetBaseIndex: PipelineBase.DescriptorSetLayouts,
maximumExtraSets: Math.Max(0, (int)limits.MaxBoundDescriptorSets - PipelineBase.DescriptorSetLayouts),
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage, maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage, maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
maximumTexturesPerStage: Constants.MaxTexturesPerStage, maximumTexturesPerStage: Constants.MaxTexturesPerStage,

View file

@ -1,4 +1,4 @@
using CommandLine; using CommandLine;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
@ -25,32 +25,32 @@ namespace Ryujinx.ShaderTools
_imagesCount = 0; _imagesCount = 0;
} }
public int CreateConstantBufferBinding(int index) public SetBindingPair CreateConstantBufferBinding(int index)
{ {
return index + 1; return new SetBindingPair(0, index + 1);
} }
public int CreateImageBinding(int count, bool isBuffer) public SetBindingPair CreateImageBinding(int count, bool isBuffer)
{ {
int binding = _imagesCount; int binding = _imagesCount;
_imagesCount += count; _imagesCount += count;
return binding; return new SetBindingPair(3, binding);
} }
public int CreateStorageBufferBinding(int index) public SetBindingPair CreateStorageBufferBinding(int index)
{ {
return index; return new SetBindingPair(1, index);
} }
public int CreateTextureBinding(int count, bool isBuffer) public SetBindingPair CreateTextureBinding(int count, bool isBuffer)
{ {
int binding = _texturesCount; int binding = _texturesCount;
_texturesCount += count; _texturesCount += count;
return binding; return new SetBindingPair(2, binding);
} }
public ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize) public ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize)