From 85ffd760161c6995f0004e042178d2e9259b2af5 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 14 Nov 2018 20:22:02 -0200 Subject: [PATCH] Force cache to remove entries when memory usage exceeds a given threshold (#492) --- .../Gal/OpenGL/OGLCachedResource.cs | 22 ++++++++++++++++--- Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs | 4 +++- Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs | 7 ++++-- Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs | 4 +++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs index efacb4d425..6e17872ba0 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { public delegate void DeleteValue(T Value); - private const int MaxTimeDelta = 5 * 60000; + private const int MinTimeDelta = 5 * 60000; private const int MaxRemovalsPerRun = 10; private struct CacheBucket @@ -41,8 +41,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL private bool Locked; - public OGLCachedResource(DeleteValue DeleteValueCallback) + private long MaxSize; + private long TotalSize; + + public OGLCachedResource(DeleteValue DeleteValueCallback, long MaxSize) { + this.MaxSize = MaxSize; + if (DeleteValueCallback == null) { throw new ArgumentNullException(nameof(DeleteValueCallback)); @@ -98,12 +103,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL SortedCache.Remove(Bucket.Node); + TotalSize -= Bucket.DataSize; + Cache[Key] = NewBucket; } else { Cache.Add(Key, NewBucket); } + + TotalSize += Size; } public bool TryGetValue(long Key, out T Value) @@ -159,7 +168,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL long TimeDelta = Timestamp - Bucket.Timestamp; - if ((uint)TimeDelta <= (uint)MaxTimeDelta) + if (TimeDelta <= MinTimeDelta && !UnderMemoryPressure()) { break; } @@ -169,7 +178,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL Cache.Remove(Node.Value); DeleteValueCallback(Bucket.Value); + + TotalSize -= Bucket.DataSize; } } + + private bool UnderMemoryPressure() + { + return TotalSize >= MaxSize; + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs index 4958b53b3b..e04190e042 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs @@ -5,11 +5,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLConstBuffer : IGalConstBuffer { + private const long MaxConstBufferCacheSize = 64 * 1024 * 1024; + private OGLCachedResource Cache; public OGLConstBuffer() { - Cache = new OGLCachedResource(DeleteBuffer); + Cache = new OGLCachedResource(DeleteBuffer, MaxConstBufferCacheSize); } public void LockCache() diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index cefbb2d2a1..cd6292f7e7 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -5,6 +5,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLRasterizer : IGalRasterizer { + private const long MaxVertexBufferCacheSize = 128 * 1024 * 1024; + private const long MaxIndexBufferCacheSize = 64 * 1024 * 1024; + private int[] VertexBuffers; private OGLCachedResource VboCache; @@ -24,8 +27,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL { VertexBuffers = new int[32]; - VboCache = new OGLCachedResource(GL.DeleteBuffer); - IboCache = new OGLCachedResource(GL.DeleteBuffer); + VboCache = new OGLCachedResource(GL.DeleteBuffer, MaxVertexBufferCacheSize); + IboCache = new OGLCachedResource(GL.DeleteBuffer, MaxIndexBufferCacheSize); IndexBuffer = new IbInfo(); } diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index 274b94ea87..6f843b9c31 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -6,13 +6,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLTexture : IGalTexture { + private const long MaxTextureCacheSize = 768 * 1024 * 1024; + private OGLCachedResource TextureCache; public EventHandler TextureDeleted { get; set; } public OGLTexture() { - TextureCache = new OGLCachedResource(DeleteTexture); + TextureCache = new OGLCachedResource(DeleteTexture, MaxTextureCacheSize); } public void LockCache()