diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-06-03 20:12:18 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-03 20:12:18 -0300 |
commit | 21c9ac6240a3db3300143d1d0dd4a1070d4f576f (patch) | |
tree | 1d3fbafa1861368efe7cf8c923752cb0b621f717 /src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs | |
parent | 81c9052847f1aa4a70010fefa8e6ee38b5ace612 (diff) |
Implement shader storage buffer operations using new Load/Store instructions (#4993)1.1.861
* Implement storage buffer operations using new Load/Store instruction
* Extend GenerateMultiTargetStorageOp to also match access with constant offset, and log and comments
* Remove now unused code
* Catch more complex cases of global memory usage
* Shader cache version bump
* Extend global access elimination to work with more shared memory cases
* Change alignment requirement from 16 bytes to 8 bytes, handle cases where we need more than 16 storage buffers
* Tweak preferencing to catch more cases
* Enable CB0 elimination even when host storage buffer alignment is > 16 (for Intel)
* Fix storage buffer bindings
* Simplify some code
* Shader cache version bump
* Fix typo
* Extend global memory elimination to handle shared memory with multiple possible offsets and local memory
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs index a2cfbe22..2d19a5a7 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs @@ -14,6 +14,11 @@ namespace Ryujinx.Graphics.Shader.Translation private readonly string _stagePrefix; private readonly int[] _cbSlotToBindingMap; + private readonly int[] _sbSlotToBindingMap; + private uint _sbSlotWritten; + + private readonly Dictionary<int, int> _sbSlots; + private readonly Dictionary<int, int> _sbSlotsReverse; private readonly HashSet<int> _usedConstantBufferBindings; @@ -26,7 +31,12 @@ namespace Ryujinx.Graphics.Shader.Translation _stagePrefix = GetShaderStagePrefix(stage); _cbSlotToBindingMap = new int[18]; + _sbSlotToBindingMap = new int[16]; _cbSlotToBindingMap.AsSpan().Fill(-1); + _sbSlotToBindingMap.AsSpan().Fill(-1); + + _sbSlots = new Dictionary<int, int>(); + _sbSlotsReverse = new Dictionary<int, int>(); _usedConstantBufferBindings = new HashSet<int>(); @@ -47,6 +57,52 @@ namespace Ryujinx.Graphics.Shader.Translation return binding; } + public bool TryGetStorageBufferBinding(int sbCbSlot, int sbCbOffset, bool write, out int binding) + { + if (!TryGetSbSlot((byte)sbCbSlot, (ushort)sbCbOffset, out int slot)) + { + binding = 0; + return false; + } + + binding = _sbSlotToBindingMap[slot]; + + if (binding < 0) + { + binding = _gpuAccessor.QueryBindingStorageBuffer(slot); + _sbSlotToBindingMap[slot] = binding; + string slotNumber = slot.ToString(CultureInfo.InvariantCulture); + AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}"); + } + + if (write) + { + _sbSlotWritten |= 1u << slot; + } + + return true; + } + + private bool TryGetSbSlot(byte sbCbSlot, ushort sbCbOffset, out int slot) + { + int key = PackSbCbInfo(sbCbSlot, sbCbOffset); + + if (!_sbSlots.TryGetValue(key, out slot)) + { + slot = _sbSlots.Count; + + if (slot >= _sbSlotToBindingMap.Length) + { + return false; + } + + _sbSlots.Add(key, slot); + _sbSlotsReverse.Add(slot, key); + } + + return true; + } + public bool TryGetConstantBufferSlot(int binding, out int slot) { for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++) @@ -90,6 +146,34 @@ namespace Ryujinx.Graphics.Shader.Translation return descriptors; } + public BufferDescriptor[] GetStorageBufferDescriptors() + { + var descriptors = new BufferDescriptor[_sbSlots.Count]; + + int descriptorIndex = 0; + + foreach ((int key, int slot) in _sbSlots) + { + int binding = _sbSlotToBindingMap[slot]; + + if (binding >= 0) + { + (int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key); + descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset) + { + Flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None + }; + } + } + + if (descriptors.Length != descriptorIndex) + { + Array.Resize(ref descriptors, descriptorIndex); + } + + return descriptors; + } + private void AddNewConstantBuffer(int binding, string name) { StructureType type = new StructureType(new[] @@ -100,6 +184,16 @@ namespace Ryujinx.Graphics.Shader.Translation _properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type)); } + private void AddNewStorageBuffer(int binding, string name) + { + StructureType type = new StructureType(new[] + { + new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) + }); + + _properties.AddStorageBuffer(binding, new BufferDefinition(BufferLayout.Std430, 1, binding, name, type)); + } + public static string GetShaderStagePrefix(ShaderStage stage) { uint index = (uint)stage; @@ -111,5 +205,15 @@ namespace Ryujinx.Graphics.Shader.Translation return _stagePrefixes[index]; } + + 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); + } } }
\ No newline at end of file |