MemoryAllocator.cs
1 using Ryujinx.Common.Memory; 2 using System; 3 using System.Runtime.CompilerServices; 4 using System.Runtime.InteropServices; 5 6 namespace Ryujinx.Graphics.Nvdec.Vp9.Common 7 { 8 internal class MemoryAllocator : IDisposable 9 { 10 private const int PoolEntries = 10; 11 12 private struct PoolItem 13 { 14 public IntPtr Pointer; 15 public int Length; 16 public bool InUse; 17 } 18 19 private readonly PoolItem[] _pool = new PoolItem[PoolEntries]; 20 21 public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged 22 { 23 int lengthInBytes = Unsafe.SizeOf<T>() * length; 24 25 IntPtr ptr = IntPtr.Zero; 26 27 for (int i = 0; i < PoolEntries; i++) 28 { 29 ref PoolItem item = ref _pool[i]; 30 31 if (!item.InUse && item.Length == lengthInBytes) 32 { 33 item.InUse = true; 34 ptr = item.Pointer; 35 break; 36 } 37 } 38 39 if (ptr == IntPtr.Zero) 40 { 41 ptr = Marshal.AllocHGlobal(lengthInBytes); 42 43 for (int i = 0; i < PoolEntries; i++) 44 { 45 ref PoolItem item = ref _pool[i]; 46 47 if (!item.InUse) 48 { 49 item.InUse = true; 50 if (item.Pointer != IntPtr.Zero) 51 { 52 Marshal.FreeHGlobal(item.Pointer); 53 } 54 item.Pointer = ptr; 55 item.Length = lengthInBytes; 56 break; 57 } 58 } 59 } 60 61 return new ArrayPtr<T>(ptr, length); 62 } 63 64 public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged 65 { 66 IntPtr ptr = (IntPtr)arr.ToPointer(); 67 68 for (int i = 0; i < PoolEntries; i++) 69 { 70 ref PoolItem item = ref _pool[i]; 71 72 if (item.Pointer == ptr) 73 { 74 item.InUse = false; 75 break; 76 } 77 } 78 } 79 80 public void Dispose() 81 { 82 for (int i = 0; i < PoolEntries; i++) 83 { 84 ref PoolItem item = ref _pool[i]; 85 86 if (item.Pointer != IntPtr.Zero) 87 { 88 Marshal.FreeHGlobal(item.Pointer); 89 item.Pointer = IntPtr.Zero; 90 } 91 } 92 } 93 } 94 }