DiskCacheGpuAccessor.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. using System;
  7. using System.Runtime.InteropServices;
  8. namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
  9. {
  10. /// <summary>
  11. /// Represents a GPU state and memory accessor.
  12. /// </summary>
  13. class DiskCacheGpuAccessor : GpuAccessorBase, IGpuAccessor
  14. {
  15. private readonly ReadOnlyMemory<byte> _data;
  16. private readonly ReadOnlyMemory<byte> _cb1Data;
  17. private readonly ShaderSpecializationState _oldSpecState;
  18. private readonly ShaderSpecializationState _newSpecState;
  19. private readonly int _stageIndex;
  20. private readonly bool _isVulkan;
  21. private readonly ResourceCounts _resourceCounts;
  22. /// <summary>
  23. /// Creates a new instance of the cached GPU state accessor for shader translation.
  24. /// </summary>
  25. /// <param name="context">GPU context</param>
  26. /// <param name="data">The data of the shader</param>
  27. /// <param name="cb1Data">The constant buffer 1 data of the shader</param>
  28. /// <param name="oldSpecState">Shader specialization state of the cached shader</param>
  29. /// <param name="newSpecState">Shader specialization state of the recompiled shader</param>
  30. /// <param name="stageIndex">Shader stage index</param>
  31. public DiskCacheGpuAccessor(
  32. GpuContext context,
  33. ReadOnlyMemory<byte> data,
  34. ReadOnlyMemory<byte> cb1Data,
  35. ShaderSpecializationState oldSpecState,
  36. ShaderSpecializationState newSpecState,
  37. ResourceCounts counts,
  38. int stageIndex) : base(context, counts, stageIndex)
  39. {
  40. _data = data;
  41. _cb1Data = cb1Data;
  42. _oldSpecState = oldSpecState;
  43. _newSpecState = newSpecState;
  44. _stageIndex = stageIndex;
  45. _isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
  46. _resourceCounts = counts;
  47. }
  48. /// <inheritdoc/>
  49. public uint ConstantBuffer1Read(int offset)
  50. {
  51. if (offset + sizeof(uint) > _cb1Data.Length)
  52. {
  53. throw new DiskCacheLoadException(DiskCacheLoadResult.InvalidCb1DataLength);
  54. }
  55. return MemoryMarshal.Cast<byte, uint>(_cb1Data.Span.Slice(offset))[0];
  56. }
  57. /// <inheritdoc/>
  58. public void Log(string message)
  59. {
  60. Logger.Warning?.Print(LogClass.Gpu, $"Shader translator: {message}");
  61. }
  62. /// <inheritdoc/>
  63. public ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize)
  64. {
  65. return MemoryMarshal.Cast<byte, ulong>(_data.Span.Slice((int)address));
  66. }
  67. /// <inheritdoc/>
  68. public bool QueryAlphaToCoverageDitherEnable()
  69. {
  70. return _oldSpecState.GraphicsState.AlphaToCoverageEnable && _oldSpecState.GraphicsState.AlphaToCoverageDitherEnable;
  71. }
  72. /// <inheritdoc/>
  73. public AlphaTestOp QueryAlphaTestCompare()
  74. {
  75. if (!_isVulkan || !_oldSpecState.GraphicsState.AlphaTestEnable)
  76. {
  77. return AlphaTestOp.Always;
  78. }
  79. return _oldSpecState.GraphicsState.AlphaTestCompare switch
  80. {
  81. CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never,
  82. CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less,
  83. CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal,
  84. CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual,
  85. CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater,
  86. CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual,
  87. CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual,
  88. _ => AlphaTestOp.Always
  89. };
  90. }
  91. /// <inheritdoc/>
  92. public float QueryAlphaTestReference() => _oldSpecState.GraphicsState.AlphaTestReference;
  93. /// <inheritdoc/>
  94. public AttributeType QueryAttributeType(int location)
  95. {
  96. return _oldSpecState.GraphicsState.AttributeTypes[location];
  97. }
  98. /// <inheritdoc/>
  99. public int QueryComputeLocalSizeX() => _oldSpecState.ComputeState.LocalSizeX;
  100. /// <inheritdoc/>
  101. public int QueryComputeLocalSizeY() => _oldSpecState.ComputeState.LocalSizeY;
  102. /// <inheritdoc/>
  103. public int QueryComputeLocalSizeZ() => _oldSpecState.ComputeState.LocalSizeZ;
  104. /// <inheritdoc/>
  105. public int QueryComputeLocalMemorySize() => _oldSpecState.ComputeState.LocalMemorySize;
  106. /// <inheritdoc/>
  107. public int QueryComputeSharedMemorySize() => _oldSpecState.ComputeState.SharedMemorySize;
  108. /// <inheritdoc/>
  109. public uint QueryConstantBufferUse()
  110. {
  111. _newSpecState.RecordConstantBufferUse(_stageIndex, _oldSpecState.ConstantBufferUse[_stageIndex]);
  112. return _oldSpecState.ConstantBufferUse[_stageIndex];
  113. }
  114. /// <inheritdoc/>
  115. public bool QueryHasConstantBufferDrawParameters()
  116. {
  117. return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters;
  118. }
  119. /// <inheritdoc/>
  120. public InputTopology QueryPrimitiveTopology()
  121. {
  122. _newSpecState.RecordPrimitiveTopology();
  123. return ConvertToInputTopology(_oldSpecState.GraphicsState.Topology, _oldSpecState.GraphicsState.TessellationMode);
  124. }
  125. /// <inheritdoc/>
  126. public bool QueryProgramPointSize()
  127. {
  128. return _oldSpecState.GraphicsState.ProgramPointSizeEnable;
  129. }
  130. /// <inheritdoc/>
  131. public float QueryPointSize()
  132. {
  133. return _oldSpecState.GraphicsState.PointSize;
  134. }
  135. /// <inheritdoc/>
  136. public bool QueryTessCw()
  137. {
  138. return _oldSpecState.GraphicsState.TessellationMode.UnpackCw();
  139. }
  140. /// <inheritdoc/>
  141. public TessPatchType QueryTessPatchType()
  142. {
  143. return _oldSpecState.GraphicsState.TessellationMode.UnpackPatchType();
  144. }
  145. /// <inheritdoc/>
  146. public TessSpacing QueryTessSpacing()
  147. {
  148. return _oldSpecState.GraphicsState.TessellationMode.UnpackSpacing();
  149. }
  150. /// <inheritdoc/>
  151. public TextureFormat QueryTextureFormat(int handle, int cbufSlot)
  152. {
  153. _newSpecState.RecordTextureFormat(_stageIndex, handle, cbufSlot);
  154. (uint format, bool formatSrgb) = _oldSpecState.GetFormat(_stageIndex, handle, cbufSlot);
  155. return ConvertToTextureFormat(format, formatSrgb);
  156. }
  157. /// <inheritdoc/>
  158. public SamplerType QuerySamplerType(int handle, int cbufSlot)
  159. {
  160. _newSpecState.RecordTextureSamplerType(_stageIndex, handle, cbufSlot);
  161. return _oldSpecState.GetTextureTarget(_stageIndex, handle, cbufSlot).ConvertSamplerType();
  162. }
  163. /// <inheritdoc/>
  164. public bool QueryTextureCoordNormalized(int handle, int cbufSlot)
  165. {
  166. _newSpecState.RecordTextureCoordNormalized(_stageIndex, handle, cbufSlot);
  167. return _oldSpecState.GetCoordNormalized(_stageIndex, handle, cbufSlot);
  168. }
  169. /// <inheritdoc/>
  170. public bool QueryTransformDepthMinusOneToOne()
  171. {
  172. return _oldSpecState.GraphicsState.DepthMode;
  173. }
  174. /// <inheritdoc/>
  175. public bool QueryTransformFeedbackEnabled()
  176. {
  177. return _oldSpecState.TransformFeedbackDescriptors != null;
  178. }
  179. /// <inheritdoc/>
  180. public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
  181. {
  182. return _oldSpecState.TransformFeedbackDescriptors[bufferIndex].AsSpan();
  183. }
  184. /// <inheritdoc/>
  185. public int QueryTransformFeedbackStride(int bufferIndex)
  186. {
  187. return _oldSpecState.TransformFeedbackDescriptors[bufferIndex].Stride;
  188. }
  189. /// <inheritdoc/>
  190. public bool QueryEarlyZForce()
  191. {
  192. _newSpecState.RecordEarlyZForce();
  193. return _oldSpecState.GraphicsState.EarlyZForce;
  194. }
  195. /// <inheritdoc/>
  196. public bool QueryHasUnalignedStorageBuffer()
  197. {
  198. return _oldSpecState.GraphicsState.HasUnalignedStorageBuffer || _oldSpecState.ComputeState.HasUnalignedStorageBuffer;
  199. }
  200. /// <inheritdoc/>
  201. public bool QueryViewportTransformDisable()
  202. {
  203. return _oldSpecState.GraphicsState.ViewportTransformDisable;
  204. }
  205. /// <inheritdoc/>
  206. public void RegisterTexture(int handle, int cbufSlot)
  207. {
  208. if (!_oldSpecState.TextureRegistered(_stageIndex, handle, cbufSlot))
  209. {
  210. throw new DiskCacheLoadException(DiskCacheLoadResult.MissingTextureDescriptor);
  211. }
  212. (uint format, bool formatSrgb) = _oldSpecState.GetFormat(_stageIndex, handle, cbufSlot);
  213. TextureTarget target = _oldSpecState.GetTextureTarget(_stageIndex, handle, cbufSlot);
  214. bool coordNormalized = _oldSpecState.GetCoordNormalized(_stageIndex, handle, cbufSlot);
  215. _newSpecState.RegisterTexture(_stageIndex, handle, cbufSlot, format, formatSrgb, target, coordNormalized);
  216. }
  217. }
  218. }