SpecializationStateUpdater.cs 8.5 KB

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