Added VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes
diff --git a/src/VulkanSample.cpp b/src/VulkanSample.cpp
index 1c31f07..3cae1bd 100644
--- a/src/VulkanSample.cpp
+++ b/src/VulkanSample.cpp
@@ -1179,6 +1179,19 @@
     heapSizeLimit[0] = 512ull * 1024 * 1024;

     outInfo.pHeapSizeLimit = heapSizeLimit.data();

     */

+

+    // External memory test

+    VkPhysicalDeviceMemoryProperties memProps = {};

+    vkGetPhysicalDeviceMemoryProperties(g_hPhysicalDevice, &memProps);

+    static VkExternalMemoryHandleTypeFlagsKHR externalMemoryHandleTypes[VK_MAX_MEMORY_TYPES] = {};

+    for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)

+    {

+        if(memProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)

+        {

+            externalMemoryHandleTypes[i] = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;

+        }

+    }

+    outInfo.pTypeExternalMemoryHandleTypes = externalMemoryHandleTypes;

 }

 

 static void PrintPhysicalDeviceProperties(const VkPhysicalDeviceProperties& properties)

diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h
index 18e644e..254f466 100644
--- a/src/vk_mem_alloc.h
+++ b/src/vk_mem_alloc.h
@@ -2451,6 +2451,17 @@
     Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.

     */

     uint32_t vulkanApiVersion;

+

+    /** \brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type.

+

+    If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount`

+    elements, defining external memory handle types of particular Vulkan memory type,

+    to be passed using `VkExportMemoryAllocateInfoKHR`.

+

+    Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type.\

+    This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL.

+    */

+    const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryTypeCount") pTypeExternalMemoryHandleTypes;

 } VmaAllocatorCreateInfo;

 

 /// Creates Allocator object.

@@ -8032,12 +8043,18 @@
     */

     uint32_t GetGpuDefragmentationMemoryTypeBits();

 

+    VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const

+    {

+        return m_TypeExternalMemoryHandleTypes[memTypeIndex];

+    }

+

 private:

     VkDeviceSize m_PreferredLargeHeapBlockSize;

 

     VkPhysicalDevice m_PhysicalDevice;

     VMA_ATOMIC_UINT32 m_CurrentFrameIndex;

     VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.

+    VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES];

     

     VMA_RW_MUTEX m_PoolsMutex;

     // Protected by m_PoolsMutex. Sorted by pointer value.

@@ -13289,6 +13306,14 @@
     }

 #endif // #if VMA_BUFFER_DEVICE_ADDRESS

 

+    // Attach VkExportMemoryAllocateInfoKHR if necessary.

+    VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR };

+    exportMemoryAllocInfo.handleTypes = m_hAllocator->GetExternalMemoryHandleTypeFlags(m_MemoryTypeIndex);

+    if(exportMemoryAllocInfo.handleTypes != 0)

+    {

+        VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo);

+    }

+

     VkDeviceMemory mem = VK_NULL_HANDLE;

     VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);

     if(res < 0)

@@ -15727,6 +15752,8 @@
     memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations));

     memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));

 

+    memset(&m_TypeExternalMemoryHandleTypes, 0, sizeof(m_TypeExternalMemoryHandleTypes));

+

     if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)

     {

         m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData;

@@ -15749,6 +15776,12 @@
 

     m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits();

 

+    if(pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL)

+    {

+        memcpy(m_TypeExternalMemoryHandleTypes, pCreateInfo->pTypeExternalMemoryHandleTypes,

+            sizeof(VkExternalMemoryHandleTypeFlagsKHR) * GetMemoryTypeCount());

+    }

+

     if(pCreateInfo->pHeapSizeLimit != VMA_NULL)

     {

         for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)

@@ -15784,7 +15817,6 @@
         // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,

         // becase minBlockCount is 0.

         m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));

-

     }

 }

 

@@ -16264,6 +16296,14 @@
     }

 #endif // #if VMA_BUFFER_DEVICE_ADDRESS

 

+    // Attach VkExportMemoryAllocateInfoKHR if necessary.

+    VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR };

+    exportMemoryAllocInfo.handleTypes = GetExternalMemoryHandleTypeFlags(memTypeIndex);

+    if(exportMemoryAllocInfo.handleTypes != 0)

+    {

+        VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo);

+    }

+

     size_t allocIndex;

     VkResult res = VK_SUCCESS;

     for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)