VMA memory type selection: controlling allocation strategy across discrete and integrated GPUs
0 reputation · 06 May 2026, 02:29 UTC
0 reputation · 06 May 2026, 02:29 UTC
I am using the Vulkan Memory Allocator (VMA) to manage VkDeviceMemory for buffers and images, and I need predictable memory type selection across both discrete and integrated GPUs. VMA automates the choice of memory type from vkGetPhysicalDeviceMemoryProperties based on usage flags, but the 'optimal' type differs by hardware architecture — for example, HOST_VISIBLE memory that is also DEVICE_LOCAL (resizable BAR / unified memory) behaves very differently from a discrete card's separate host-visible pool.
My constraint is that I want staging buffers to prefer host-visible memory while device-only resources stay DEVICE_LOCAL, without hardcoding memory type indices, since those indices vary per device. I also need to respect the per-resource VkMemoryRequirements alignment, and I am unsure how VMA's pool and budget settings interact with driver limits on the number of live allocations.
Assume Vulkan 1.2+ and a recent VMA release; I plan to verify behavior with the validation layers.
Specifically:
VmaPool be configured so one resource category cannot exhaust the allocation budget of another?Use VMA’s *usage* enums, not hard‑coded type indices. For staging buffers you should request
VMA_MEMORY_USAGE_AUTO_PREFER_HOST (or the synonym
VMA_MEMORY_USAGE_CPU_TO_GPU). This tells VMA to try a memory type that has
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT first; if none is available it will automatically
choose a device‑local type that satisfies the other required flags.
For resources that must stay on the device you use
VMA_MEMORY_USAGE_GPU_ONLY. If you need stronger host‑side access patterns you can add
VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT or
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT to the allocation flags.
These flags do not override the usage enum, they only provide additional hints to the
allocator.
Create two distinct VmaPools:
memoryTypeBits to the bitmask of memory types that have
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT but not HOST_VISIBLE. Supply a
maxAllocationSize or maxBlockCount that matches the expected device‑only usage.
memoryTypeBits to the host‑visible set (and optionally
include DEVICE_LOCAL if you want the fallback). Give it a larger or unlimited
budget so that host‑visible allocations cannot be starved.
When you call vmaCreateAllocation you can pass the pool handle in
VmaAllocationCreateInfo::pool. Because each pool has its own limits, an allocation
that would exceed the device‑only pool’s maxBlockCount will either fail or be routed to
the staging pool if you set VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT accordingly.
This guarantees that one category cannot deplete the other’s budget.
After allocation you can call:
VmaAllocationInfo info;
vmaGetAllocationInfo(allocator, allocation, &info);
uint32_t chosenType = info.memoryTypeIndex;
The memoryTypeIndex field corresponds to the index returned by
vkGetPhysicalDeviceMemoryProperties and reflects the actual type VMA selected. Logging
this value lets you confirm that the allocator behaved as expected, especially when you
enable the Vulkan validation layers which will warn if a requested type is unavailable.
VmaAllocatorCreateInfo ai = {};
ai.flags = VMA_ALLOCATOR_CREATE_DEBUG_LOG_BIT;
VMA_MEMORY_USAGE_AUTO_PREFER_HOST and verify that
info.memoryTypeIndex has the HOST_VISIBLE flag set. If the device lacks a
host‑visible type, the index should correspond to a device‑local type.
maxBlockCount
is reached; subsequent allocations should fail or spill to the staging pool.
Do you need to know whether the physical device exposes a memory type that is both
HOST_VISIBLE and DEVICE_LOCAL? This determines whether the fallback path is
necessary on your target hardware. If you can provide that information, it can refine
the pool configuration or the choice of usage enum.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.