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