Skip to content

Commit 49322c0

Browse files
More work on function vmaImportVulkanFunctionsFromVolk
Also added Cmake option VMA_VOLK_HEADER_PATH. Also updated the documentation.
1 parent 412d69d commit 49322c0

File tree

6 files changed

+129
-46
lines changed

6 files changed

+129
-46
lines changed

include/vk_mem_alloc.h

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,17 +1670,55 @@ typedef struct VmaVirtualAllocationInfo
16701670
*/
16711671

16721672
#ifdef VOLK_HEADER_VERSION
1673-
/** \brief Fully initializes `dst` structure with Vulkan functions needed by this library based on functions imported by
1673+
/** \brief Fully initializes `pDstVulkanFunctions` structure with Vulkan functions needed by this library based on functions imported by
16741674
[volk library](https://github.com/zeux/volk).
16751675

1676-
If you use volk, call this function after `VkInstance` and `VkDevice` is created to fill in structure #VmaVulkanFunctions
1677-
before calling vmaCreateAllocator().
1676+
This function is defined in VMA header only if "volk.h" was included before it.
16781677

1679-
Pointers to functions related to the entire Vulkan instance are fetched using global function definitions.
1680-
Pointers to functions related to the Vulkan device are fetched using `volkLoadDeviceTable()` for given `device`.
1678+
To use this function properly:
1679+
1680+
-# Create `VkInstance` and `VkDevice` object.
1681+
-# Fill in structure #VmaAllocatorCreateInfo, especially members:
1682+
- VmaAllocatorCreateInfo::device
1683+
- VmaAllocatorCreateInfo::vulkanApiVersion
1684+
- VmaAllocatorCreateInfo::flags - set appropriate flags for the Vulkan extensions you enabled
1685+
-# Define structure #VmaVulkanFunctions.
1686+
-# Call this function.
1687+
Parameter `pAllocatorCreateInfo` is read to find out which functions should be fetched for
1688+
appropriate Vulkan version and extensions.
1689+
Parameter `pDstVulkanFunctions` is filled with those function pointers.
1690+
Others are set to null.
1691+
-# Attach the #VmaVulkanFunctions structure to VmaAllocatorCreateInfo::pVulkanFunctions.
1692+
-# Call vmaCreateAllocator() to create the #VmaAllocator object.
1693+
1694+
Example:
1695+
1696+
\code
1697+
VmaAllocatorCreateInfo allocatorCreateInfo = {};
1698+
allocatorCreateInfo.physicalDevice = myPhysivcalDevice;
1699+
allocatorCreateInfo.device = myDevice;
1700+
allocatorCreateInfo.instance = myInstance;
1701+
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_3;
1702+
allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT |
1703+
VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT |
1704+
VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT;
1705+
1706+
VmaVulkanFunctions vulkanFunctions;
1707+
VkResult res = vmaImportVulkanFunctionsFromVolk(&allocatorCreateInfo, &vulkanFunctions);
1708+
// Check res...
1709+
allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
1710+
1711+
VmaAllocator allocator;
1712+
res = vmaCreateAllocator(&allocatorCreateInfo, &allocator);
1713+
// Check res...
1714+
\endcode
1715+
1716+
Internally in this function, pointers to functions related to the entire Vulkan instance are fetched using global function definitions,
1717+
while pointers to functions related to the Vulkan device are fetched using `volkLoadDeviceTable()` for given `pAllocatorCreateInfo->device`.
16811718
*/
16821719
VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
1683-
VkDevice VMA_NOT_NULL device, VmaVulkanFunctions* VMA_NOT_NULL dst);
1720+
const VmaAllocatorCreateInfo* VMA_NOT_NULL pAllocatorCreateInfo,
1721+
VmaVulkanFunctions* VMA_NOT_NULL pDstVulkanFunctions);
16841722
#endif
16851723

16861724
/// Creates #VmaAllocator object.
@@ -15100,16 +15138,20 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
1510015138
#ifdef VOLK_HEADER_VERSION
1510115139

