diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-02-08 10:19:43 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-08 14:19:43 +0100 |
commit | 26bf13a65d6689601593a8050970d6835fd9dfe2 (patch) | |
tree | c9ff9bd67a82728f3dc46b6175ac7eb1df38d2f2 /Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs | |
parent | 96cf242bcf168b9f9e6a1e27200529466217f396 (diff) |
Limit texture cache based on total texture size (#4350)1.1.606
* Limit texture cache based on total texture size
* Formatting
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index 379eb715..a0b9f57b 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) - { - 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) + if (_textures.Count > MaxCapacity || + (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)) { - 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 { @@ -128,6 +112,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> /// <param name="texture">The texture to be removed from the cache</param> @@ -148,21 +157,14 @@ 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> /// <param name="descriptor">The texture descriptor</param> |