BufferPool.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. using System;
  2. namespace Ryujinx.Graphics.Vic.Image
  3. {
  4. class BufferPool<T>
  5. {
  6. /// <summary>
  7. /// Maximum number of buffers on the pool.
  8. /// </summary>
  9. private const int MaxBuffers = 4;
  10. /// <summary>
  11. /// Maximum size of a buffer that can be added on the pool.
  12. /// If the required buffer is larger than this, it won't be
  13. /// added to the pool to avoid long term high memory usage.
  14. /// </summary>
  15. private const int MaxBufferSize = 2048 * 2048;
  16. private struct PoolItem
  17. {
  18. public bool InUse;
  19. public T[] Buffer;
  20. }
  21. private readonly PoolItem[] _pool = new PoolItem[MaxBuffers];
  22. /// <summary>
  23. /// Rents a buffer with the exact size requested.
  24. /// </summary>
  25. /// <param name="length">Size of the buffer</param>
  26. /// <param name="buffer">Span of the requested size</param>
  27. /// <returns>The index of the buffer on the pool</returns>
  28. public int Rent(int length, out Span<T> buffer)
  29. {
  30. int index = RentMinimum(length, out T[] bufferArray);
  31. buffer = new Span<T>(bufferArray).Slice(0, length);
  32. return index;
  33. }
  34. /// <summary>
  35. /// Rents a buffer with a size greater than or equal to the requested size.
  36. /// </summary>
  37. /// <param name="length">Size of the buffer</param>
  38. /// <param name="buffer">Array with a length greater than or equal to the requested length</param>
  39. /// <returns>The index of the buffer on the pool</returns>
  40. public int RentMinimum(int length, out T[] buffer)
  41. {
  42. if ((uint)length > MaxBufferSize)
  43. {
  44. buffer = new T[length];
  45. return -1;
  46. }
  47. // Try to find a buffer that is larger or the same size of the requested one.
  48. // This will avoid an allocation.
  49. for (int i = 0; i < MaxBuffers; i++)
  50. {
  51. ref PoolItem item = ref _pool[i];
  52. if (!item.InUse && item.Buffer != null && item.Buffer.Length >= length)
  53. {
  54. buffer = item.Buffer;
  55. item.InUse = true;
  56. return i;
  57. }
  58. }
  59. buffer = new T[length];
  60. // Try to add the new buffer to the pool.
  61. // We try to find a slot that is not in use, and replace the buffer in it.
  62. for (int i = 0; i < MaxBuffers; i++)
  63. {
  64. ref PoolItem item = ref _pool[i];
  65. if (!item.InUse)
  66. {
  67. item.Buffer = buffer;
  68. item.InUse = true;
  69. return i;
  70. }
  71. }
  72. return -1;
  73. }
  74. /// <summary>
  75. /// Returns a buffer returned from <see cref="Rent(int)"/> to the pool.
  76. /// </summary>
  77. /// <param name="index">Index of the buffer on the pool</param>
  78. public void Return(int index)
  79. {
  80. if (index < 0)
  81. {
  82. return;
  83. }
  84. _pool[index].InUse = false;
  85. }
  86. }
  87. }