MemoryAllocator.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using Silk.NET.Vulkan;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Vulkan
  5. {
  6. class MemoryAllocator : IDisposable
  7. {
  8. private ulong MaxDeviceMemoryUsageEstimate = 16UL * 1024 * 1024 * 1024;
  9. private readonly Vk _api;
  10. private readonly Device _device;
  11. private readonly List<MemoryAllocatorBlockList> _blockLists;
  12. private int _blockAlignment;
  13. public MemoryAllocator(Vk api, Device device, uint maxMemoryAllocationCount)
  14. {
  15. _api = api;
  16. _device = device;
  17. _blockLists = new List<MemoryAllocatorBlockList>();
  18. _blockAlignment = (int)Math.Min(int.MaxValue, MaxDeviceMemoryUsageEstimate / (ulong)maxMemoryAllocationCount);
  19. }
  20. public MemoryAllocation AllocateDeviceMemory(
  21. PhysicalDevice physicalDevice,
  22. MemoryRequirements requirements,
  23. MemoryPropertyFlags flags = 0)
  24. {
  25. int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags);
  26. if (memoryTypeIndex < 0)
  27. {
  28. return default;
  29. }
  30. bool map = flags.HasFlag(MemoryPropertyFlags.MemoryPropertyHostVisibleBit);
  31. return Allocate(memoryTypeIndex, requirements.Size, requirements.Alignment, map);
  32. }
  33. private MemoryAllocation Allocate(int memoryTypeIndex, ulong size, ulong alignment, bool map)
  34. {
  35. for (int i = 0; i < _blockLists.Count; i++)
  36. {
  37. var bl = _blockLists[i];
  38. if (bl.MemoryTypeIndex == memoryTypeIndex)
  39. {
  40. lock (bl)
  41. {
  42. return bl.Allocate(size, alignment, map);
  43. }
  44. }
  45. }
  46. var newBl = new MemoryAllocatorBlockList(_api, _device, memoryTypeIndex, _blockAlignment);
  47. _blockLists.Add(newBl);
  48. return newBl.Allocate(size, alignment, map);
  49. }
  50. private static int FindSuitableMemoryTypeIndex(Vk api, PhysicalDevice physicalDevice, uint memoryTypeBits, MemoryPropertyFlags flags)
  51. {
  52. api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties);
  53. for (int i = 0; i < properties.MemoryTypeCount; i++)
  54. {
  55. var type = properties.MemoryTypes[i];
  56. if ((memoryTypeBits & (1 << i)) != 0 && type.PropertyFlags.HasFlag(flags))
  57. {
  58. return i;
  59. }
  60. }
  61. return -1;
  62. }
  63. public void Dispose()
  64. {
  65. for (int i = 0; i < _blockLists.Count; i++)
  66. {
  67. _blockLists[i].Dispose();
  68. }
  69. }
  70. }
  71. }