aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
new file mode 100644
index 00000000..64a146fb
--- /dev/null
+++ b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
@@ -0,0 +1,260 @@
+using Ryujinx.Graphics.GAL;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace Ryujinx.Graphics.Gpu.Image
+{
+ /// <summary>
+ /// Maxwell sampler descriptor structure.
+ /// This structure defines the sampler descriptor as it is packed on the GPU sampler pool region.
+ /// </summary>
+ struct SamplerDescriptor
+ {
+ private static readonly float[] _f5ToF32ConversionLut = new float[]
+ {
+ 0.0f,
+ 0.055555556f,
+ 0.1f,
+ 0.13636364f,
+ 0.16666667f,
+ 0.1923077f,
+ 0.21428572f,
+ 0.23333333f,
+ 0.25f,
+ 0.2777778f,
+ 0.3f,
+ 0.3181818f,
+ 0.33333334f,
+ 0.34615386f,
+ 0.35714287f,
+ 0.36666667f,
+ 0.375f,
+ 0.3888889f,
+ 0.4f,
+ 0.4090909f,
+ 0.41666666f,
+ 0.42307693f,
+ 0.42857143f,
+ 0.43333334f,
+ 0.4375f,
+ 0.44444445f,
+ 0.45f,
+ 0.45454547f,
+ 0.45833334f,
+ 0.46153846f,
+ 0.4642857f,
+ 0.46666667f
+ };
+
+ private static readonly float[] _maxAnisotropyLut = new float[]
+ {
+ 1, 2, 4, 6, 8, 10, 12, 16
+ };
+
+ private const float Frac8ToF32 = 1.0f / 256.0f;
+
+#pragma warning disable CS0649
+ public uint Word0;
+ public uint Word1;
+ public uint Word2;
+ public uint Word3;
+ public float BorderColorR;
+ public float BorderColorG;
+ public float BorderColorB;
+ public float BorderColorA;
+#pragma warning restore CS0649
+
+ /// <summary>
+ /// Unpacks the texture wrap mode along the X axis.
+ /// </summary>
+ /// <returns>The texture wrap mode enum</returns>
+ public AddressMode UnpackAddressU()
+ {
+ return (AddressMode)(Word0 & 7);
+ }
+
+ // <summary>
+ /// Unpacks the texture wrap mode along the Y axis.
+ /// </summary>
+ /// <returns>The texture wrap mode enum</returns>
+ public AddressMode UnpackAddressV()
+ {
+ return (AddressMode)((Word0 >> 3) & 7);
+ }
+
+ // <summary>
+ /// Unpacks the texture wrap mode along the Z axis.
+ /// </summary>
+ /// <returns>The texture wrap mode enum</returns>
+ public AddressMode UnpackAddressP()
+ {
+ return (AddressMode)((Word0 >> 6) & 7);
+ }
+
+ /// <summary>
+ /// Unpacks the compare mode used for depth comparison on the shader, for
+ /// depth buffer texture.
+ /// This is only relevant for shaders with shadow samplers.
+ /// </summary>
+ /// <returns>The depth comparison mode enum</returns>
+ public CompareMode UnpackCompareMode()
+ {
+ return (CompareMode)((Word0 >> 9) & 1);
+ }
+
+ /// <summary>
+ /// Unpacks the compare operation used for depth comparison on the shader, for
+ /// depth buffer texture.
+ /// This is only relevant for shaders with shadow samplers.
+ /// </summary>
+ /// <returns>The depth comparison operation enum</returns>
+ public CompareOp UnpackCompareOp()
+ {
+ return (CompareOp)(((Word0 >> 10) & 7) + 1);
+ }
+
+ /// <summary>
+ /// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
+ /// </summary>
+ /// <returns>The maximum anisotropy</returns>
+ public float UnpackMaxAnisotropy()
+ {
+ return _maxAnisotropyLut[(Word0 >> 20) & 7];
+ }
+
+ /// <summary>
+ /// Unpacks the texture magnification filter.
+ /// This defines the filtering used when the texture covers an area on the screen
+ /// that is larger than the texture size.
+ /// </summary>
+ /// <returns>The magnification filter</returns>
+ public MagFilter UnpackMagFilter()
+ {
+ return (MagFilter)(Word1 & 3);
+ }
+
+ /// <summary>
+ /// Unpacks the texture minification filter.
+ /// This defines the filtering used when the texture covers an area on the screen
+ /// that is smaller than the texture size.
+ /// </summary>
+ /// <returns>The minification filter</returns>
+ public MinFilter UnpackMinFilter()
+ {
+ SamplerMinFilter minFilter = (SamplerMinFilter)((Word1 >> 4) & 3);
+ SamplerMipFilter mipFilter = (SamplerMipFilter)((Word1 >> 6) & 3);
+
+ return ConvertFilter(minFilter, mipFilter);
+ }
+
+ /// <summary>
+ /// Converts two minification and filter enum, to a single minification enum,
+ /// including mipmap filtering information, as expected from the host API.
+ /// </summary>
+ /// <param name="minFilter">The minification filter</param>
+ /// <param name="mipFilter">The mipmap level filter</param>
+ /// <returns>The combined, host API compatible filter enum</returns>
+ private static MinFilter ConvertFilter(SamplerMinFilter minFilter, SamplerMipFilter mipFilter)
+ {
+ switch (mipFilter)
+ {
+ case SamplerMipFilter.None:
+ switch (minFilter)
+ {
+ case SamplerMinFilter.Nearest: return MinFilter.Nearest;
+ case SamplerMinFilter.Linear: return MinFilter.Linear;
+ }
+ break;
+
+ case SamplerMipFilter.Nearest:
+ switch (minFilter)
+ {
+ case SamplerMinFilter.Nearest: return MinFilter.NearestMipmapNearest;
+ case SamplerMinFilter.Linear: return MinFilter.LinearMipmapNearest;
+ }
+ break;
+
+ case SamplerMipFilter.Linear:
+ switch (minFilter)
+ {
+ case SamplerMinFilter.Nearest: return MinFilter.NearestMipmapLinear;
+ case SamplerMinFilter.Linear: return MinFilter.LinearMipmapLinear;
+ }
+ break;
+ }
+
+ return MinFilter.Nearest;
+ }
+
+ /// <summary>
+ /// Unpacks the seamless cubemap flag.
+ /// </summary>
+ /// <returns>The seamless cubemap flag</returns>
+ public bool UnpackSeamlessCubemap()
+ {
+ return (Word1 & (1 << 9)) != 0;
+ }
+
+ /// <summary>
+ /// Unpacks the reduction filter, used with texture minification linear filtering.
+ /// This describes how the final value will be computed from neighbouring pixels.
+ /// </summary>
+ /// <returns>The reduction filter</returns>
+ public ReductionFilter UnpackReductionFilter()
+ {
+ return (ReductionFilter)((Word1 >> 10) & 3);
+ }
+
+ /// <summary>
+ /// Unpacks the level-of-detail bias value.
+ /// This is a bias added to the level-of-detail value as computed by the GPU, used to select
+ /// which mipmap level to use from a given texture.
+ /// </summary>
+ /// <returns>The level-of-detail bias value</returns>
+ public float UnpackMipLodBias()
+ {
+ int fixedValue = (int)(Word1 >> 12) & 0x1fff;
+
+ fixedValue = (fixedValue << 19) >> 19;
+
+ return fixedValue * Frac8ToF32;
+ }
+
+ /// <summary>
+ /// Unpacks the level-of-detail snap value.
+ /// </summary>
+ /// <returns>The level-of-detail snap value</returns>
+ public float UnpackLodSnap()
+ {
+ return _f5ToF32ConversionLut[(Word1 >> 26) & 0x1f];
+ }
+
+ /// <summary>
+ /// Unpacks the minimum level-of-detail value.
+ /// </summary>
+ /// <returns>The minimum level-of-detail value</returns>
+ public float UnpackMinLod()
+ {
+ return (Word2 & 0xfff) * Frac8ToF32;
+ }
+
+ /// <summary>
+ /// Unpacks the maximum level-of-detail value.
+ /// </summary>
+ /// <returns>The maximum level-of-detail value</returns>
+ public float UnpackMaxLod()
+ {
+ return ((Word2 >> 12) & 0xfff) * Frac8ToF32;
+ }
+
+ /// <summary>
+ /// Check if two descriptors are equal.
+ /// </summary>
+ /// <param name="other">The descriptor to compare against</param>
+ /// <returns>True if they are equal, false otherwise</returns>
+ public bool Equals(ref SamplerDescriptor other)
+ {
+ return Unsafe.As<SamplerDescriptor, Vector256<byte>>(ref this).Equals(Unsafe.As<SamplerDescriptor, Vector256<byte>>(ref other));
+ }
+ }
+}