From 94a64f2aea3225d83a2aa1e61ed8d4bf8be49e5c Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Tue, 10 Jan 2023 22:53:56 -0300
Subject: Remove textures from cache on unmap if not mapped and modified
 (#4211)

---
 Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

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

diff --git a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
index 277f39b9..4a1615f0 100644
--- a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
@@ -1,4 +1,5 @@
 using System.Collections;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 
 namespace Ryujinx.Graphics.Gpu.Image
@@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         private const int MaxCapacity = 2048;
 
         private readonly LinkedList<Texture> _textures;
+        private readonly ConcurrentQueue<Texture> _deferredRemovals;
 
         /// <summary>
         /// Creates a new instance of the automatic deletion cache.
@@ -20,6 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         public AutoDeleteCache()
         {
             _textures = new LinkedList<Texture>();
+            _deferredRemovals = new ConcurrentQueue<Texture>();
         }
 
         /// <summary>
@@ -56,6 +59,14 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                 oldestTexture.CacheNode = null;
             }
+
+            if (_deferredRemovals.Count > 0)
+            {
+                while (_deferredRemovals.TryDequeue(out Texture textureToRemove))
+                {
+                    Remove(textureToRemove, false);
+                }
+            }
         }
 
         /// <summary>
@@ -84,6 +95,12 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
         }
 
+        /// <summary>
+        /// Removes a texture from the cache.
+        /// </summary>
+        /// <param name="texture">The texture to be removed from the cache</param>
+        /// <param name="flush">True to remove the texture if it was on the cache</param>
+        /// <returns>True if the texture was found and removed, false otherwise</returns>
         public bool Remove(Texture texture, bool flush)
         {
             if (texture.CacheNode == null)
@@ -104,6 +121,15 @@ namespace Ryujinx.Graphics.Gpu.Image
             return texture.DecrementReferenceCount();
         }
 
+        /// <summary>
+        /// Queues removal of a texture from the cache in a thread safe way.
+        /// </summary>
+        /// <param name="texture">The texture to be removed from the cache</param>
+        public void RemoveDeferred(Texture texture)
+        {
+            _deferredRemovals.Enqueue(texture);
+        }
+
         public IEnumerator<Texture> GetEnumerator()
         {
             return _textures.GetEnumerator();
-- 
cgit v1.2.3-70-g09d2