diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs | 260 |
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)); + } + } +} |