From 2c94ac455ead867aac0a7a689a55d814a8bcc0da Mon Sep 17 00:00:00 2001
From: riperiperi <rhy3756547@hotmail.com>
Date: Mon, 1 May 2023 20:27:51 +0100
Subject: GPU: Keep rendered textures without any pool references alive (#4662)

* GPU: Keep sampled textures without any pool references alive

Occasionally games are very wasteful and clear/write to a texture without ever sampling it. As rendered textures in NVN games seem to all have overlapping memory ranges, the texture will eventually get overwritten.

Normally, this would trigger a removal from the auto delete cache, but a pool entry would keep the texture alive. However, with these textures that are never used, they will get deleted immediately and recreated on the next frame.

This change makes it so the ShortTextureCache can keep textures that have naver had a pool reference alive for a few frames, so they're not constantly being created and deleted.

This improves performance in Zelda BOTW a little.

* Cleanup
---
 src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

(limited to 'src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs')

diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 97d78a34..fc2c07e5 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -848,7 +848,17 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                             if (overlapInCache)
                             {
-                                _cache.Remove(overlap, flush);
+                                if (flush || overlap.HadPoolOwner || overlap.IsView)
+                                {
+                                    _cache.Remove(overlap, flush);
+                                }
+                                else
+                                {
+                                    // This texture has only ever been referenced in the AutoDeleteCache.
+                                    // Keep this texture alive with the short duration cache, as it may be used often but not sampled.
+
+                                    _cache.AddShortCache(overlap);
+                                }
                             }
 
                             removeOverlap = modified;
@@ -1198,6 +1208,16 @@ namespace Ryujinx.Graphics.Gpu.Image
             _cache.AddShortCache(texture, ref descriptor);
         }
 
+        /// <summary>
+        /// Adds a texture to the short duration cache without a descriptor. This typically keeps it alive for two ticks.
+        /// On expiry, it will be removed from the AutoDeleteCache.
+        /// </summary>
+        /// <param name="texture">Texture to add to the short cache</param>
+        public void AddShortCache(Texture texture)
+        {
+            _cache.AddShortCache(texture);
+        }
+
         /// <summary>
         /// Removes a texture from the short duration cache.
         /// </summary>
-- 
cgit v1.2.3-70-g09d2