using System; namespace Ryujinx.Graphics.Vic.Image { class BufferPool { /// /// Maximum number of buffers on the pool. /// private const int MaxBuffers = 4; /// /// Maximum size of a buffer that can be added on the pool. /// If the required buffer is larger than this, it won't be /// added to the pool to avoid long term high memory usage. /// private const int MaxBufferSize = 2048 * 2048; private struct PoolItem { public bool InUse; public T[] Buffer; } private readonly PoolItem[] _pool = new PoolItem[MaxBuffers]; /// /// Rents a buffer with the exact size requested. /// /// Size of the buffer /// Span of the requested size /// The index of the buffer on the pool public int Rent(int length, out Span buffer) { int index = RentMinimum(length, out T[] bufferArray); buffer = new Span(bufferArray).Slice(0, length); return index; } /// /// Rents a buffer with a size greater than or equal to the requested size. /// /// Size of the buffer /// Array with a length greater than or equal to the requested length /// The index of the buffer on the pool public int RentMinimum(int length, out T[] buffer) { if ((uint)length > MaxBufferSize) { buffer = new T[length]; return -1; } // Try to find a buffer that is larger or the same size of the requested one. // This will avoid an allocation. for (int i = 0; i < MaxBuffers; i++) { ref PoolItem item = ref _pool[i]; if (!item.InUse && item.Buffer != null && item.Buffer.Length >= length) { buffer = item.Buffer; item.InUse = true; return i; } } buffer = new T[length]; // Try to add the new buffer to the pool. // We try to find a slot that is not in use, and replace the buffer in it. for (int i = 0; i < MaxBuffers; i++) { ref PoolItem item = ref _pool[i]; if (!item.InUse) { item.Buffer = buffer; item.InUse = true; return i; } } return -1; } /// /// Returns a buffer returned from to the pool. /// /// Index of the buffer on the pool public void Return(int index) { if (index < 0) { return; } _pool[index].InUse = false; } } }