SamplerDescriptor.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using Ryujinx.Graphics.GAL;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.Intrinsics;
  4. namespace Ryujinx.Graphics.Gpu.Image
  5. {
  6. /// <summary>
  7. /// Maxwell sampler descriptor structure.
  8. /// This structure defines the sampler descriptor as it is packed on the GPU sampler pool region.
  9. /// </summary>
  10. struct SamplerDescriptor
  11. {
  12. private static readonly float[] _f5ToF32ConversionLut =
  13. [
  14. 0.0f,
  15. 0.055555556f,
  16. 0.1f,
  17. 0.13636364f,
  18. 0.16666667f,
  19. 0.1923077f,
  20. 0.21428572f,
  21. 0.23333333f,
  22. 0.25f,
  23. 0.2777778f,
  24. 0.3f,
  25. 0.3181818f,
  26. 0.33333334f,
  27. 0.34615386f,
  28. 0.35714287f,
  29. 0.36666667f,
  30. 0.375f,
  31. 0.3888889f,
  32. 0.4f,
  33. 0.4090909f,
  34. 0.41666666f,
  35. 0.42307693f,
  36. 0.42857143f,
  37. 0.43333334f,
  38. 0.4375f,
  39. 0.44444445f,
  40. 0.45f,
  41. 0.45454547f,
  42. 0.45833334f,
  43. 0.46153846f,
  44. 0.4642857f,
  45. 0.46666667f
  46. ];
  47. private static readonly float[] _maxAnisotropyLut =
  48. [
  49. 1, 2, 4, 6, 8, 10, 12, 16
  50. ];
  51. private const float Frac8ToF32 = 1.0f / 256.0f;
  52. #pragma warning disable CS0649 // Field is never assigned to
  53. public uint Word0;
  54. public uint Word1;
  55. public uint Word2;
  56. public uint Word3;
  57. public float BorderColorR;
  58. public float BorderColorG;
  59. public float BorderColorB;
  60. public float BorderColorA;
  61. #pragma warning restore CS0649
  62. /// <summary>
  63. /// Unpacks the texture wrap mode along the X axis.
  64. /// </summary>
  65. /// <returns>The texture wrap mode enum</returns>
  66. public readonly AddressMode UnpackAddressU()
  67. {
  68. return (AddressMode)(Word0 & 7);
  69. }
  70. // <summary>
  71. /// Unpacks the texture wrap mode along the Y axis.
  72. /// </summary>
  73. /// <returns>The texture wrap mode enum</returns>
  74. public readonly AddressMode UnpackAddressV()
  75. {
  76. return (AddressMode)((Word0 >> 3) & 7);
  77. }
  78. // <summary>
  79. /// Unpacks the texture wrap mode along the Z axis.
  80. /// </summary>
  81. /// <returns>The texture wrap mode enum</returns>
  82. public readonly AddressMode UnpackAddressP()
  83. {
  84. return (AddressMode)((Word0 >> 6) & 7);
  85. }
  86. /// <summary>
  87. /// Unpacks the compare mode used for depth comparison on the shader, for
  88. /// depth buffer texture.
  89. /// This is only relevant for shaders with shadow samplers.
  90. /// </summary>
  91. /// <returns>The depth comparison mode enum</returns>
  92. public readonly CompareMode UnpackCompareMode()
  93. {
  94. return (CompareMode)((Word0 >> 9) & 1);
  95. }
  96. /// <summary>
  97. /// Unpacks the compare operation used for depth comparison on the shader, for
  98. /// depth buffer texture.
  99. /// This is only relevant for shaders with shadow samplers.
  100. /// </summary>
  101. /// <returns>The depth comparison operation enum</returns>
  102. public readonly CompareOp UnpackCompareOp()
  103. {
  104. return (CompareOp)(((Word0 >> 10) & 7) + 1);
  105. }
  106. /// <summary>
  107. /// Unpacks the sampler sRGB format flag.
  108. /// </summary>
  109. /// <returns>True if the has sampler is sRGB conversion enabled, false otherwise</returns>
  110. public readonly bool UnpackSrgb()
  111. {
  112. return (Word0 & (1 << 13)) != 0;
  113. }
  114. /// <summary>
  115. /// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
  116. /// </summary>
  117. /// <returns>The maximum anisotropy</returns>
  118. public readonly float UnpackMaxAnisotropy()
  119. {
  120. return _maxAnisotropyLut[(Word0 >> 20) & 7];
  121. }
  122. /// <summary>
  123. /// Unpacks the texture magnification filter.
  124. /// This defines the filtering used when the texture covers an area on the screen
  125. /// that is larger than the texture size.
  126. /// </summary>
  127. /// <returns>The magnification filter</returns>
  128. public readonly MagFilter UnpackMagFilter()
  129. {
  130. return (MagFilter)(Word1 & 3);
  131. }
  132. /// <summary>
  133. /// Unpacks the texture minification filter.
  134. /// This defines the filtering used when the texture covers an area on the screen
  135. /// that is smaller than the texture size.
  136. /// </summary>
  137. /// <returns>The minification filter</returns>
  138. public readonly MinFilter UnpackMinFilter()
  139. {
  140. SamplerMinFilter minFilter = (SamplerMinFilter)((Word1 >> 4) & 3);
  141. SamplerMipFilter mipFilter = (SamplerMipFilter)((Word1 >> 6) & 3);
  142. return ConvertFilter(minFilter, mipFilter);
  143. }
  144. /// <summary>
  145. /// Converts two minification and filter enum, to a single minification enum,
  146. /// including mipmap filtering information, as expected from the host API.
  147. /// </summary>
  148. /// <param name="minFilter">The minification filter</param>
  149. /// <param name="mipFilter">The mipmap level filter</param>
  150. /// <returns>The combined, host API compatible filter enum</returns>
  151. private static MinFilter ConvertFilter(SamplerMinFilter minFilter, SamplerMipFilter mipFilter)
  152. {
  153. switch (mipFilter)
  154. {
  155. case SamplerMipFilter.None:
  156. switch (minFilter)
  157. {
  158. case SamplerMinFilter.Nearest:
  159. return MinFilter.Nearest;
  160. case SamplerMinFilter.Linear:
  161. return MinFilter.Linear;
  162. }
  163. break;
  164. case SamplerMipFilter.Nearest:
  165. switch (minFilter)
  166. {
  167. case SamplerMinFilter.Nearest:
  168. return MinFilter.NearestMipmapNearest;
  169. case SamplerMinFilter.Linear:
  170. return MinFilter.LinearMipmapNearest;
  171. }
  172. break;
  173. case SamplerMipFilter.Linear:
  174. switch (minFilter)
  175. {
  176. case SamplerMinFilter.Nearest:
  177. return MinFilter.NearestMipmapLinear;
  178. case SamplerMinFilter.Linear:
  179. return MinFilter.LinearMipmapLinear;
  180. }
  181. break;
  182. }
  183. return MinFilter.Nearest;
  184. }
  185. /// <summary>
  186. /// Unpacks the seamless cubemap flag.
  187. /// </summary>
  188. /// <returns>The seamless cubemap flag</returns>
  189. public readonly bool UnpackSeamlessCubemap()
  190. {
  191. return (Word1 & (1 << 9)) != 0;
  192. }
  193. /// <summary>
  194. /// Unpacks the reduction filter, used with texture minification linear filtering.
  195. /// This describes how the final value will be computed from neighbouring pixels.
  196. /// </summary>
  197. /// <returns>The reduction filter</returns>
  198. public readonly ReductionFilter UnpackReductionFilter()
  199. {
  200. return (ReductionFilter)((Word1 >> 10) & 3);
  201. }
  202. /// <summary>
  203. /// Unpacks the level-of-detail bias value.
  204. /// This is a bias added to the level-of-detail value as computed by the GPU, used to select
  205. /// which mipmap level to use from a given texture.
  206. /// </summary>
  207. /// <returns>The level-of-detail bias value</returns>
  208. public readonly float UnpackMipLodBias()
  209. {
  210. int fixedValue = (int)(Word1 >> 12) & 0x1fff;
  211. fixedValue = (fixedValue << 19) >> 19;
  212. return fixedValue * Frac8ToF32;
  213. }
  214. /// <summary>
  215. /// Unpacks the level-of-detail snap value.
  216. /// </summary>
  217. /// <returns>The level-of-detail snap value</returns>
  218. public readonly float UnpackLodSnap()
  219. {
  220. return _f5ToF32ConversionLut[(Word1 >> 26) & 0x1f];
  221. }
  222. /// <summary>
  223. /// Unpacks the minimum level-of-detail value.
  224. /// </summary>
  225. /// <returns>The minimum level-of-detail value</returns>
  226. public readonly float UnpackMinLod()
  227. {
  228. return (Word2 & 0xfff) * Frac8ToF32;
  229. }
  230. /// <summary>
  231. /// Unpacks the maximum level-of-detail value.
  232. /// </summary>
  233. /// <returns>The maximum level-of-detail value</returns>
  234. public readonly float UnpackMaxLod()
  235. {
  236. return ((Word2 >> 12) & 0xfff) * Frac8ToF32;
  237. }
  238. /// <summary>
  239. /// Check if two descriptors are equal.
  240. /// </summary>
  241. /// <param name="other">The descriptor to compare against</param>
  242. /// <returns>True if they are equal, false otherwise</returns>
  243. public bool Equals(ref SamplerDescriptor other)
  244. {
  245. return Unsafe.As<SamplerDescriptor, Vector256<byte>>(ref this).Equals(Unsafe.As<SamplerDescriptor, Vector256<byte>>(ref other));
  246. }
  247. }
  248. }