/ src / Ryujinx.Graphics.Nvdec.Vp9 / Common / MemoryAllocator.cs
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  }