1510215140
VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
15103-
VkDevice VMA_NOT_NULL device, VmaVulkanFunctions* VMA_NOT_NULL dst)
15141+
const VmaAllocatorCreateInfo* VMA_NOT_NULL pAllocatorCreateInfo,
15142+
VmaVulkanFunctions* VMA_NOT_NULL pDstVulkanFunctions)
1510415143
{
15105-
VolkDeviceTable src = {};
15106-
memset(&dst, 0, sizeof(dst));
15107-
memset(&src, 0, sizeof(src));
15144+
VMA_ASSERT(pAllocatorCreateInfo != VMA_NULL);
15145+
VMA_ASSERT(pAllocatorCreateInfo->instance != VK_NULL_HANDLE);
15146+
VMA_ASSERT(pAllocatorCreateInfo->device != VK_NULL_HANDLE);
15147+
15148+
memset(pDstVulkanFunctions, 0, sizeof(*pDstVulkanFunctions));
1510815149

15109-
volkLoadDeviceTable(&src, device);
15150+
VolkDeviceTable src = {};
15151+
volkLoadDeviceTable(&src, pAllocatorCreateInfo->device);
1511015152

15111-
#define COPY_GLOBAL_TO_VMA_FUNC(volkName, vmaName) if(!dst->vmaName) dst->vmaName = volkName;
15112-
#define COPY_DEVICE_TO_VMA_FUNC(volkName, vmaName) if(!dst->vmaName) dst->vmaName = src.volkName;
15153+
#define COPY_GLOBAL_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = volkName;
15154+
#define COPY_DEVICE_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = src.volkName;
1511315155

1511415156
COPY_GLOBAL_TO_VMA_FUNC(vkGetInstanceProcAddr, vkGetInstanceProcAddr)
1511515157
COPY_GLOBAL_TO_VMA_FUNC(vkGetDeviceProcAddr, vkGetDeviceProcAddr)
@@ -15131,33 +15173,54 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
1513115173
COPY_DEVICE_TO_VMA_FUNC(vkDestroyImage, vkDestroyImage)
1513215174
COPY_DEVICE_TO_VMA_FUNC(vkCmdCopyBuffer, vkCmdCopyBuffer)
1513315175
#if VMA_VULKAN_VERSION >= 1001000
15134-
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
15135-
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
15136-
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
15137-
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
15138-
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2, vkBindImageMemory2KHR)
15176+
if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
15177+
{
15178+
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
15179+
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
15180+
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
15181+
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
15182+
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2, vkBindImageMemory2KHR)
15183+
}
1513915184
#endif
1514015185
#if VMA_VULKAN_VERSION >= 1003000
15141-
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirements)
15142-
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirements)
15186+
if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
15187+
{
15188+
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirements)
15189+
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirements)
15190+
}
1514315191
#endif
1514415192
#if VMA_KHR_MAINTENANCE4
15145-
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirementsKHR, vkGetDeviceBufferMemoryRequirements)
15146-
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirementsKHR, vkGetDeviceImageMemoryRequirements)
15193+
if((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0)
15194+
{
15195+
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirementsKHR, vkGetDeviceBufferMemoryRequirements)
15196+
COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirementsKHR, vkGetDeviceImageMemoryRequirements)
15197+
}
1514715198
#endif
1514815199
#if VMA_DEDICATED_ALLOCATION
15149-
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2KHR, vkGetBufferMemoryRequirements2KHR)
15150-
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2KHR, vkGetImageMemoryRequirements2KHR)
15200+
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0)
15201+
{
15202+
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2KHR, vkGetBufferMemoryRequirements2KHR)
15203+
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2KHR, vkGetImageMemoryRequirements2KHR)
15204+
}
1515115205
#endif
1515215206
#if VMA_BIND_MEMORY2
15153-
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2KHR, vkBindBufferMemory2KHR)
15154-
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2KHR, vkBindImageMemory2KHR)
15207+
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0)
15208+
{
15209+
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2KHR, vkBindBufferMemory2KHR)
15210+
COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2KHR, vkBindImageMemory2KHR)
15211+
}
1515515212
#endif
1515615213
#if VMA_MEMORY_BUDGET
15157-
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
15214+
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
15215+
{
15216+
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
15217+
}
1515815218
#endif
1515915219
#if VMA_EXTERNAL_MEMORY_WIN32
15160-
COPY_DEVICE_TO_VMA_FUNC(vkGetMemoryWin32HandleKHR, vkGetMemoryWin32HandleKHR)
15220+
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0)
15221+
{
15222+
COPY_DEVICE_TO_VMA_FUNC(vkGetMemoryWin32HandleKHR, vkGetMemoryWin32HandleKHR)
15223+
}
1516115224
#endif
1516215225

