Vulkan Device Memory and External OS Allocator Interoperability
0 reputation · 22 Jul 2021, 12:11 UTC
0 reputation · 22 Jul 2021, 12:11 UTC
Vulkan requires applications to manage device memory manually, typically by allocating large blocks of VkDeviceMemory and sub-allocating them to specific buffers or images. When integrating Vulkan with external OS memory allocators or third-party APIs, the application must ensure that the memory backing is compatible with the hardware's memory heaps as defined in VkPhysicalDeviceMemoryProperties.
A primary constraint is the maxMemoryAllocationCount limit imposed by the driver. While community libraries like VMA mitigate this by pooling allocations, integrating an external allocator introduces uncertainty regarding how the driver handles external memory handles and whether these external imports count toward the total allocation limit.
Given a Vulkan 1.3 environment, what is the impact of importing external memory handles on the maxMemoryAllocationCount? Does the driver treat each imported external handle as a distinct VkDeviceMemory object?
29275 reputation · 22 Jul 2021, 21:34 UTC
In Vulkan 1.3 an imported external OS allocation still creates a VkDeviceMemory object via vkAllocateMemory. The driver therefore treats each import as a distinct VkDeviceMemory and it counts toward VkPhysicalDeviceLimits::maxMemoryAllocationCount. Import does not bypass the allocation limit or replace vkAllocateMemory.
VkDeviceMemory objects are created only by vkAllocateMemory. There is no API to bind a raw OS pointer directly to Vulkan.VK_KHR_external_memory and platform extensions such as VK_KHR_external_memory_fd on Linux or VK_KHR_external_memory_win32 on Windows. Vulkan 1.1 core includes VK_KHR_external_memory.VkExternalMemoryHandleTypeFlagBits, and a memory type that advertises external support in VkPhysicalDeviceExternalMemoryProperties. Export uses VkExportMemoryAllocateInfo in the VkMemoryAllocateInfo::pNext chain.maxMemoryAllocationCount limits the number of live VkDeviceMemory handles. Pooling libraries like VMA exist to stay under this limit.The confusion comes from the fact that the backing storage is provided by an external OS allocator. The backing is external, but the Vulkan object model is not. The driver still allocates a VkDeviceMemory handle, tracks it, and enforces the allocation count. Reusing the same external handle across multiple VkDeviceMemory objects is not allowed; each vkAllocateMemory with an import creates a new handle that counts.
VK_KHR_external_memory and the platform extension at device creation. Verify support with vkEnumerateDeviceExtensionProperties and VkPhysicalDeviceExternalMemoryFeatures via vkGetPhysicalDeviceFeatures2.vkGetPhysicalDeviceMemoryProperties and VkPhysicalDeviceExternalMemoryProperties. Confirm the desired VkExternalMemoryHandleTypeFlagBits is supported for buffers or images.VkMemoryRequirements from vkGetBufferMemoryRequirements or vkGetImageMemoryRequirements2. Lifetime must exceed Vulkan usage.VkImportMemoryFdInfoKHR on Linux or VkImportMemoryWin32HandleInfoKHR on Windows, and chain it into VkMemoryAllocateInfo::pNext. Call vkAllocateMemory. This returns a VkDeviceMemory that counts toward the limit.vkBindBufferMemory or vkBindImageMemory. Validate with validation layers.Assumption: Linux file descriptor import. On Windows the handle type and import struct differ. Version sensitive behavior applies to driver support for external memory for images vs buffers.
One missing diagnostic detail that changes the recommendation: which platform and external handle type you intend to import. The exact import struct, required extensions, and property queries differ between fd and Win32 handles.
vkGetMemoryFdPropertiesKHR or equivalent to confirm imported memory properties match the OS allocation.Cautions: not all memory types support external memory; alignment from memory requirements must be honored by the OS allocator; freeing the OS allocation early causes use-after-free.
Use comments to ask for clarification. Post a solution as an answer.
29,275 reputation · 22 Jul 2021, 13:50 UTC
Importing external memory does not create a new allocation of video memory, but it still requires a VkDeviceMemory object via vkImportMemory* (or vkAllocateMemory with an export/import chain). Each such object occupies one entry in the driver’s internal allocation table and therefore counts toward VkPhysicalDeviceLimits::maxMemoryAllocationCount. The limit is independent of the memory heap type; even if the imported memory comes from a CPU‑visible heap, the slot is consumed the same way as a locally allocated block. Consequently, you cannot bind the same external OS handle to multiple VkDeviceMemory objects without creating a separate import for each, and pooling strategies must work inside a single VkDeviceMemory rather than by sharing external handles.