From 5d69d9103ef423719619658dc3378869692a5064 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 10 Sep 2020 20:44:04 +0100 Subject: Texture/Buffer Memory Management Improvements (#1408) * Initial implementation. Still pending better valid-overlap handling, disposed pool, compressed format flush fix. * Very messy backend resource cache. * Oops * Dispose -> Release * Improve Release/Dispose. * More rule refinement. * View compatibility levels as an enum - you can always know if a view is only copy compatible. * General cleanup. Use locking on the resource cache, as it is likely to be used by other threads in future. * Rename resource cache to resource pool. * Address some of the smaller nits. * Fix regression with MK8 lens flare Texture flushes done the old way should trigger memory tracking. * Use TextureCreateInfo as a key. It now implements IEquatable and generates a hashcode based on width/height. * Fix size change for compressed+non-compressed view combos. Before, this could set either the compressed or non compressed texture with a size with the wrong size, depending on which texture had its size changed. This caused exceptions when flushing the texture. Now it correctly takes the block size into account, assuming that these textures are only related because a pixel in the non-compressed texture represents a block in the compressed one. * Implement JD's suggestion for HashCode Combine Co-authored-by: jduncanator <1518948+jduncanator@users.noreply.github.com> * Address feedback * Address feedback. Co-authored-by: jduncanator <1518948+jduncanator@users.noreply.github.com> --- Ryujinx.Graphics.OpenGL/ResourcePool.cs | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 Ryujinx.Graphics.OpenGL/ResourcePool.cs (limited to 'Ryujinx.Graphics.OpenGL/ResourcePool.cs') diff --git a/Ryujinx.Graphics.OpenGL/ResourcePool.cs b/Ryujinx.Graphics.OpenGL/ResourcePool.cs new file mode 100644 index 00000000..57231cd6 --- /dev/null +++ b/Ryujinx.Graphics.OpenGL/ResourcePool.cs @@ -0,0 +1,122 @@ +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.OpenGL.Image; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.OpenGL +{ + class DisposedTexture + { + public TextureCreateInfo Info; + public TextureView View; + public float ScaleFactor; + public int RemainingFrames; + } + + /// + /// A structure for pooling resources that can be reused without recreation, such as textures. + /// + class ResourcePool : IDisposable + { + private const int DisposedLiveFrames = 2; + + private readonly object _lock = new object(); + private readonly Dictionary> _textures = new Dictionary>(); + + /// + /// Add a texture that is not being used anymore to the resource pool to be used later. + /// Both the texture's view and storage should be completely unused. + /// + /// The texture's view + public void AddTexture(TextureView view) + { + lock (_lock) + { + List list; + if (!_textures.TryGetValue(view.Info, out list)) + { + list = new List(); + _textures.Add(view.Info, list); + } + + list.Add(new DisposedTexture() + { + Info = view.Info, + View = view, + ScaleFactor = view.ScaleFactor, + RemainingFrames = DisposedLiveFrames + }); + } + } + + /// + /// Attempt to obtain a texture from the resource cache with the desired parameters. + /// + /// The creation info for the desired texture + /// The scale factor for the desired texture + /// A TextureView with the description specified, or null if one was not found. + public TextureView GetTextureOrNull(TextureCreateInfo info, float scaleFactor) + { + lock (_lock) + { + List list; + if (!_textures.TryGetValue(info, out list)) + { + return null; + } + + foreach (DisposedTexture texture in list) + { + if (scaleFactor == texture.ScaleFactor) + { + list.Remove(texture); + return texture.View; + } + } + + return null; + } + } + + /// + /// Update the pool, removing any resources that have expired. + /// + public void Tick() + { + lock (_lock) + { + foreach (List list in _textures.Values) + { + for (int i = 0; i < list.Count; i++) + { + DisposedTexture tex = list[i]; + + if (--tex.RemainingFrames < 0) + { + tex.View.Dispose(); + list.RemoveAt(i--); + } + } + } + } + } + + /// + /// Disposes the resource pool. + /// + public void Dispose() + { + lock (_lock) + { + foreach (List list in _textures.Values) + { + foreach (DisposedTexture texture in list) + { + texture.View.Dispose(); + } + } + _textures.Clear(); + } + } + } +} -- cgit v1.2.3