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(); private readonly Dictionary> _textures = new(); /// /// 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) { if (!_textures.TryGetValue(view.Info, out List 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) { if (!_textures.TryGetValue(info, out List 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(); } } } }