1516315226
#undef COPY_DEVICE_TO_VMA_FUNC
@@ -16882,7 +16945,7 @@ See code sample below.
1688216945

1688316946
\subsection quick_start_initialization_importing_vulkan_functions Importing Vulkan functions
1688416947

16885-
You may need to configure importing Vulkan functions. There are 3 ways to do this:
16948+
You may need to configure importing Vulkan functions. There are 4 ways to do this:
1688616949

1688716950
-# **If you link with Vulkan static library** (e.g. "vulkan-1.lib" on Windows):
1688816951
- You don't need to do anything.
@@ -16893,10 +16956,13 @@ You may need to configure importing Vulkan functions. There are 3 ways to do thi
1689316956
- Provide pointers to these two functions via VmaVulkanFunctions::vkGetInstanceProcAddr,
1689416957
VmaVulkanFunctions::vkGetDeviceProcAddr.
1689516958
- The library will fetch pointers to all other functions it needs internally.
16896-
-# **If you fetch pointers to all Vulkan functions in a custom way**, e.g. using some loader like
16897-
[Volk](https://github.com/zeux/volk):
16959+
-# **If you fetch pointers to all Vulkan functions in a custom way**:
1689816960
- Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0.
1689916961
- Pass these pointers via structure #VmaVulkanFunctions.
16962+
-# **If you use [volk library](https://github.com/zeux/volk)**:
16963+
- Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0.
16964+
- Use function vmaImportVulkanFunctionsFromVolk() to fill in the structure #VmaVulkanFunctions.
16965+
For more information, see the description of this function.
1690016966

1690116967
\subsection quick_start_initialization_enabling_extensions Enabling extensions
1690216968

src/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
option(VMA_STATIC_VULKAN_FUNCTIONS "Link statically with Vulkan API" ON)
2424
option(VMA_DYNAMIC_VULKAN_FUNCTIONS "Fetch pointers to Vulkan functions internally (no static linking)" OFF)
25+
set(VMA_VOLK_HEADER_PATH "" CACHE STRING "Path to volk.h file from the volk library (optional)")
2526
option(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY "Every allocation will have its own memory block" OFF)
2627
option(VMA_DEBUG_INITIALIZE_ALLOCATIONS "Automatically fill new allocations and destroyed allocations with some bit pattern" OFF)
2728
option(VMA_DEBUG_GLOBAL_MUTEX "Enable single mutex protecting all entry calls to the library" OFF)
@@ -50,6 +51,7 @@ target_sources(VmaSample PRIVATE
5051
Tests.h
5152
VmaUsage.cpp
5253
VmaUsage.h
54+
VolkUsage.cpp
5355
VulkanSample.cpp
5456
../include/vk_mem_alloc.h
5557
)
@@ -78,6 +80,15 @@ target_sources(VmaSample PRIVATE vk_mem_alloc.natvis)
7880
add_subdirectory(Shaders)
7981
add_dependencies(VmaSample VmaSampleShaders)
8082

83+
if(NOT "${VMA_VOLK_HEADER_PATH}" STREQUAL "")
84+
if(EXISTS "${VMA_VOLK_HEADER_PATH}")
85+
message(STATUS "File volk.h found and used from path: ${VMA_VOLK_HEADER_PATH}")
86+
target_compile_definitions(VmaSample PRIVATE VMA_VOLK_HEADER_PATH="${VMA_VOLK_HEADER_PATH}")
87+
else()
88+
message(FATAL_ERROR "File volk.h not found in path: ${VMA_VOLK_HEADER_PATH}")
89+
endif()
90+
endif()
91+
8192
# Use Unicode instead of multibyte set
8293
add_compile_definitions(UNICODE _UNICODE)
8394

src/Tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3904,7 +3904,7 @@ void TestHeapSizeLimit()
39043904
allocatorCreateInfo.pHeapSizeLimit = heapSizeLimit;
39053905
#ifdef VOLK_HEADER_VERSION
39063906
VmaVulkanFunctions vulkanFunctions = {};
3907-
vmaImportVulkanFunctionsFromVolk(g_hDevice, &vulkanFunctions);
3907+
vmaImportVulkanFunctionsFromVolk(&allocatorCreateInfo, &vulkanFunctions);
39083908
allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
39093909
#endif
39103910
#if VMA_DYNAMIC_VULKAN_FUNCTIONS

src/VmaUsage.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ include all public interface declarations. Example:
9696
#pragma clang diagnostic ignored "-Wnullability-completeness"
9797
#endif
9898

99-
//#include <vulkan/vulkan.h>
100-
#include "third_party/volk-1.4.304/volk.h"
99+
#ifdef VMA_VOLK_HEADER_PATH
100+
#include VMA_VOLK_HEADER_PATH
101+
#else
102+
#include <vulkan/vulkan.h>
103+
#endif
101104

102105
#ifdef _WIN32
103-
#include <vulkan/vulkan_win32.h>
106+
#include <vulkan/vulkan_win32.h>
104107
#endif // #ifdef _WIN32
105108

106109
#include "vk_mem_alloc.h"

src/VolkUsage.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
// THE SOFTWARE.
2121
//
2222

23-
/*
24-
In exactly one CPP file define macro VMA_IMPLEMENTATION and then include
25-
vk_mem_alloc.h to include definitions of its internal implementation
26-
*/
23+
#ifdef VMA_VOLK_HEADER_PATH
2724

2825
#define VOLK_IMPLEMENTATION
2926
#include "VmaUsage.h"
27+
28+
#endif // #ifdef VMA_VOLK_HEADER_PATH

src/VulkanSample.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,9 @@ void VulkanUsage::Init()
426426
g_Allocs = &g_CpuAllocationCallbacks;
427427
}
428428

