diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-05-05 11:20:20 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-05 14:20:20 +0000 |
commit | aa021085cfab10ab63a7e6c2f9c9e29b4111525c (patch) | |
tree | bbf192b3c321110fa6abd6f8bcd7c429119daa93 /src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs | |
parent | 1f5d8818609a82df893167a8ec5bd6ccda406c61 (diff) |
Allow any shader SSBO constant buffer slot and offset (#2237)1.1.755
* Allow any shader SSBO constant buffer slot and offset
* Fix slot value passed to SetUsedStorageBuffer on fallback case
* Shader cache version
* Ensure that the storage buffer source constant buffer offset is word aligned
* Fix FirstBinding on GetUniformBufferDescriptors
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs index 22f5a671..ae60bcc6 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs @@ -125,6 +125,9 @@ namespace Ryujinx.Graphics.Shader.Translation private readonly Dictionary<TextureInfo, TextureMeta> _usedTextures; private readonly Dictionary<TextureInfo, TextureMeta> _usedImages; + private readonly Dictionary<int, int> _sbSlots; + private readonly Dictionary<int, int> _sbSlotsReverse; + private BufferDescriptor[] _cachedConstantBufferDescriptors; private BufferDescriptor[] _cachedStorageBufferDescriptors; private TextureDescriptor[] _cachedTextureDescriptors; @@ -152,6 +155,9 @@ namespace Ryujinx.Graphics.Shader.Translation _usedTextures = new Dictionary<TextureInfo, TextureMeta>(); _usedImages = new Dictionary<TextureInfo, TextureMeta>(); + + _sbSlots = new Dictionary<int, int>(); + _sbSlotsReverse = new Dictionary<int, int>(); } public ShaderConfig( @@ -770,9 +776,8 @@ namespace Ryujinx.Graphics.Shader.Translation usedMask |= (int)GpuAccessor.QueryConstantBufferUse(); } - return _cachedConstantBufferDescriptors = GetBufferDescriptors( + return _cachedConstantBufferDescriptors = GetUniformBufferDescriptors( usedMask, - 0, UsedFeatures.HasFlag(FeatureFlags.CbIndexing), out _firstConstantBufferBinding, GpuAccessor.QueryBindingConstantBuffer); @@ -785,7 +790,7 @@ namespace Ryujinx.Graphics.Shader.Translation return _cachedStorageBufferDescriptors; } - return _cachedStorageBufferDescriptors = GetBufferDescriptors( + return _cachedStorageBufferDescriptors = GetStorageBufferDescriptors( _usedStorageBuffers, _usedStorageBuffersWrite, true, @@ -793,7 +798,48 @@ namespace Ryujinx.Graphics.Shader.Translation GpuAccessor.QueryBindingStorageBuffer); } - private static BufferDescriptor[] GetBufferDescriptors( + private static BufferDescriptor[] GetUniformBufferDescriptors(int usedMask, bool isArray, out int firstBinding, Func<int, int> getBindingCallback) + { + firstBinding = 0; + int lastSlot = -1; + bool hasFirstBinding = false; + var descriptors = new BufferDescriptor[BitOperations.PopCount((uint)usedMask)]; + + for (int i = 0; i < descriptors.Length; i++) + { + int slot = BitOperations.TrailingZeroCount(usedMask); + + if (isArray) + { + // The next array entries also consumes bindings, even if they are unused. + for (int j = lastSlot + 1; j < slot; j++) + { + int binding = getBindingCallback(j); + + if (!hasFirstBinding) + { + firstBinding = binding; + hasFirstBinding = true; + } + } + } + + lastSlot = slot; + descriptors[i] = new BufferDescriptor(getBindingCallback(slot), slot); + + if (!hasFirstBinding) + { + firstBinding = descriptors[i].Binding; + hasFirstBinding = true; + } + + usedMask &= ~(1 << slot); + } + + return descriptors; + } + + private BufferDescriptor[] GetStorageBufferDescriptors( int usedMask, int writtenMask, bool isArray, @@ -827,7 +873,9 @@ namespace Ryujinx.Graphics.Shader.Translation lastSlot = slot; - descriptors[i] = new BufferDescriptor(getBindingCallback(slot), slot); + (int sbCbSlot, int sbCbOffset) = GetSbCbInfo(slot); + + descriptors[i] = new BufferDescriptor(getBindingCallback(slot), slot, sbCbSlot, sbCbOffset); if (!hasFirstBinding) { @@ -924,6 +972,40 @@ namespace Ryujinx.Graphics.Shader.Translation return FindDescriptorIndex(GetImageDescriptors(), texOp); } + public int GetSbSlot(byte sbCbSlot, ushort sbCbOffset) + { + int key = PackSbCbInfo(sbCbSlot, sbCbOffset); + + if (!_sbSlots.TryGetValue(key, out int slot)) + { + slot = _sbSlots.Count; + _sbSlots.Add(key, slot); + _sbSlotsReverse.Add(slot, key); + } + + return slot; + } + + public (int, int) GetSbCbInfo(int slot) + { + if (_sbSlotsReverse.TryGetValue(slot, out int key)) + { + return UnpackSbCbInfo(key); + } + + throw new ArgumentException($"Invalid slot {slot}.", nameof(slot)); + } + + private static int PackSbCbInfo(int sbCbSlot, int sbCbOffset) + { + return sbCbOffset | ((int)sbCbSlot << 16); + } + + private static (int, int) UnpackSbCbInfo(int key) + { + return ((byte)(key >> 16), (ushort)key); + } + public ShaderProgramInfo CreateProgramInfo(ShaderIdentification identification = ShaderIdentification.None) { return new ShaderProgramInfo( |