GpuAccessorBase.cs 10 KB

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