429+
#ifdef VOLK_HEADER_VERSION
429430
ERR_GUARD_VULKAN(volkInitialize());
431+
#endif
430432

431433
uint32_t instanceLayerPropCount = 0;
432434
ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr) );
@@ -515,7 +517,9 @@ void VulkanUsage::Init()
515517

516518
ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, g_Allocs, &g_hVulkanInstance) );
517519

520+
#ifdef VOLK_HEADER_VERSION
518521
volkLoadInstance(g_hVulkanInstance);
522+
#endif
519523

520524
if(VK_EXT_debug_utils_enabled)
521525
{
@@ -1516,22 +1520,18 @@ void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
15161520
}
15171521

15181522
#ifdef VOLK_HEADER_VERSION
1519-
15201523
static VmaVulkanFunctions vulkanFunctions = {};
1521-
vmaImportVulkanFunctionsFromVolk(g_hDevice, &vulkanFunctions);
1524+
vmaImportVulkanFunctionsFromVolk(&outInfo, &vulkanFunctions);
15221525
outInfo.pVulkanFunctions = &vulkanFunctions;
1523-
1524-
#else // #ifdef VOLK_HEADER_VERSION
1526+
#endif // #ifdef VOLK_HEADER_VERSION
15251527

15261528
#if VMA_DYNAMIC_VULKAN_FUNCTIONS
1527-
v static VmaVulkanFunctions vulkanFunctions = {};
1529+
static VmaVulkanFunctions vulkanFunctions = {};
15281530
vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
15291531
vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
15301532
outInfo.pVulkanFunctions = &vulkanFunctions;
15311533
#endif // #if VMA_DYNAMIC_VULKAN_FUNCTIONS
15321534

1533-
#endif // #ifdef VOLK_HEADER_VERSION
1534-
15351535
// Uncomment to enable HeapSizeLimit.
15361536
/*
15371537
static std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
@@ -2097,7 +2097,11 @@ static void InitializeApplication()
20972097
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
20982098

20992099
ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
2100+
2101+
#ifdef VOLK_HEADER_VERSION
21002102
volkLoadDevice(g_hDevice);
2103+
#endif
2104+
21012105
SetDebugUtilsObjectName(VK_OBJECT_TYPE_DEVICE, reinterpret_cast<std::uint64_t>(g_hDevice), "g_hDevice");
21022106
// Only now that SetDebugUtilsObjectName is loaded, we can assign a name to g_hVulkanInstance as well
21032107
SetDebugUtilsObjectName(VK_OBJECT_TYPE_INSTANCE, reinterpret_cast<std::uint64_t>(g_hVulkanInstance), "g_hVulkanInstance");

0 commit comments

Comments
 (0)