GpuAccessorBase.cs 11 KB

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