mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-12-28 22:23:23 +01:00
c30504e3b3
* Use a descriptor cache for faster pool invalidation. * Speed up comparison by casting to Vector256 Now we never need to worry about this ever again
260 lines
8.6 KiB
C#
260 lines
8.6 KiB
C#
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));
|
|
}
|
|
}
|
|
}
|