/ src / Ryujinx.Graphics.OpenGL / ResourcePool.cs
ResourcePool.cs
  1  using Ryujinx.Graphics.GAL;
  2  using Ryujinx.Graphics.OpenGL.Image;
  3  using System;
  4  using System.Collections.Generic;
  5  
  6  namespace Ryujinx.Graphics.OpenGL
  7  {
  8      class DisposedTexture
  9      {
 10          public TextureCreateInfo Info;
 11          public TextureView View;
 12          public int RemainingFrames;
 13      }
 14  
 15      /// <summary>
 16      /// A structure for pooling resources that can be reused without recreation, such as textures.
 17      /// </summary>
 18      class ResourcePool : IDisposable
 19      {
 20          private const int DisposedLiveFrames = 2;
 21  
 22          private readonly object _lock = new();
 23          private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new();
 24  
 25          /// <summary>
 26          /// Add a texture that is not being used anymore to the resource pool to be used later.
 27          /// Both the texture's view and storage should be completely unused.
 28          /// </summary>
 29          /// <param name="view">The texture's view</param>
 30          public void AddTexture(TextureView view)
 31          {
 32              lock (_lock)
 33              {
 34                  if (!_textures.TryGetValue(view.Info, out List<DisposedTexture> list))
 35                  {
 36                      list = new List<DisposedTexture>();
 37                      _textures.Add(view.Info, list);
 38                  }
 39  
 40                  list.Add(new DisposedTexture()
 41                  {
 42                      Info = view.Info,
 43                      View = view,
 44                      RemainingFrames = DisposedLiveFrames,
 45                  });
 46              }
 47          }
 48  
 49          /// <summary>
 50          /// Attempt to obtain a texture from the resource cache with the desired parameters.
 51          /// </summary>
 52          /// <param name="info">The creation info for the desired texture</param>
 53          /// <returns>A TextureView with the description specified, or null if one was not found.</returns>
 54          public TextureView GetTextureOrNull(TextureCreateInfo info)
 55          {
 56              lock (_lock)
 57              {
 58                  if (!_textures.TryGetValue(info, out List<DisposedTexture> list))
 59                  {
 60                      return null;
 61                  }
 62  
 63                  foreach (DisposedTexture texture in list)
 64                  {
 65                      list.Remove(texture);
 66                      return texture.View;
 67                  }
 68  
 69                  return null;
 70              }
 71          }
 72  
 73          /// <summary>
 74          /// Update the pool, removing any resources that have expired.
 75          /// </summary>
 76          public void Tick()
 77          {
 78              lock (_lock)
 79              {
 80                  foreach (List<DisposedTexture> list in _textures.Values)
 81                  {
 82                      for (int i = 0; i < list.Count; i++)
 83                      {
 84                          DisposedTexture tex = list[i];
 85  
 86                          if (--tex.RemainingFrames < 0)
 87                          {
 88                              tex.View.Dispose();
 89                              list.RemoveAt(i--);
 90                          }
 91                      }
 92                  }
 93              }
 94          }
 95  
 96          /// <summary>
 97          /// Disposes the resource pool.
 98          /// </summary>
 99          public void Dispose()
100          {
101              lock (_lock)
102              {
103                  foreach (List<DisposedTexture> list in _textures.Values)
104                  {
105                      foreach (DisposedTexture texture in list)
106                      {
107                          texture.View.Dispose();
108                      }
109                  }
110                  _textures.Clear();
111              }
112          }
113      }
114  }