aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/MemoryAllocator.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/MemoryAllocator.cs84
1 files changed, 84 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs b/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs
new file mode 100644
index 00000000..0b05ef92
--- /dev/null
+++ b/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs
@@ -0,0 +1,84 @@
+using Silk.NET.Vulkan;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Vulkan
+{
+ class MemoryAllocator : IDisposable
+ {
+ private ulong MaxDeviceMemoryUsageEstimate = 16UL * 1024 * 1024 * 1024;
+
+ private readonly Vk _api;
+ private readonly Device _device;
+ private readonly List<MemoryAllocatorBlockList> _blockLists;
+
+ private int _blockAlignment;
+
+ public MemoryAllocator(Vk api, Device device, uint maxMemoryAllocationCount)
+ {
+ _api = api;
+ _device = device;
+ _blockLists = new List<MemoryAllocatorBlockList>();
+ _blockAlignment = (int)Math.Min(int.MaxValue, MaxDeviceMemoryUsageEstimate / (ulong)maxMemoryAllocationCount);
+ }
+
+ public MemoryAllocation AllocateDeviceMemory(
+ PhysicalDevice physicalDevice,
+ MemoryRequirements requirements,
+ MemoryPropertyFlags flags = 0)
+ {
+ int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags);
+ if (memoryTypeIndex < 0)
+ {
+ return default;
+ }
+
+ bool map = flags.HasFlag(MemoryPropertyFlags.MemoryPropertyHostVisibleBit);
+ return Allocate(memoryTypeIndex, requirements.Size, requirements.Alignment, map);
+ }
+
+ private MemoryAllocation Allocate(int memoryTypeIndex, ulong size, ulong alignment, bool map)
+ {
+ for (int i = 0; i < _blockLists.Count; i++)
+ {
+ var bl = _blockLists[i];
+ if (bl.MemoryTypeIndex == memoryTypeIndex)
+ {
+ lock (bl)
+ {
+ return bl.Allocate(size, alignment, map);
+ }
+ }
+ }
+
+ var newBl = new MemoryAllocatorBlockList(_api, _device, memoryTypeIndex, _blockAlignment);
+ _blockLists.Add(newBl);
+ return newBl.Allocate(size, alignment, map);
+ }
+
+ private static int FindSuitableMemoryTypeIndex(Vk api, PhysicalDevice physicalDevice, uint memoryTypeBits, MemoryPropertyFlags flags)
+ {
+ api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties);
+
+ for (int i = 0; i < properties.MemoryTypeCount; i++)
+ {
+ var type = properties.MemoryTypes[i];
+
+ if ((memoryTypeBits & (1 << i)) != 0 && type.PropertyFlags.HasFlag(flags))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void Dispose()
+ {
+ for (int i = 0; i < _blockLists.Count; i++)
+ {
+ _blockLists[i].Dispose();
+ }
+ }
+ }
+}