ResourceManager.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using Ryujinx.Graphics.Shader.StructuredIr;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. namespace Ryujinx.Graphics.Shader.Translation
  6. {
  7. class ResourceManager
  8. {
  9. private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
  10. private readonly IGpuAccessor _gpuAccessor;
  11. private readonly ShaderProperties _properties;
  12. private readonly string _stagePrefix;
  13. private readonly int[] _cbSlotToBindingMap;
  14. private readonly HashSet<int> _usedConstantBufferBindings;
  15. public ShaderProperties Properties => _properties;
  16. public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties)
  17. {
  18. _gpuAccessor = gpuAccessor;
  19. _properties = properties;
  20. _stagePrefix = GetShaderStagePrefix(stage);
  21. _cbSlotToBindingMap = new int[18];
  22. _cbSlotToBindingMap.AsSpan().Fill(-1);
  23. _usedConstantBufferBindings = new HashSet<int>();
  24. properties.AddConstantBuffer(0, new BufferDefinition(BufferLayout.Std140, 0, 0, "support_buffer", SupportBuffer.GetStructureType()));
  25. }
  26. public int GetConstantBufferBinding(int slot)
  27. {
  28. int binding = _cbSlotToBindingMap[slot];
  29. if (binding < 0)
  30. {
  31. binding = _gpuAccessor.QueryBindingConstantBuffer(slot);
  32. _cbSlotToBindingMap[slot] = binding;
  33. string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
  34. AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}");
  35. }
  36. return binding;
  37. }
  38. public bool TryGetConstantBufferSlot(int binding, out int slot)
  39. {
  40. for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
  41. {
  42. if (_cbSlotToBindingMap[slot] == binding)
  43. {
  44. return true;
  45. }
  46. }
  47. slot = 0;
  48. return false;
  49. }
  50. public void SetUsedConstantBufferBinding(int binding)
  51. {
  52. _usedConstantBufferBindings.Add(binding);
  53. }
  54. public BufferDescriptor[] GetConstantBufferDescriptors()
  55. {
  56. var descriptors = new BufferDescriptor[_usedConstantBufferBindings.Count];
  57. int descriptorIndex = 0;
  58. for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
  59. {
  60. int binding = _cbSlotToBindingMap[slot];
  61. if (binding >= 0 && _usedConstantBufferBindings.Contains(binding))
  62. {
  63. descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot);
  64. }
  65. }
  66. if (descriptors.Length != descriptorIndex)
  67. {
  68. Array.Resize(ref descriptors, descriptorIndex);
  69. }
  70. return descriptors;
  71. }
  72. private void AddNewConstantBuffer(int binding, string name)
  73. {
  74. StructureType type = new StructureType(new[]
  75. {
  76. new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16)
  77. });
  78. _properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type));
  79. }
  80. public static string GetShaderStagePrefix(ShaderStage stage)
  81. {
  82. uint index = (uint)stage;
  83. if (index >= _stagePrefixes.Length)
  84. {
  85. return "invalid";
  86. }
  87. return _stagePrefixes[index];
  88. }
  89. }
  90. }