diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/Sampler.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Sampler.cs | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Sampler.cs b/Ryujinx.Graphics.Gpu/Image/Sampler.cs index 4c05329a..52d5ccec 100644 --- a/Ryujinx.Graphics.Gpu/Image/Sampler.cs +++ b/Ryujinx.Graphics.Gpu/Image/Sampler.cs @@ -1,5 +1,6 @@ using Ryujinx.Graphics.GAL; using System; +using System.Numerics; namespace Ryujinx.Graphics.Gpu.Image { @@ -8,10 +9,17 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> class Sampler : IDisposable { + private const int MinLevelsForAnisotropic = 5; + /// <summary> /// Host sampler object. /// </summary> - public ISampler HostSampler { get; } + private readonly ISampler _hostSampler; + + /// <summary> + /// Host sampler object, with anisotropy forced. + /// </summary> + private readonly ISampler _anisoSampler; /// <summary> /// Creates a new instance of the cached sampler. @@ -42,13 +50,10 @@ namespace Ryujinx.Graphics.Gpu.Image float maxLod = descriptor.UnpackMaxLod(); float mipLodBias = descriptor.UnpackMipLodBias(); - float maxRequestedAnisotropy = GraphicsConfig.MaxAnisotropy >= 0 && GraphicsConfig.MaxAnisotropy <= 16 ? GraphicsConfig.MaxAnisotropy : descriptor.UnpackMaxAnisotropy(); + float maxRequestedAnisotropy = descriptor.UnpackMaxAnisotropy(); float maxSupportedAnisotropy = context.Capabilities.MaximumSupportedAnisotropy; - if (maxRequestedAnisotropy > maxSupportedAnisotropy) - maxRequestedAnisotropy = maxSupportedAnisotropy; - - HostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo( + _hostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo( minFilter, magFilter, seamlessCubemap, @@ -61,7 +66,56 @@ namespace Ryujinx.Graphics.Gpu.Image minLod, maxLod, mipLodBias, - maxRequestedAnisotropy)); + Math.Min(maxRequestedAnisotropy, maxSupportedAnisotropy))); + + if (GraphicsConfig.MaxAnisotropy >= 0 && GraphicsConfig.MaxAnisotropy <= 16 && (minFilter == MinFilter.LinearMipmapNearest || minFilter == MinFilter.LinearMipmapLinear)) + { + maxRequestedAnisotropy = GraphicsConfig.MaxAnisotropy; + + _anisoSampler = context.Renderer.CreateSampler(new SamplerCreateInfo( + minFilter, + magFilter, + seamlessCubemap, + addressU, + addressV, + addressP, + compareMode, + compareOp, + color, + minLod, + maxLod, + mipLodBias, + Math.Min(maxRequestedAnisotropy, maxSupportedAnisotropy))); + } + } + + /// <summary> + /// Gets a host sampler for the given texture. + /// </summary> + /// <param name="texture">Texture to be sampled</param> + /// <returns>A host sampler</returns> + public ISampler GetHostSampler(Texture texture) + { + return _anisoSampler != null && AllowForceAnisotropy(texture) ? _anisoSampler : _hostSampler; + } + + /// <summary> + /// Determine if the given texture can have anisotropic filtering forced. + /// Filtered textures that we might want to force anisotropy on should have a lot of mip levels. + /// </summary> + /// <param name="texture">The texture</param> + /// <returns>True if anisotropic filtering can be forced, false otherwise</returns> + private static bool AllowForceAnisotropy(Texture texture) + { + if (texture == null || !(texture.Target == Target.Texture2D || texture.Target == Target.Texture2DArray)) + { + return false; + } + + int maxSize = Math.Max(texture.Info.Width, texture.Info.Height); + int maxLevels = BitOperations.Log2((uint)maxSize) + 1; + + return texture.Info.Levels >= Math.Min(MinLevelsForAnisotropic, maxLevels); } /// <summary> @@ -69,7 +123,8 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> public void Dispose() { - HostSampler.Dispose(); + _hostSampler.Dispose(); + _anisoSampler?.Dispose(); } } }
\ No newline at end of file |