GpuAccessorBase.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Graphics.GAL;
  3. using Ryujinx.Graphics.Gpu.Engine.Threed;
  4. using Ryujinx.Graphics.Gpu.Image;
  5. using Ryujinx.Graphics.Shader;
  6. using Ryujinx.Graphics.Shader.Translation;
  7. using System;
  8. namespace Ryujinx.Graphics.Gpu.Shader
  9. {
  10. /// <summary>
  11. /// GPU accessor.
  12. /// </summary>
  13. class GpuAccessorBase
  14. {
  15. private readonly GpuContext _context;
  16. private readonly ResourceCounts _resourceCounts;
  17. private readonly int _stageIndex;
  18. private readonly int[] _constantBufferBindings;
  19. /// <summary>
  20. /// Creates a new GPU accessor.
  21. /// </summary>
  22. /// <param name="context">GPU context</param>
  23. public GpuAccessorBase(GpuContext context, ResourceCounts resourceCounts, int stageIndex)
  24. {
  25. _context = context;
  26. _resourceCounts = resourceCounts;
  27. _stageIndex = stageIndex;
  28. if (context.Capabilities.Api != TargetApi.Vulkan)
  29. {
  30. _constantBufferBindings = new int[Constants.TotalGpUniformBuffers];
  31. _constantBufferBindings.AsSpan().Fill(-1);
  32. }
  33. }
  34. public int QueryBindingConstantBuffer(int index)
  35. {
  36. if (_context.Capabilities.Api == TargetApi.Vulkan)
  37. {
  38. // We need to start counting from 1 since binding 0 is reserved for the support uniform buffer.
  39. return GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer") + 1;
  40. }
  41. else
  42. {
  43. int binding = _constantBufferBindings[index];
  44. if (binding < 0)
  45. {
  46. binding = _resourceCounts.UniformBuffersCount++;
  47. _constantBufferBindings[index] = binding;
  48. }
  49. return binding;
  50. }
  51. }
  52. public int QueryBindingStorageBuffer(int index)
  53. {
  54. if (_context.Capabilities.Api == TargetApi.Vulkan)
  55. {
  56. return GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer");
  57. }
  58. else
  59. {
  60. return _resourceCounts.StorageBuffersCount++;
  61. }
  62. }
  63. public int QueryBindingTexture(int index, bool isBuffer)
  64. {
  65. if (_context.Capabilities.Api == TargetApi.Vulkan)
  66. {
  67. if (isBuffer)
  68. {
  69. index += (int)_context.Capabilities.MaximumTexturesPerStage;
  70. }
  71. return GetBindingFromIndex(index, _context.Capabilities.MaximumTexturesPerStage * 2, "Texture");
  72. }
  73. else
  74. {
  75. return _resourceCounts.TexturesCount++;
  76. }
  77. }
  78. public int QueryBindingImage(int index, bool isBuffer)
  79. {
  80. if (_context.Capabilities.Api == TargetApi.Vulkan)
  81. {
  82. if (isBuffer)
  83. {
  84. index += (int)_context.Capabilities.MaximumImagesPerStage;
  85. }
  86. return GetBindingFromIndex(index, _context.Capabilities.MaximumImagesPerStage * 2, "Image");
  87. }
  88. else
  89. {
  90. return _resourceCounts.ImagesCount++;
  91. }
  92. }
  93. private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName)
  94. {
  95. if ((uint)index >= maxPerStage)
  96. {
  97. Logger.Error?.Print(LogClass.Gpu, $"{resourceName} index {index} exceeds per stage limit of {maxPerStage}.");
  98. }
  99. return GetStageIndex() * (int)maxPerStage + index;
  100. }
  101. private int GetStageIndex()
  102. {
  103. // This is just a simple remapping to ensure that most frequently used shader stages
  104. // have the lowest binding numbers.
  105. // This is useful because if we need to run on a system with a low limit on the bindings,
  106. // then we can still get most games working as the most common shaders will have low binding numbers.
  107. return _stageIndex switch
  108. {
  109. 4 => 1, // Fragment
  110. 3 => 2, // Geometry
  111. 1 => 3, // Tessellation control
  112. 2 => 4, // Tessellation evaluation
  113. _ => 0 // Vertex/Compute
  114. };
  115. }
  116. public int QueryHostGatherBiasPrecision() => _context.Capabilities.GatherBiasPrecision;
  117. public bool QueryHostReducedPrecision() => _context.Capabilities.ReduceShaderPrecision;
  118. public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
  119. public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
  120. public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
  121. public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
  122. public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
  123. public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
  124. public bool QueryHostSupportsGeometryShader() => _context.Capabilities.SupportsGeometryShader;
  125. public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
  126. public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
  127. public bool QueryHostSupportsLayerVertexTessellation() => _context.Capabilities.SupportsLayerVertexTessellation;
  128. public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset;
  129. public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
  130. public bool QueryHostSupportsSnormBufferTextureFormat() => _context.Capabilities.SupportsSnormBufferTextureFormat;
  131. public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
  132. public bool QueryHostSupportsViewportIndexVertexTessellation() => _context.Capabilities.SupportsViewportIndexVertexTessellation;
  133. public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;
  134. /// <summary>
  135. /// Converts a packed Maxwell texture format to the shader translator texture format.
  136. /// </summary>
  137. /// <param name="format">Packed maxwell format</param>
  138. /// <param name="formatSrgb">Indicates if the format is sRGB</param>
  139. /// <returns>Shader translator texture format</returns>
  140. protected static TextureFormat ConvertToTextureFormat(uint format, bool formatSrgb)
  141. {
  142. if (!FormatTable.TryGetTextureFormat(format, formatSrgb, out FormatInfo formatInfo))
  143. {
  144. return TextureFormat.Unknown;
  145. }
  146. return formatInfo.Format switch
  147. {
  148. Format.R8Unorm => TextureFormat.R8Unorm,
  149. Format.R8Snorm => TextureFormat.R8Snorm,
  150. Format.R8Uint => TextureFormat.R8Uint,
  151. Format.R8Sint => TextureFormat.R8Sint,
  152. Format.R16Float => TextureFormat.R16Float,
  153. Format.R16Unorm => TextureFormat.R16Unorm,
  154. Format.R16Snorm => TextureFormat.R16Snorm,
  155. Format.R16Uint => TextureFormat.R16Uint,
  156. Format.R16Sint => TextureFormat.R16Sint,
  157. Format.R32Float => TextureFormat.R32Float,
  158. Format.R32Uint => TextureFormat.R32Uint,
  159. Format.R32Sint => TextureFormat.R32Sint,
  160. Format.R8G8Unorm => TextureFormat.R8G8Unorm,
  161. Format.R8G8Snorm => TextureFormat.R8G8Snorm,
  162. Format.R8G8Uint => TextureFormat.R8G8Uint,
  163. Format.R8G8Sint => TextureFormat.R8G8Sint,
  164. Format.R16G16Float => TextureFormat.R16G16Float,
  165. Format.R16G16Unorm => TextureFormat.R16G16Unorm,
  166. Format.R16G16Snorm => TextureFormat.R16G16Snorm,
  167. Format.R16G16Uint => TextureFormat.R16G16Uint,
  168. Format.R16G16Sint => TextureFormat.R16G16Sint,
  169. Format.R32G32Float => TextureFormat.R32G32Float,
  170. Format.R32G32Uint => TextureFormat.R32G32Uint,
  171. Format.R32G32Sint => TextureFormat.R32G32Sint,
  172. Format.R8G8B8A8Unorm => TextureFormat.R8G8B8A8Unorm,
  173. Format.R8G8B8A8Snorm => TextureFormat.R8G8B8A8Snorm,
  174. Format.R8G8B8A8Uint => TextureFormat.R8G8B8A8Uint,
  175. Format.R8G8B8A8Sint => TextureFormat.R8G8B8A8Sint,
  176. Format.R8G8B8A8Srgb => TextureFormat.R8G8B8A8Unorm,
  177. Format.R16G16B16A16Float => TextureFormat.R16G16B16A16Float,
  178. Format.R16G16B16A16Unorm => TextureFormat.R16G16B16A16Unorm,
  179. Format.R16G16B16A16Snorm => TextureFormat.R16G16B16A16Snorm,
  180. Format.R16G16B16A16Uint => TextureFormat.R16G16B16A16Uint,
  181. Format.R16G16B16A16Sint => TextureFormat.R16G16B16A16Sint,
  182. Format.R32G32B32A32Float => TextureFormat.R32G32B32A32Float,
  183. Format.R32G32B32A32Uint => TextureFormat.R32G32B32A32Uint,
  184. Format.R32G32B32A32Sint => TextureFormat.R32G32B32A32Sint,
  185. Format.R10G10B10A2Unorm => TextureFormat.R10G10B10A2Unorm,
  186. Format.R10G10B10A2Uint => TextureFormat.R10G10B10A2Uint,
  187. Format.R11G11B10Float => TextureFormat.R11G11B10Float,
  188. _ => TextureFormat.Unknown
  189. };
  190. }
  191. /// <summary>
  192. /// Converts the Maxwell primitive topology to the shader translator topology.
  193. /// </summary>
  194. /// <param name="topology">Maxwell primitive topology</param>
  195. /// <param name="tessellationMode">Maxwell tessellation mode</param>
  196. /// <returns>Shader translator topology</returns>
  197. protected static InputTopology ConvertToInputTopology(PrimitiveTopology topology, TessMode tessellationMode)
  198. {
  199. return topology switch
  200. {
  201. PrimitiveTopology.Points => InputTopology.Points,
  202. PrimitiveTopology.Lines or
  203. PrimitiveTopology.LineLoop or
  204. PrimitiveTopology.LineStrip => InputTopology.Lines,
  205. PrimitiveTopology.LinesAdjacency or
  206. PrimitiveTopology.LineStripAdjacency => InputTopology.LinesAdjacency,
  207. PrimitiveTopology.Triangles or
  208. PrimitiveTopology.TriangleStrip or
  209. PrimitiveTopology.TriangleFan => InputTopology.Triangles,
  210. PrimitiveTopology.TrianglesAdjacency or
  211. PrimitiveTopology.TriangleStripAdjacency => InputTopology.TrianglesAdjacency,
  212. PrimitiveTopology.Patches => tessellationMode.UnpackPatchType() == TessPatchType.Isolines
  213. ? InputTopology.Lines
  214. : InputTopology.Triangles,
  215. _ => InputTopology.Points
  216. };
  217. }
  218. }
  219. }