aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-02-08 10:19:43 -0300
committerGitHub <noreply@github.com>2023-02-08 14:19:43 +0100
commit26bf13a65d6689601593a8050970d6835fd9dfe2 (patch)
treec9ff9bd67a82728f3dc46b6175ac7eb1df38d2f2 /Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs
parent96cf242bcf168b9f9e6a1e27200529466217f396 (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.cs78
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>