SpecializationStateUpdater.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. using Ryujinx.Common.Memory;
  2. using Ryujinx.Graphics.GAL;
  3. using Ryujinx.Graphics.Gpu.Engine.Types;
  4. using Ryujinx.Graphics.Gpu.Shader;
  5. using Ryujinx.Graphics.Shader;
  6. namespace Ryujinx.Graphics.Gpu.Engine.Threed
  7. {
  8. /// <summary>
  9. /// Maintains a "current" specialiation state, and provides a flag to check if it has changed meaningfully.
  10. /// </summary>
  11. internal class SpecializationStateUpdater
  12. {
  13. private readonly GpuContext _context;
  14. private GpuChannelGraphicsState _graphics;
  15. private GpuChannelPoolState _pool;
  16. private bool _usesDrawParameters;
  17. private bool _usesTopology;
  18. private bool _changed;
  19. /// <summary>
  20. /// Creates a new instance of the specialization state updater class.
  21. /// </summary>
  22. /// <param name="context">GPU context</param>
  23. public SpecializationStateUpdater(GpuContext context)
  24. {
  25. _context = context;
  26. }
  27. /// <summary>
  28. /// Signal that the specialization state has changed.
  29. /// </summary>
  30. private void Signal()
  31. {
  32. _changed = true;
  33. }
  34. /// <summary>
  35. /// Checks if the specialization state has changed since the last check.
  36. /// </summary>
  37. /// <returns>True if it has changed, false otherwise</returns>
  38. public bool HasChanged()
  39. {
  40. if (_changed)
  41. {
  42. _changed = false;
  43. return true;
  44. }
  45. else
  46. {
  47. return false;
  48. }
  49. }
  50. /// <summary>
  51. /// Sets the active shader, clearing the dirty state and recording if certain specializations are noteworthy.
  52. /// </summary>
  53. /// <param name="gs">The active shader</param>
  54. public void SetShader(CachedShaderProgram gs)
  55. {
  56. _usesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
  57. _usesTopology = gs.SpecializationState.IsPrimitiveTopologyQueried();
  58. _changed = false;
  59. }
  60. /// <summary>
  61. /// Get the current graphics state.
  62. /// </summary>
  63. /// <returns>GPU graphics state</returns>
  64. public ref GpuChannelGraphicsState GetGraphicsState()
  65. {
  66. return ref _graphics;
  67. }
  68. /// <summary>
  69. /// Get the current pool state.
  70. /// </summary>
  71. /// <returns>GPU pool state</returns>
  72. public ref GpuChannelPoolState GetPoolState()
  73. {
  74. return ref _pool;
  75. }
  76. /// <summary>
  77. /// Early Z force enable.
  78. /// </summary>
  79. /// <param name="value">The new value</param>
  80. public void SetEarlyZForce(bool value)
  81. {
  82. _graphics.EarlyZForce = value;
  83. Signal();
  84. }
  85. /// <summary>
  86. /// Primitive topology of current draw.
  87. /// </summary>
  88. /// <param name="value">The new value</param>
  89. public void SetTopology(PrimitiveTopology value)
  90. {
  91. if (value != _graphics.Topology)
  92. {
  93. _graphics.Topology = value;
  94. if (_usesTopology)
  95. {
  96. Signal();
  97. }
  98. }
  99. }
  100. /// <summary>
  101. /// Tessellation mode.
  102. /// </summary>
  103. /// <param name="value">The new value</param>
  104. public void SetTessellationMode(TessMode value)
  105. {
  106. if (value.Packed != _graphics.TessellationMode.Packed)
  107. {
  108. _graphics.TessellationMode = value;
  109. Signal();
  110. }
  111. }
  112. /// <summary>
  113. /// Updates alpha-to-coverage state, and sets it as changed.
  114. /// </summary>
  115. /// <param name="enable">Whether alpha-to-coverage is enabled</param>
  116. /// <param name="ditherEnable">Whether alpha-to-coverage dithering is enabled</param>
  117. public void SetAlphaToCoverageEnable(bool enable, bool ditherEnable)
  118. {
  119. _graphics.AlphaToCoverageEnable = enable;
  120. _graphics.AlphaToCoverageDitherEnable = ditherEnable;
  121. Signal();
  122. }
  123. /// <summary>
  124. /// Indicates whether the viewport transform is disabled.
  125. /// </summary>
  126. /// <param name="value">The new value</param>
  127. public void SetViewportTransformDisable(bool value)
  128. {
  129. if (value != _graphics.ViewportTransformDisable)
  130. {
  131. _graphics.ViewportTransformDisable = value;
  132. Signal();
  133. }
  134. }
  135. /// <summary>
  136. /// Depth mode zero to one or minus one to one.
  137. /// </summary>
  138. /// <param name="value">The new value</param>
  139. public void SetDepthMode(bool value)
  140. {
  141. if (value != _graphics.DepthMode)
  142. {
  143. _graphics.DepthMode = value;
  144. Signal();
  145. }
  146. }
  147. /// <summary>
  148. /// Indicates if the point size is set on the shader or is fixed.
  149. /// </summary>
  150. /// <param name="value">The new value</param>
  151. public void SetProgramPointSizeEnable(bool value)
  152. {
  153. if (value != _graphics.ProgramPointSizeEnable)
  154. {
  155. _graphics.ProgramPointSizeEnable = value;
  156. Signal();
  157. }
  158. }
  159. /// <summary>
  160. /// Point size used if <see cref="SetProgramPointSizeEnable" /> is provided false.
  161. /// </summary>
  162. /// <param name="value">The new value</param>
  163. public void SetPointSize(float value)
  164. {
  165. if (value != _graphics.PointSize)
  166. {
  167. _graphics.PointSize = value;
  168. Signal();
  169. }
  170. }
  171. /// <summary>
  172. /// Updates alpha test specialization state, and sets it as changed.
  173. /// </summary>
  174. /// <param name="enable">Whether alpha test is enabled</param>
  175. /// <param name="reference">The value to compare with the fragment output alpha</param>
  176. /// <param name="op">The comparison that decides if the fragment should be discarded</param>
  177. public void SetAlphaTest(bool enable, float reference, CompareOp op)
  178. {
  179. _graphics.AlphaTestEnable = enable;
  180. _graphics.AlphaTestReference = reference;
  181. _graphics.AlphaTestCompare = op;
  182. Signal();
  183. }
  184. /// <summary>
  185. /// Updates the type of the vertex attributes consumed by the shader.
  186. /// </summary>
  187. /// <param name="state">The new state</param>
  188. public void SetAttributeTypes(ref Array32<VertexAttribState> state)
  189. {
  190. bool changed = false;
  191. ref Array32<AttributeType> attributeTypes = ref _graphics.AttributeTypes;
  192. for (int location = 0; location < state.Length; location++)
  193. {
  194. VertexAttribType type = state[location].UnpackType();
  195. AttributeType value = type switch
  196. {
  197. VertexAttribType.Sint => AttributeType.Sint,
  198. VertexAttribType.Uint => AttributeType.Uint,
  199. _ => AttributeType.Float
  200. };
  201. if (attributeTypes[location] != value)
  202. {
  203. attributeTypes[location] = value;
  204. changed = true;
  205. }
  206. }
  207. if (changed)
  208. {
  209. Signal();
  210. }
  211. }
  212. /// <summary>
  213. /// Updates the type of the outputs produced by the fragment shader based on the current render target state.
  214. /// </summary>
  215. /// <param name="rtControl">The render target control register</param>
  216. /// <param name="state">The color attachment state</param>
  217. public void SetFragmentOutputTypes(RtControl rtControl, ref Array8<RtColorState> state)
  218. {
  219. bool changed = false;
  220. int count = rtControl.UnpackCount();
  221. for (int index = 0; index < Constants.TotalRenderTargets; index++)
  222. {
  223. int rtIndex = rtControl.UnpackPermutationIndex(index);
  224. var colorState = state[rtIndex];
  225. if (index < count && StateUpdater.IsRtEnabled(colorState))
  226. {
  227. Format format = colorState.Format.Convert().Format;
  228. AttributeType type = format.IsInteger() ? (format.IsSint() ? AttributeType.Sint : AttributeType.Uint) : AttributeType.Float;
  229. if (type != _graphics.FragmentOutputTypes[index])
  230. {
  231. _graphics.FragmentOutputTypes[index] = type;
  232. changed = true;
  233. }
  234. }
  235. }
  236. if (changed && _context.Capabilities.NeedsFragmentOutputSpecialization)
  237. {
  238. Signal();
  239. }
  240. }
  241. /// <summary>
  242. /// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0.
  243. /// </summary>
  244. /// <param name="value">The new value</param>
  245. public void SetHasConstantBufferDrawParameters(bool value)
  246. {
  247. if (value != _graphics.HasConstantBufferDrawParameters)
  248. {
  249. _graphics.HasConstantBufferDrawParameters = value;
  250. if (_usesDrawParameters)
  251. {
  252. Signal();
  253. }
  254. }
  255. }
  256. /// <summary>
  257. /// Indicates that any storage buffer use is unaligned.
  258. /// </summary>
  259. /// <param name="value">The new value</param>
  260. /// <returns>True if the unaligned state changed, false otherwise</returns>
  261. public bool SetHasUnalignedStorageBuffer(bool value)
  262. {
  263. if (value != _graphics.HasUnalignedStorageBuffer)
  264. {
  265. _graphics.HasUnalignedStorageBuffer = value;
  266. Signal();
  267. return true;
  268. }
  269. return false;
  270. }
  271. /// <summary>
  272. /// Sets the GPU pool state.
  273. /// </summary>
  274. /// <param name="state">The new state</param>
  275. public void SetPoolState(GpuChannelPoolState state)
  276. {
  277. if (!state.Equals(_pool))
  278. {
  279. _pool = state;
  280. Signal();
  281. }
  282. }
  283. }
  284. }