ResourceReservations.cs
1 using Ryujinx.Graphics.Shader.IntermediateRepresentation; 2 using Ryujinx.Graphics.Shader.StructuredIr; 3 using System.Collections.Generic; 4 using System.Numerics; 5 6 namespace Ryujinx.Graphics.Shader.Translation 7 { 8 public class ResourceReservations 9 { 10 public const int TfeBuffersCount = 4; 11 12 public const int MaxVertexBufferTextures = 32; 13 14 private const int TextureSetIndex = 2; // TODO: Get from GPU accessor. 15 16 public int VertexInfoConstantBufferBinding { get; } 17 public int VertexOutputStorageBufferBinding { get; } 18 public int GeometryVertexOutputStorageBufferBinding { get; } 19 public int GeometryIndexOutputStorageBufferBinding { get; } 20 public int IndexBufferTextureBinding { get; } 21 public int TopologyRemapBufferTextureBinding { get; } 22 23 public int ReservedConstantBuffers { get; } 24 public int ReservedStorageBuffers { get; } 25 public int ReservedTextures { get; } 26 public int ReservedImages { get; } 27 public int InputSizePerInvocation { get; } 28 public int OutputSizePerInvocation { get; } 29 public int OutputSizeInBytesPerInvocation => OutputSizePerInvocation * sizeof(uint); 30 31 private readonly int _tfeBufferSbBaseBinding; 32 private readonly int _vertexBufferTextureBaseBinding; 33 34 private readonly Dictionary<IoDefinition, int> _offsets; 35 internal IReadOnlyDictionary<IoDefinition, int> Offsets => _offsets; 36 37 internal ResourceReservations(bool isTransformFeedbackEmulated, bool vertexAsCompute) 38 { 39 // All stages reserves the first constant buffer binding for the support buffer. 40 ReservedConstantBuffers = 1; 41 ReservedStorageBuffers = 0; 42 ReservedTextures = 0; 43 ReservedImages = 0; 44 45 if (isTransformFeedbackEmulated) 46 { 47 // Transform feedback emulation currently always uses 4 storage buffers. 48 _tfeBufferSbBaseBinding = ReservedStorageBuffers; 49 ReservedStorageBuffers = TfeBuffersCount; 50 } 51 52 if (vertexAsCompute) 53 { 54 // One constant buffer reserved for vertex related state. 55 VertexInfoConstantBufferBinding = ReservedConstantBuffers++; 56 57 // One storage buffer for the output vertex data. 58 VertexOutputStorageBufferBinding = ReservedStorageBuffers++; 59 60 // One storage buffer for the output geometry vertex data. 61 GeometryVertexOutputStorageBufferBinding = ReservedStorageBuffers++; 62 63 // One storage buffer for the output geometry index data. 64 GeometryIndexOutputStorageBufferBinding = ReservedStorageBuffers++; 65 66 // Enough textures reserved for all vertex attributes, plus the index buffer. 67 IndexBufferTextureBinding = ReservedTextures; 68 TopologyRemapBufferTextureBinding = ReservedTextures + 1; 69 _vertexBufferTextureBaseBinding = ReservedTextures + 2; 70 ReservedTextures += 2 + MaxVertexBufferTextures; 71 } 72 } 73 74 internal ResourceReservations( 75 IGpuAccessor gpuAccessor, 76 bool isTransformFeedbackEmulated, 77 bool vertexAsCompute, 78 IoUsage? vacInput, 79 IoUsage vacOutput) : this(isTransformFeedbackEmulated, vertexAsCompute) 80 { 81 if (vertexAsCompute) 82 { 83 _offsets = new(); 84 85 if (vacInput.HasValue) 86 { 87 InputSizePerInvocation = FillIoOffsetMap(gpuAccessor, StorageKind.Input, vacInput.Value); 88 } 89 90 OutputSizePerInvocation = FillIoOffsetMap(gpuAccessor, StorageKind.Output, vacOutput); 91 } 92 } 93 94 private int FillIoOffsetMap(IGpuAccessor gpuAccessor, StorageKind storageKind, IoUsage vacUsage) 95 { 96 int offset = 0; 97 98 for (int c = 0; c < 4; c++) 99 { 100 _offsets.Add(new IoDefinition(storageKind, IoVariable.Position, 0, c), offset++); 101 } 102 103 _offsets.Add(new IoDefinition(storageKind, IoVariable.PointSize), offset++); 104 105 int clipDistancesWrittenMap = vacUsage.ClipDistancesWritten; 106 107 while (clipDistancesWrittenMap != 0) 108 { 109 int index = BitOperations.TrailingZeroCount(clipDistancesWrittenMap); 110 111 _offsets.Add(new IoDefinition(storageKind, IoVariable.ClipDistance, 0, index), offset++); 112 113 clipDistancesWrittenMap &= ~(1 << index); 114 } 115 116 if (vacUsage.UsesRtLayer) 117 { 118 _offsets.Add(new IoDefinition(storageKind, IoVariable.Layer), offset++); 119 } 120 121 if (vacUsage.UsesViewportIndex && gpuAccessor.QueryHostSupportsViewportIndexVertexTessellation()) 122 { 123 _offsets.Add(new IoDefinition(storageKind, IoVariable.VertexIndex), offset++); 124 } 125 126 if (vacUsage.UsesViewportMask && gpuAccessor.QueryHostSupportsViewportMask()) 127 { 128 _offsets.Add(new IoDefinition(storageKind, IoVariable.ViewportMask), offset++); 129 } 130 131 int usedDefinedMap = vacUsage.UserDefinedMap; 132 133 while (usedDefinedMap != 0) 134 { 135 int location = BitOperations.TrailingZeroCount(usedDefinedMap); 136 137 for (int c = 0; c < 4; c++) 138 { 139 _offsets.Add(new IoDefinition(storageKind, IoVariable.UserDefined, location, c), offset++); 140 } 141 142 usedDefinedMap &= ~(1 << location); 143 } 144 145 return offset; 146 } 147 148 internal static bool IsVectorOrArrayVariable(IoVariable variable) 149 { 150 return variable switch 151 { 152 IoVariable.ClipDistance or 153 IoVariable.Position => true, 154 _ => false, 155 }; 156 } 157 158 public int GetTfeBufferStorageBufferBinding(int bufferIndex) 159 { 160 return _tfeBufferSbBaseBinding + bufferIndex; 161 } 162 163 public int GetVertexBufferTextureBinding(int vaLocation) 164 { 165 return _vertexBufferTextureBaseBinding + vaLocation; 166 } 167 168 public SetBindingPair GetVertexBufferTextureSetAndBinding(int vaLocation) 169 { 170 return new SetBindingPair(TextureSetIndex, GetVertexBufferTextureBinding(vaLocation)); 171 } 172 173 public SetBindingPair GetIndexBufferTextureSetAndBinding() 174 { 175 return new SetBindingPair(TextureSetIndex, IndexBufferTextureBinding); 176 } 177 178 public SetBindingPair GetTopologyRemapBufferTextureSetAndBinding() 179 { 180 return new SetBindingPair(TextureSetIndex, TopologyRemapBufferTextureBinding); 181 } 182 183 internal bool TryGetOffset(StorageKind storageKind, int location, int component, out int offset) 184 { 185 return _offsets.TryGetValue(new IoDefinition(storageKind, IoVariable.UserDefined, location, component), out offset); 186 } 187 188 internal bool TryGetOffset(StorageKind storageKind, IoVariable ioVariable, int location, int component, out int offset) 189 { 190 return _offsets.TryGetValue(new IoDefinition(storageKind, ioVariable, location, component), out offset); 191 } 192 193 internal bool TryGetOffset(StorageKind storageKind, IoVariable ioVariable, int component, out int offset) 194 { 195 return _offsets.TryGetValue(new IoDefinition(storageKind, ioVariable, 0, component), out offset); 196 } 197 198 internal bool TryGetOffset(StorageKind storageKind, IoVariable ioVariable, out int offset) 199 { 200 return _offsets.TryGetValue(new IoDefinition(storageKind, ioVariable, 0, 0), out offset); 201 } 202 } 203 }