From bc4e70b6fafc333c91caf5a94e49ece339dccd80 Mon Sep 17 00:00:00 2001
From: riperiperi <rhy3756547@hotmail.com>
Date: Wed, 8 Dec 2021 21:09:36 +0000
Subject: [PATCH] Move texture anisotropy check to SetInfo (#2843)

Rather than calculating this for every sampler, this PR calculates if a texture can force anisotropy when its info is set, and exposes the value via a public boolean.

This should help texture/sampler heavy games when anisotropic filtering is not Auto, like UE4 ones (or so i hear?). There is another cost where samplers are created twice when anisotropic filtering is enabled, but I'm not sure how relevant this one is.
---
 Ryujinx.Graphics.Gpu/Image/Sampler.cs | 24 +-----------------------
 Ryujinx.Graphics.Gpu/Image/Texture.cs | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Image/Sampler.cs b/Ryujinx.Graphics.Gpu/Image/Sampler.cs
index 52d5ccec1e..f8923d3495 100644
--- a/Ryujinx.Graphics.Gpu/Image/Sampler.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Sampler.cs
@@ -1,6 +1,5 @@
 using Ryujinx.Graphics.GAL;
 using System;
-using System.Numerics;
 
 namespace Ryujinx.Graphics.Gpu.Image
 {
@@ -9,8 +8,6 @@ namespace Ryujinx.Graphics.Gpu.Image
     /// </summary>
     class Sampler : IDisposable
     {
-        private const int MinLevelsForAnisotropic = 5;
-
         /// <summary>
         /// Host sampler object.
         /// </summary>
@@ -96,26 +93,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <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);
+            return _anisoSampler != null && texture?.CanForceAnisotropy == true ? _anisoSampler : _hostSampler;
         }
 
         /// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 7cc8faf67c..a13edc6911 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -10,6 +10,7 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
+using System.Numerics;
 
 namespace Ryujinx.Graphics.Gpu.Image
 {
@@ -23,6 +24,8 @@ namespace Ryujinx.Graphics.Gpu.Image
         // This method uses much more memory so we want to avoid it if possible.
         private const int ByteComparisonSwitchThreshold = 4;
 
+        private const int MinLevelsForForceAnisotropy = 5;
+
         private struct TexturePoolOwner
         {
             public TexturePool Pool;
@@ -49,6 +52,11 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// </summary>
         public TextureInfo Info { get; private set; }
 
+        /// <summary>
+        /// Set when anisotropic filtering can be forced on the given texture.
+        /// </summary>
+        public bool CanForceAnisotropy { get; private set; }
+
         /// <summary>
         /// Host scale factor.
         /// </summary>
@@ -1129,6 +1137,24 @@ namespace Ryujinx.Graphics.Gpu.Image
             return null;
         }
 
+        /// <summary>
+        /// Determine if this texture can have anisotropic filtering forced.
+        /// Filtered textures that we might want to force anisotropy on should have a lot of mip levels.
+        /// </summary>
+        /// <returns>True if anisotropic filtering can be forced, false otherwise</returns>
+        private bool CanTextureForceAnisotropy()
+        {
+            if (!(Target == Target.Texture2D || Target == Target.Texture2DArray))
+            {
+                return false;
+            }
+
+            int maxSize = Math.Max(Info.Width, Info.Height);
+            int maxLevels = BitOperations.Log2((uint)maxSize) + 1;
+
+            return Info.Levels >= Math.Min(MinLevelsForForceAnisotropy, maxLevels);
+        }
+
         /// <summary>
         /// Check if this texture and the specified target have the same number of dimensions.
         /// For the purposes of this comparison, 2D and 2D Multisample textures are not considered to have
@@ -1219,6 +1245,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         {
             Info = info;
             Target = info.Target;
+            CanForceAnisotropy = CanTextureForceAnisotropy();
 
             _depth  = info.GetDepth();
             _layers = info.GetLayers();