Added vmaImportVulkanFunctionsFromVolk

This commit is contained in:
Adam Sawicki 2025-04-09 18:11:44 +02:00
parent d8d4f86cc2
commit 412d69d269
6 changed files with 141 additions and 4 deletions

View file

@ -2469,7 +2469,8 @@ PREDEFINED = VMA_CALL_PRE= \
VMA_EXTERNAL_MEMORY_WIN32=1 \
VMA_EXTERNAL_MEMORY=1 \
VMA_EXTENDS_VK_STRUCT= \
VMA_STATS_STRING_ENABLED=1
VMA_STATS_STRING_ENABLED=1 \
VOLK_HEADER_VERSION=304
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

View file

@ -1669,6 +1669,20 @@ typedef struct VmaVirtualAllocationInfo
@{
*/
#ifdef VOLK_HEADER_VERSION
/** \brief Fully initializes `dst` structure with Vulkan functions needed by this library based on functions imported by
[volk library](https://github.com/zeux/volk).
If you use volk, call this function after `VkInstance` and `VkDevice` is created to fill in structure #VmaVulkanFunctions
before calling vmaCreateAllocator().
Pointers to functions related to the entire Vulkan instance are fetched using global function definitions.
Pointers to functions related to the Vulkan device are fetched using `volkLoadDeviceTable()` for given `device`.
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
VkDevice VMA_NOT_NULL device, VmaVulkanFunctions* VMA_NOT_NULL dst);
#endif
/// Creates #VmaAllocator object.
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo,
@ -15082,6 +15096,78 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
#ifndef _VMA_PUBLIC_INTERFACE
#ifdef VOLK_HEADER_VERSION
VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
VkDevice VMA_NOT_NULL device, VmaVulkanFunctions* VMA_NOT_NULL dst)
{
VolkDeviceTable src = {};
memset(&dst, 0, sizeof(dst));
memset(&src, 0, sizeof(src));
volkLoadDeviceTable(&src, device);
#define COPY_GLOBAL_TO_VMA_FUNC(volkName, vmaName) if(!dst->vmaName) dst->vmaName = volkName;
#define COPY_DEVICE_TO_VMA_FUNC(volkName, vmaName) if(!dst->vmaName) dst->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_DEVICE_TO_VMA_FUNC(vkAllocateMemory, vkAllocateMemory)
COPY_DEVICE_TO_VMA_FUNC(vkFreeMemory, vkFreeMemory)
COPY_DEVICE_TO_VMA_FUNC(vkMapMemory, vkMapMemory)
COPY_DEVICE_TO_VMA_FUNC(vkUnmapMemory, vkUnmapMemory)
COPY_DEVICE_TO_VMA_FUNC(vkFlushMappedMemoryRanges, vkFlushMappedMemoryRanges)
COPY_DEVICE_TO_VMA_FUNC(vkInvalidateMappedMemoryRanges, vkInvalidateMappedMemoryRanges)
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory, vkBindBufferMemory)
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory, vkBindImageMemory)
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements, vkGetBufferMemoryRequirements)
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements, vkGetImageMemoryRequirements)
COPY_DEVICE_TO_VMA_FUNC(vkCreateBuffer, vkCreateBuffer)
COPY_DEVICE_TO_VMA_FUNC(vkDestroyBuffer, vkDestroyBuffer)
COPY_DEVICE_TO_VMA_FUNC(vkCreateImage, vkCreateImage)
COPY_DEVICE_TO_VMA_FUNC(vkDestroyImage, vkDestroyImage)
COPY_DEVICE_TO_VMA_FUNC(vkCmdCopyBuffer, vkCmdCopyBuffer)
#if VMA_VULKAN_VERSION >= 1001000
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2, vkBindImageMemory2KHR)
#endif
#if VMA_VULKAN_VERSION >= 1003000
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirements)
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirements)
#endif
#if VMA_KHR_MAINTENANCE4
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirementsKHR, vkGetDeviceBufferMemoryRequirements)
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirementsKHR, vkGetDeviceImageMemoryRequirements)
#endif
#if VMA_DEDICATED_ALLOCATION
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2KHR, vkGetBufferMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2KHR, vkGetImageMemoryRequirements2KHR)
#endif
#if VMA_BIND_MEMORY2
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2KHR, vkBindBufferMemory2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2KHR, vkBindImageMemory2KHR)
#endif
#if VMA_MEMORY_BUDGET
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
#endif
#if VMA_EXTERNAL_MEMORY_WIN32
COPY_DEVICE_TO_VMA_FUNC(vkGetMemoryWin32HandleKHR, vkGetMemoryWin32HandleKHR)
#endif
#undef COPY_DEVICE_TO_VMA_FUNC
#undef COPY_GLOBAL_TO_VMA_FUNC
return VK_SUCCESS;
}
#endif // #ifdef VOLK_HEADER_VERSION
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
const VmaAllocatorCreateInfo* pCreateInfo,
VmaAllocator* pAllocator)

View file

@ -3902,6 +3902,11 @@ void TestHeapSizeLimit()
allocatorCreateInfo.device = g_hDevice;
allocatorCreateInfo.instance = g_hVulkanInstance;
allocatorCreateInfo.pHeapSizeLimit = heapSizeLimit;
#ifdef VOLK_HEADER_VERSION
VmaVulkanFunctions vulkanFunctions = {};
vmaImportVulkanFunctionsFromVolk(g_hDevice, &vulkanFunctions);
allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
#endif
#if VMA_DYNAMIC_VULKAN_FUNCTIONS
VmaVulkanFunctions vulkanFunctions = {};
vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;

View file

@ -96,7 +96,8 @@ include all public interface declarations. Example:
#pragma clang diagnostic ignored "-Wnullability-completeness"
#endif
#include <vulkan/vulkan.h>
//#include <vulkan/vulkan.h>
#include "third_party/volk-1.4.304/volk.h"
#ifdef _WIN32
#include <vulkan/vulkan_win32.h>

29
src/VolkUsage.cpp Normal file
View file

@ -0,0 +1,29 @@
//
// Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
/*
In exactly one CPP file define macro VMA_IMPLEMENTATION and then include
vk_mem_alloc.h to include definitions of its internal implementation
*/
#define VOLK_IMPLEMENTATION
#include "VmaUsage.h"

View file

@ -426,6 +426,8 @@ void VulkanUsage::Init()
g_Allocs = &g_CpuAllocationCallbacks;
}
ERR_GUARD_VULKAN(volkInitialize());
uint32_t instanceLayerPropCount = 0;
ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr) );
std::vector<VkLayerProperties> instanceLayerProps(instanceLayerPropCount);
@ -513,6 +515,8 @@ void VulkanUsage::Init()
ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, g_Allocs, &g_hVulkanInstance) );
volkLoadInstance(g_hVulkanInstance);
if(VK_EXT_debug_utils_enabled)
{
RegisterDebugCallbacks();
@ -1511,12 +1515,22 @@ void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
outInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
}
#if VMA_DYNAMIC_VULKAN_FUNCTIONS
#ifdef VOLK_HEADER_VERSION
static VmaVulkanFunctions vulkanFunctions = {};
vmaImportVulkanFunctionsFromVolk(g_hDevice, &vulkanFunctions);
outInfo.pVulkanFunctions = &vulkanFunctions;
#else // #ifdef VOLK_HEADER_VERSION
#if VMA_DYNAMIC_VULKAN_FUNCTIONS
v static VmaVulkanFunctions vulkanFunctions = {};
vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
outInfo.pVulkanFunctions = &vulkanFunctions;
#endif
#endif // #if VMA_DYNAMIC_VULKAN_FUNCTIONS
#endif // #ifdef VOLK_HEADER_VERSION
// Uncomment to enable HeapSizeLimit.
/*
@ -2083,6 +2097,7 @@ static void InitializeApplication()
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
volkLoadDevice(g_hDevice);
SetDebugUtilsObjectName(VK_OBJECT_TYPE_DEVICE, reinterpret_cast<std::uint64_t>(g_hDevice), "g_hDevice");
// Only now that SetDebugUtilsObjectName is loaded, we can assign a name to g_hVulkanInstance as well
SetDebugUtilsObjectName(VK_OBJECT_TYPE_INSTANCE, reinterpret_cast<std::uint64_t>(g_hVulkanInstance), "g_hVulkanInstance");