GpuAccessorBase.cs 11 KB

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