PoolCache.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Gpu.Image
  4. {
  5. /// <summary>
  6. /// Resource pool interface.
  7. /// </summary>
  8. /// <typeparam name="T">Resource pool type</typeparam>
  9. interface IPool<T>
  10. {
  11. /// <summary>
  12. /// Start address of the pool in memory.
  13. /// </summary>
  14. ulong Address { get; }
  15. /// <summary>
  16. /// Linked list node used on the texture pool cache.
  17. /// </summary>
  18. LinkedListNode<T> CacheNode { get; set; }
  19. /// <summary>
  20. /// Timestamp set on the last use of the pool by the cache.
  21. /// </summary>
  22. ulong CacheTimestamp { get; set; }
  23. }
  24. /// <summary>
  25. /// Pool cache.
  26. /// This can keep multiple pools, and return the current one as needed.
  27. /// </summary>
  28. abstract class PoolCache<T> : IDisposable where T : IPool<T>, IDisposable
  29. {
  30. private const int MaxCapacity = 2;
  31. private const ulong MinDeltaForRemoval = 20000;
  32. private readonly GpuContext _context;
  33. private readonly LinkedList<T> _pools;
  34. private ulong _currentTimestamp;
  35. /// <summary>
  36. /// Constructs a new instance of the pool.
  37. /// </summary>
  38. /// <param name="context">GPU context that the texture pool belongs to</param>
  39. public PoolCache(GpuContext context)
  40. {
  41. _context = context;
  42. _pools = new LinkedList<T>();
  43. }
  44. /// <summary>
  45. /// Increments the internal timestamp of the cache that is used to decide when old resources will be deleted.
  46. /// </summary>
  47. public void Tick()
  48. {
  49. _currentTimestamp++;
  50. }
  51. /// <summary>
  52. /// Finds a cache texture pool, or creates a new one if not found.
  53. /// </summary>
  54. /// <param name="channel">GPU channel that the texture pool cache belongs to</param>
  55. /// <param name="address">Start address of the texture pool</param>
  56. /// <param name="maximumId">Maximum ID of the texture pool</param>
  57. /// <returns>The found or newly created texture pool</returns>
  58. public T FindOrCreate(GpuChannel channel, ulong address, int maximumId)
  59. {
  60. // Remove old entries from the cache, if possible.
  61. while (_pools.Count > MaxCapacity && (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval)
  62. {
  63. T oldestPool = _pools.First.Value;
  64. _pools.RemoveFirst();
  65. oldestPool.Dispose();
  66. oldestPool.CacheNode = null;
  67. }
  68. T pool;
  69. // Try to find the pool on the cache.
  70. for (LinkedListNode<T> node = _pools.First; node != null; node = node.Next)
  71. {
  72. pool = node.Value;
  73. if (pool.Address == address)
  74. {
  75. if (pool.CacheNode != _pools.Last)
  76. {
  77. _pools.Remove(pool.CacheNode);
  78. pool.CacheNode = _pools.AddLast(pool);
  79. }
  80. pool.CacheTimestamp = _currentTimestamp;
  81. return pool;
  82. }
  83. }
  84. // If not found, create a new one.
  85. pool = CreatePool(_context, channel, address, maximumId);
  86. pool.CacheNode = _pools.AddLast(pool);
  87. pool.CacheTimestamp = _currentTimestamp;
  88. return pool;
  89. }
  90. /// <summary>
  91. /// Creates a new instance of the pool.
  92. /// </summary>
  93. /// <param name="context">GPU context that the pool belongs to</param>
  94. /// <param name="channel">GPU channel that the pool belongs to</param>
  95. /// <param name="address">Address of the pool in guest memory</param>
  96. /// <param name="maximumId">Maximum ID of the pool (equal to maximum minus one)</param>
  97. protected abstract T CreatePool(GpuContext context, GpuChannel channel, ulong address, int maximumId);
  98. public void Dispose()
  99. {
  100. foreach (T pool in _pools)
  101. {
  102. pool.Dispose();
  103. pool.CacheNode = null;
  104. }
  105. _pools.Clear();
  106. }
  107. }
  108. }