MemoryAllocator.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 PhysicalDevice _physicalDevice;
  11. private readonly Device _device;
  12. private readonly List<MemoryAllocatorBlockList> _blockLists;
  13. private readonly int _blockAlignment;
  14. private readonly PhysicalDeviceMemoryProperties _physicalDeviceMemoryProperties;
  15. public MemoryAllocator(Vk api, PhysicalDevice physicalDevice, Device device, uint maxMemoryAllocationCount)
  16. {
  17. _api = api;
  18. _physicalDevice = physicalDevice;
  19. _device = device;
  20. _blockLists = new List<MemoryAllocatorBlockList>();
  21. _blockAlignment = (int)Math.Min(int.MaxValue, MaxDeviceMemoryUsageEstimate / (ulong)maxMemoryAllocationCount);
  22. _api.GetPhysicalDeviceMemoryProperties(_physicalDevice, out _physicalDeviceMemoryProperties);
  23. }
  24. public MemoryAllocation AllocateDeviceMemory(
  25. MemoryRequirements requirements,
  26. MemoryPropertyFlags flags = 0)
  27. {
  28. return AllocateDeviceMemory(requirements, flags, flags);
  29. }
  30. public MemoryAllocation AllocateDeviceMemory(
  31. MemoryRequirements requirements,
  32. MemoryPropertyFlags flags,
  33. MemoryPropertyFlags alternativeFlags)
  34. {
  35. int memoryTypeIndex = FindSuitableMemoryTypeIndex(requirements.MemoryTypeBits, flags, alternativeFlags);
  36. if (memoryTypeIndex < 0)
  37. {
  38. return default;
  39. }
  40. bool map = flags.HasFlag(MemoryPropertyFlags.HostVisibleBit);
  41. return Allocate(memoryTypeIndex, requirements.Size, requirements.Alignment, map);
  42. }
  43. private MemoryAllocation Allocate(int memoryTypeIndex, ulong size, ulong alignment, bool map)
  44. {
  45. for (int i = 0; i < _blockLists.Count; i++)
  46. {
  47. var bl = _blockLists[i];
  48. if (bl.MemoryTypeIndex == memoryTypeIndex)
  49. {
  50. lock (bl)
  51. {
  52. return bl.Allocate(size, alignment, map);
  53. }
  54. }
  55. }
  56. var newBl = new MemoryAllocatorBlockList(_api, _device, memoryTypeIndex, _blockAlignment);
  57. _blockLists.Add(newBl);
  58. return newBl.Allocate(size, alignment, map);
  59. }
  60. private int FindSuitableMemoryTypeIndex(
  61. uint memoryTypeBits,
  62. MemoryPropertyFlags flags,
  63. MemoryPropertyFlags alternativeFlags)
  64. {
  65. int bestCandidateIndex = -1;
  66. for (int i = 0; i < _physicalDeviceMemoryProperties.MemoryTypeCount; i++)
  67. {
  68. var type = _physicalDeviceMemoryProperties.MemoryTypes[i];
  69. if ((memoryTypeBits & (1 << i)) != 0)
  70. {
  71. if (type.PropertyFlags.HasFlag(flags))
  72. {
  73. return i;
  74. }
  75. else if (type.PropertyFlags.HasFlag(alternativeFlags))
  76. {
  77. bestCandidateIndex = i;
  78. }
  79. }
  80. }
  81. return bestCandidateIndex;
  82. }
  83. public void Dispose()
  84. {
  85. for (int i = 0; i < _blockLists.Count; i++)
  86. {
  87. _blockLists[i].Dispose();
  88. }
  89. }
  90. }
  91. }