diff --git a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
index 379eb71596..a0b9f57bd9 100644
--- a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
@@ -33,10 +33,12 @@ namespace Ryujinx.Graphics.Gpu.Image
     /// </summary>
     class AutoDeleteCache : IEnumerable<Texture>
     {
+        private const int MinCountForDeletion = 32;
         private const int MaxCapacity = 2048;
+        private const ulong MaxTextureSizeCapacity = 512 * 1024 * 1024; // MB;
 
         private readonly LinkedList<Texture> _textures;
-        private readonly ConcurrentQueue<Texture> _deferredRemovals;
+        private ulong _totalSize;
 
         private HashSet<ShortTextureCacheEntry> _shortCacheBuilder;
         private HashSet<ShortTextureCacheEntry> _shortCache;
@@ -49,7 +51,6 @@ namespace Ryujinx.Graphics.Gpu.Image
         public AutoDeleteCache()
         {
             _textures = new LinkedList<Texture>();
-            _deferredRemovals = new ConcurrentQueue<Texture>();
 
             _shortCacheBuilder = new HashSet<ShortTextureCacheEntry>();
             _shortCache = new HashSet<ShortTextureCacheEntry>();
@@ -67,37 +68,15 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <param name="texture">The texture to be added to the cache</param>
         public void Add(Texture texture)
         {
-            texture.IncrementReferenceCount();
+            _totalSize += texture.Size;
 
+            texture.IncrementReferenceCount();
             texture.CacheNode = _textures.AddLast(texture);
 
-            if (_textures.Count > MaxCapacity)
+            if (_textures.Count > MaxCapacity ||
+                (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion))
             {
-                Texture oldestTexture = _textures.First.Value;
-
-                if (!oldestTexture.CheckModified(false))
-                {
-                    // The texture must be flushed if it falls out of the auto delete cache.
-                    // Flushes out of the auto delete cache do not trigger write tracking,
-                    // as it is expected that other overlapping textures exist that have more up-to-date contents.
-
-                    oldestTexture.Group.SynchronizeDependents(oldestTexture);
-                    oldestTexture.FlushModified(false);
-                }
-
-                _textures.RemoveFirst();
-
-                oldestTexture.DecrementReferenceCount();
-
-                oldestTexture.CacheNode = null;
-            }
-
-            if (_deferredRemovals.Count > 0)
-            {
-                while (_deferredRemovals.TryDequeue(out Texture textureToRemove))
-                {
-                    Remove(textureToRemove, false);
-                }
+                RemoveLeastUsedTexture();
             }
         }
 
@@ -120,6 +99,11 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                     texture.CacheNode = _textures.AddLast(texture);
                 }
+
+                if (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)
+                {
+                    RemoveLeastUsedTexture();
+                }
             }
             else
             {
@@ -127,6 +111,31 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
         }
 
+        /// <summary>
+        /// Removes the least used texture from the cache.
+        /// </summary>
+        private void RemoveLeastUsedTexture()
+        {
+            Texture oldestTexture = _textures.First.Value;
+
+            _totalSize -= oldestTexture.Size;
+
+            if (!oldestTexture.CheckModified(false))
+            {
+                // The texture must be flushed if it falls out of the auto delete cache.
+                // Flushes out of the auto delete cache do not trigger write tracking,
+                // as it is expected that other overlapping textures exist that have more up-to-date contents.
+
+                oldestTexture.Group.SynchronizeDependents(oldestTexture);
+                oldestTexture.FlushModified(false);
+            }
+
+            _textures.RemoveFirst();
+
+            oldestTexture.DecrementReferenceCount();
+            oldestTexture.CacheNode = null;
+        }
+
         /// <summary>
         /// Removes a texture from the cache.
         /// </summary>
@@ -148,20 +157,13 @@ namespace Ryujinx.Graphics.Gpu.Image
 
             _textures.Remove(texture.CacheNode);
 
+            _totalSize -= texture.Size;
+
             texture.CacheNode = null;
 
             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);
-        }
-
         /// <summary>
         /// Attempt to find a texture on the short duration cache.
         /// </summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 352a828d16..6c0de53674 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -1637,13 +1637,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
 
             RemoveFromPools(true);
-
-            // We only want to remove if there's no mapped region of the texture that was modified by the GPU,
-            // otherwise we could lose data.
-            if (!Group.AnyModified(this))
-            {
-                _physicalMemory.TextureCache.QueueAutoDeleteCacheRemoval(this);
-            }
         }
 
         /// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 1d5b1851f5..27bec786f0 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -1079,19 +1079,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
         }
 
-        /// <summary>
-        /// Queues the removal of a texture from the auto delete cache.
-        /// </summary>
-        /// <remarks>
-        /// This function is thread safe and can be called from any thread.
-        /// The texture will be deleted on the next time the cache is used.
-        /// </remarks>
-        /// <param name="texture">The texture to be removed</param>
-        public void QueueAutoDeleteCacheRemoval(Texture texture)
-        {
-            _cache.RemoveDeferred(texture);
-        }
-
         /// <summary>
         /// Adds a texture to the short duration cache. This typically keeps it alive for two ticks.
         /// </summary>
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
index 896e11a5dc..942fa2f875 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
@@ -434,32 +434,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
         }
 
-        /// <summary>
-        /// Checks if a texture was modified by the GPU.
-        /// </summary>
-        /// <param name="texture">The texture to be checked</param>
-        /// <returns>True if any region of the texture was modified by the GPU, false otherwise</returns>
-        public bool AnyModified(Texture texture)
-        {
-            bool anyModified = false;
-
-            EvaluateRelevantHandles(texture, (baseHandle, regionCount, split) =>
-            {
-                for (int i = 0; i < regionCount; i++)
-                {
-                    TextureGroupHandle group = _handles[baseHandle + i];
-
-                    if (group.Modified)
-                    {
-                        anyModified = true;
-                        break;
-                    }
-                }
-            });
-
-            return anyModified;
-        }
-
         /// <summary>
         /// Flush modified ranges for a given texture.
         /// </summary>