|
@@ -1,5 +1,6 @@
|
|
|
using Ryujinx.Graphics.GAL;
|
|
using Ryujinx.Graphics.GAL;
|
|
|
using System;
|
|
using System;
|
|
|
|
|
+using System.Numerics;
|
|
|
|
|
|
|
|
namespace Ryujinx.Graphics.Gpu.Image
|
|
namespace Ryujinx.Graphics.Gpu.Image
|
|
|
{
|
|
{
|
|
@@ -8,10 +9,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
class Sampler : IDisposable
|
|
class Sampler : IDisposable
|
|
|
{
|
|
{
|
|
|
|
|
+ private const int MinLevelsForAnisotropic = 5;
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Host sampler object.
|
|
/// Host sampler object.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public ISampler HostSampler { get; }
|
|
|
|
|
|
|
+ private readonly ISampler _hostSampler;
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Host sampler object, with anisotropy forced.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private readonly ISampler _anisoSampler;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Creates a new instance of the cached sampler.
|
|
/// Creates a new instance of the cached sampler.
|
|
@@ -42,13 +50,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|
|
float maxLod = descriptor.UnpackMaxLod();
|
|
float maxLod = descriptor.UnpackMaxLod();
|
|
|
float mipLodBias = descriptor.UnpackMipLodBias();
|
|
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;
|
|
float maxSupportedAnisotropy = context.Capabilities.MaximumSupportedAnisotropy;
|
|
|
|
|
|
|
|
- if (maxRequestedAnisotropy > maxSupportedAnisotropy)
|
|
|
|
|
- maxRequestedAnisotropy = maxSupportedAnisotropy;
|
|
|
|
|
-
|
|
|
|
|
- HostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo(
|
|
|
|
|
|
|
+ _hostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo(
|
|
|
minFilter,
|
|
minFilter,
|
|
|
magFilter,
|
|
magFilter,
|
|
|
seamlessCubemap,
|
|
seamlessCubemap,
|
|
@@ -61,7 +66,56 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|
|
minLod,
|
|
minLod,
|
|
|
maxLod,
|
|
maxLod,
|
|
|
mipLodBias,
|
|
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>
|
|
/// <summary>
|
|
@@ -69,7 +123,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
public void Dispose()
|
|
public void Dispose()
|
|
|
{
|
|
{
|
|
|
- HostSampler.Dispose();
|
|
|
|
|
|
|
+ _hostSampler.Dispose();
|
|
|
|
|
+ _anisoSampler?.Dispose();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|