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