aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-05-20 16:19:26 -0300
committerGitHub <noreply@github.com>2023-05-20 16:19:26 -0300
commit402f05b8ef013807997589ecc0a8ff50267dcd23 (patch)
tree8e3b06c2ce3e3ccd4b443a4c68365251acc668fa /src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
parentfb27042e01b0fa110184673d436ec96ec8cf20c7 (diff)
Replace constant buffer access on shader with new Load instruction (#4646)1.1.811
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
new file mode 100644
index 00000000..b31790d3
--- /dev/null
+++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
@@ -0,0 +1,126 @@
+using Ryujinx.Graphics.Shader.StructuredIr;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace Ryujinx.Graphics.Shader.Translation
+{
+ class ResourceManager
+ {
+ private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
+
+ private readonly IGpuAccessor _gpuAccessor;
+ private readonly ShaderProperties _properties;
+ private readonly string _stagePrefix;
+
+ private readonly int[] _cbSlotToBindingMap;
+
+ private readonly HashSet<int> _usedConstantBufferBindings;
+
+ public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties)
+ {
+ _gpuAccessor = gpuAccessor;
+ _properties = properties;
+ _stagePrefix = GetShaderStagePrefix(stage);
+
+ _cbSlotToBindingMap = new int[18];
+ _cbSlotToBindingMap.AsSpan().Fill(-1);
+
+ _usedConstantBufferBindings = new HashSet<int>();
+
+ properties.AddConstantBuffer(0, new BufferDefinition(BufferLayout.Std140, 0, 0, "support_buffer", SupportBuffer.GetStructureType()));
+ }
+
+ public int GetConstantBufferBinding(int slot)
+ {
+ int binding = _cbSlotToBindingMap[slot];
+ if (binding < 0)
+ {
+ binding = _gpuAccessor.QueryBindingConstantBuffer(slot);
+ _cbSlotToBindingMap[slot] = binding;
+ string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
+ AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}");
+ }
+
+ return binding;
+ }
+
+ public bool TryGetConstantBufferSlot(int binding, out int slot)
+ {
+ for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
+ {
+ if (_cbSlotToBindingMap[slot] == binding)
+ {
+ return true;
+ }
+ }
+
+ slot = 0;
+ return false;
+ }
+
+ public void SetUsedConstantBufferBinding(int binding)
+ {
+ _usedConstantBufferBindings.Add(binding);
+ }
+
+ public BufferDescriptor[] GetConstantBufferDescriptors()
+ {
+ var descriptors = new BufferDescriptor[_usedConstantBufferBindings.Count];
+
+ int descriptorIndex = 0;
+
+ for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
+ {
+ int binding = _cbSlotToBindingMap[slot];
+
+ if (binding >= 0 && _usedConstantBufferBindings.Contains(binding))
+ {
+ descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot);
+ }
+ }
+
+ if (descriptors.Length != descriptorIndex)
+ {
+ Array.Resize(ref descriptors, descriptorIndex);
+ }
+
+ return descriptors;
+ }
+
+ private void AddNewConstantBuffer(int binding, string name)
+ {
+ StructureType type = new StructureType(new[]
+ {
+ new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16)
+ });
+
+ _properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type));
+ }
+
+ public void InheritFrom(ResourceManager other)
+ {
+ for (int i = 0; i < other._cbSlotToBindingMap.Length; i++)
+ {
+ int binding = other._cbSlotToBindingMap[i];
+
+ if (binding >= 0)
+ {
+ _cbSlotToBindingMap[i] = binding;
+ }
+ }
+ }
+
+ public static string GetShaderStagePrefix(ShaderStage stage)
+ {
+ uint index = (uint)stage;
+
+ if (index >= _stagePrefixes.Length)
+ {
+ return "invalid";
+ }
+
+ return _stagePrefixes[index];
+ }
+ }
+} \ No newline at end of file