fix issue 546: vmaImportVulkanFunctionsFromVolk() leaves vkGetPhysicalDevice* pointers null with volk's table API
diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h
index f2b58bf..493e04e 100644
--- a/include/vk_mem_alloc.h
+++ b/include/vk_mem_alloc.h
@@ -1355,7 +1355,7 @@
     /** \brief Additional minimum alignment to be used for this allocation. Can be 0.
 
     Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
-    
+
     When creating a buffer or an image, specifying a custom alignment is not needed in most cases,
     because Vulkan implementation inspects the `CreateInfo` structure (including intended usage flags)
     and returns required alignment through functions like `vkGetBufferMemoryRequirements2`, which VMA automatically
@@ -1505,17 +1505,17 @@
 typedef struct VmaAllocationInfo2
 {
     /** \brief Basic parameters of the allocation.
-    
+
     If you need only these, you can use function vmaGetAllocationInfo() and structure #VmaAllocationInfo instead.
     */
     VmaAllocationInfo allocationInfo;
     /** \brief Size of the `VkDeviceMemory` block that the allocation belongs to.
-    
+
     In case of an allocation with dedicated memory, it will be equal to `allocationInfo.size`.
     */
     VkDeviceSize blockSize;
     /** \brief `VK_TRUE` if the allocation has dedicated memory, `VK_FALSE` if it was placed as part of a larger memory block.
-    
+
     When `VK_TRUE`, it also means `VkMemoryDedicatedAllocateInfo` was used when creating the allocation
     (if VK_KHR_dedicated_allocation extension or Vulkan version >= 1.1 is enabled).
     */
@@ -2241,8 +2241,8 @@
 */
 VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(
     VmaAllocator VMA_NOT_NULL allocator,
-    VmaAllocation VMA_NOT_NULL allocation, 
-    HANDLE hTargetProcess, 
+    VmaAllocation VMA_NOT_NULL allocation,
+    HANDLE hTargetProcess,
     HANDLE* VMA_NOT_NULL pHandle);
 
 /**
@@ -2291,9 +2291,9 @@
 */
 VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle2(
     VmaAllocator VMA_NOT_NULL allocator,
-    VmaAllocation VMA_NOT_NULL allocation, 
-    VkExternalMemoryHandleTypeFlagBits handleType, 
-    HANDLE hTargetProcess, 
+    VmaAllocation VMA_NOT_NULL allocation,
+    VkExternalMemoryHandleTypeFlagBits handleType,
+    HANDLE hTargetProcess,
     HANDLE* VMA_NOT_NULL pHandle);
 #endif // VMA_EXTERNAL_MEMORY_WIN32
 
@@ -2779,7 +2779,7 @@
 \param allocator
 \param allocation Allocation that provides memory to be used for binding new buffer to it.
 \param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the allocation. Normally it should be 0.
-\param pBufferCreateInfo 
+\param pBufferCreateInfo
 \param[out] pBuffer Buffer that was created.
 
 This function automatically:
@@ -6447,7 +6447,7 @@
 {
 public:
     VmaWin32Handle() noexcept : m_hHandle(VMA_NULL) { }
-    explicit VmaWin32Handle(HANDLE hHandle) noexcept 
+    explicit VmaWin32Handle(HANDLE hHandle) noexcept
         : m_hHandle(hHandle)
         , m_IsNTHandle(IsNTHandle(hHandle))
     {
@@ -6521,7 +6521,7 @@
     VMA_RW_MUTEX m_Mutex; // Protects access m_Handle
     bool m_IsNTHandle = false; // True if m_Handle is NT handle, false if it's a KMT handle.
 };
-#else 
+#else
 class VmaWin32Handle
 {
     // ABI compatibility
@@ -7226,14 +7226,14 @@
     Checks whether an allocation placed in a free block would conflict with existing
     allocations due to buffer-image granularity requirements and, if needed, aligns the
     allocation start to the next granularity page.
-    
+
     Parameters:
     - inOutAllocOffset: candidate allocation offset inside the block; may be increased.
     - allocSize: size of the allocation being placed.
     - blockOffset: start offset of the free block being considered.
     - blockSize: size of the free block being considered.
     - allocType: VmaSuballocationType of the allocation being placed.
-    
+
     Returns true when the placement conflicts or no longer fits in the free block after alignment.
     Returns false when the placement is valid, possibly after updating inOutAllocOffset.
     */
@@ -14646,7 +14646,7 @@
     // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
     if(res != VK_SUCCESS)
         return res;
-    
+
     do
     {
         VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex];
@@ -15676,17 +15676,26 @@
     VMA_ASSERT(pAllocatorCreateInfo->device != VK_NULL_HANDLE);
 
     memset(pDstVulkanFunctions, 0, sizeof(*pDstVulkanFunctions));
-    
+
     VolkDeviceTable src = {};
     volkLoadDeviceTable(&src, pAllocatorCreateInfo->device);
 
 #define COPY_GLOBAL_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = volkName;
+
+#if VOLK_HEADER_VERSION > 335
+    VolkInstanceTable instSrc = {};
+    volkLoadInstanceTable(&instSrc, pAllocatorCreateInfo->instance);
+#define COPY_INSTANCE_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = instSrc.volkName;
+#else
+#define COPY_INSTANCE_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = volkName;
+#endif
+
 #define COPY_DEVICE_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = src.volkName;
 
     COPY_GLOBAL_TO_VMA_FUNC(vkGetInstanceProcAddr, vkGetInstanceProcAddr)
-    COPY_GLOBAL_TO_VMA_FUNC(vkGetDeviceProcAddr, vkGetDeviceProcAddr)
-    COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties)
-    COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties, vkGetPhysicalDeviceMemoryProperties)
+    COPY_INSTANCE_TO_VMA_FUNC(vkGetDeviceProcAddr, vkGetDeviceProcAddr)
+    COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties)
+    COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties, vkGetPhysicalDeviceMemoryProperties)
     COPY_DEVICE_TO_VMA_FUNC(vkAllocateMemory, vkAllocateMemory)
     COPY_DEVICE_TO_VMA_FUNC(vkFreeMemory, vkFreeMemory)
     COPY_DEVICE_TO_VMA_FUNC(vkMapMemory, vkMapMemory)
@@ -15705,8 +15714,8 @@
 #if VMA_VULKAN_VERSION >= 1001000
     if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
     {
-        COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
-        COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
+        COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
+        COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
         COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
         COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
         COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
@@ -15744,8 +15753,8 @@
 #if VMA_MEMORY_BUDGET
     if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
     {
-        COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
-        COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2KHR, vkGetPhysicalDeviceProperties2KHR)
+        COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
+        COPY_INSTANCE_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2KHR, vkGetPhysicalDeviceProperties2KHR)
     }
 #endif
 #if VMA_EXTERNAL_MEMORY_WIN32
@@ -15756,6 +15765,7 @@
 #endif
 
 #undef COPY_DEVICE_TO_VMA_FUNC
+#undef COPY_INSTANCE_TO_VMA_FUNC
 #undef COPY_GLOBAL_TO_VMA_FUNC
 
     return VK_SUCCESS;
@@ -16157,7 +16167,7 @@
             VmaBufferImageUsage(*pImageCreateInfo), pMemoryTypeIndex);
     }
 #endif // VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000
-    
+
     // Must create a dummy image to query :(
     VkImage hImage = VK_NULL_HANDLE;
     res = funcs->vkCreateImage(
@@ -17256,7 +17266,7 @@
     VMA_DEBUG_GLOBAL_MUTEX_LOCK;
     return allocation->GetWin32Handle(allocator, handleType, hTargetProcess, pHandle);
 }
-#endif // VMA_EXTERNAL_MEMORY_WIN32 
+#endif // VMA_EXTERNAL_MEMORY_WIN32
 #endif // VMA_STATS_STRING_ENABLED
 #endif // _VMA_PUBLIC_INTERFACE
 #endif // VMA_IMPLEMENTATION
@@ -19174,7 +19184,7 @@
 vmaDestroyBuffer(g_Allocator, buf, alloc);
 \endcode
 
-If you need each allocation to have its own device memory block and start at offset 0, you can still do 
+If you need each allocation to have its own device memory block and start at offset 0, you can still do
 by using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag. It works also with custom pools.
 
 Alternatively, you can use convenient functions vmaCreateDedicatedBuffer(), vmaCreateDedicatedImage() that