Added documentation for VK_KHR_external_memory_win32

Rebuilt the documentation.
This commit is contained in:
Adam Sawicki 2024-08-28 13:20:19 +02:00
parent ca17831d74
commit eb46f62376
112 changed files with 3340 additions and 990 deletions

View file

@ -95,6 +95,7 @@ See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-me
- \subpage enabling_buffer_device_address
- \subpage vk_ext_memory_priority
- \subpage vk_amd_device_coherent_memory
- \subpage vk_khr_external_memory_win32
- \subpage general_considerations
- [Thread safety](@ref general_considerations_thread_safety)
- [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
@ -475,6 +476,7 @@ typedef enum VmaAllocatorCreateFlagBits
You should set this flag if you found available and enabled this device extension,
while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
For more information, see \ref vk_khr_external_memory_win32.
*/
VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT = 0x00000200,
@ -2077,15 +2079,34 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
#if VMA_EXTERNAL_MEMORY_WIN32
/**
\brief Given an allocation, returns Win32 Handle, that may be imported by other processes or APIs.
\brief Given an allocation, returns Win32 handle that may be imported by other processes or APIs.
`hTargetProcess` must be a valid handle to target process or NULL. If it's `NULL`, the function returns
handle for the current process.
\param hTargetProcess Must be a valid handle to target process or null. If it's null, the function returns
handle for the current process.
\param[out] pHandle Output parameter that returns the handle.
If the allocation was created with `VMA_ALLOCATION_CREATE_EXPORT_WIN32_HANDLE_BIT` flag,
the function fills `pHandle` with handle that can be used in target process.
The function fills `pHandle` with handle that can be used in target process.
The handle is fetched using function `vkGetMemoryWin32HandleKHR`.
When no longer needed, you must close it using:
\code
CloseHandle(handle);
\endcode
You can close it any time, before or after destroying the allocation object.
It is reference-counted internally by Windows.
Note the handle is returned for the entire `VkDeviceMemory` block that the allocation belongs to.
If the allocation is sub-allocated from a larger block, you may need to consider the offset of the allocation
(VmaAllocationInfo::offset).
If the function fails with `VK_ERROR_FEATURE_NOT_PRESENT` error code, please double-check
that VmaVulkanFunctions::vkGetMemoryWin32HandleKHR function pointer is set, e.g. either by using `VMA_DYNAMIC_VULKAN_FUNCTIONS`
or by manually passing it through VmaAllocatorCreateInfo::pVulkanFunctions.
For more information, see chapter \ref vk_khr_external_memory_win32.
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32HandleKHR(VmaAllocator VMA_NOT_NULL allocator,
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle);
#endif // VMA_EXTERNAL_MEMORY_WIN32
@ -16647,7 +16668,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
}
}
#if VMA_EXTERNAL_MEMORY_WIN32
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32HandleKHR(VmaAllocator VMA_NOT_NULL allocator,
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle)
{
VMA_ASSERT(allocator && allocation && pHandle);
@ -18799,6 +18820,142 @@ Example use of this extension can be found in the code of the sample and test su
accompanying this library.
\page vk_khr_external_memory_win32 VK_KHR_external_memory_win32
On Windows, the VK_KHR_external_memory_win32 device extension allows exporting a Win32 `HANDLE`
of a `VkDeviceMemory` block, to be able to reference the memory on other Vulkan logical devices or instances,
in multiple processes, and/or in multiple APIs.
VMA offers support for it.
\section vk_khr_external_memory_win32_initialization Initialization
1) Make sure the extension is defined in the code by including following header before including VMA:
\code
#include <vulkan/vulkan_win32.h>
\endcode
2) Check if "VK_KHR_external_memory_win32" is available among device extensions.
Enable it when creating the `VkDevice` object.
3) Enable the usage of this extension in VMA by setting flag #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
when calling vmaCreateAllocator().
4) Make sure that VMA has access to the `vkGetMemoryWin32HandleKHR` function by either enabling `VMA_DYNAMIC_VULKAN_FUNCTIONS` macro
or setting VmaVulkanFunctions::vkGetMemoryWin32HandleKHR explicitly.
For more information, see \ref quick_start_initialization_importing_vulkan_functions.
\section vk_khr_external_memory_win32_preparations Preparations
You can find example usage among tests, in file "Tests.cpp", function `TestWin32Handles()`.
To use the extenion, buffers need to be created with `VkExternalMemoryBufferCreateInfoKHR` attached to their `pNext` chain,
and memory allocations need to be made with `VkExportMemoryAllocateInfoKHR` attached to their `pNext` chain.
To make use of them, you need to use \ref custom_memory_pools. Example:
\code
// Define an example buffer and allocation parameters.
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
};
VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
exampleBufCreateInfo.size = 0x10000; // Doesn't matter here.
exampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
exampleBufCreateInfo.pNext = &externalMemBufCreateInfo;
VmaAllocationCreateInfo exampleAllocCreateInfo = {};
exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
// Find memory type index to use for the custom pool.
uint32_t memTypeIndex;
VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_Allocator,
&exampleBufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex);
// Check res...
// Create a custom pool.
constexpr static VkExportMemoryAllocateInfoKHR exportMemAllocInfo = {
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
};
VmaPoolCreateInfo poolCreateInfo = {};
poolCreateInfo.memoryTypeIndex = memTypeIndex;
poolCreateInfo.pMemoryAllocateNext = (void*)&exportMemAllocInfo;
VmaPool pool;
res = vmaCreatePool(g_Allocator, &poolCreateInfo, &pool);
// Check res...
// YOUR OTHER CODE COMES HERE....
// At the end, don't forget to destroy it!
vmaDestroyPool(g_Allocator, pool);
\endcode
Note that the structure passed as VmaPoolCreateInfo::pMemoryAllocateNext must remain alive and unchanged
for the whole lifetime of the custom pool, because it will be used when the pool allocates a new device memory block.
No copy is made internally. This is why variable `exportMemAllocInfo` is defined as `static`.
\section vk_khr_external_memory_win32_memory_allocation Memory allocation
Finally, you can create a buffer with an allocation out of the custom pool.
The buffer should use same flags as the sample buffer used to find the memory type.
It should also specify `VkExternalMemoryBufferCreateInfoKHR` in its `pNext` chain.
\code
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
};
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufCreateInfo.size = // Your desired buffer size.
bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
bufCreateInfo.pNext = &externalMemBufCreateInfo;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.pool = pool; // It is enough to set this one member.
VkBuffer buf;
VmaAllocation alloc;
res = vmaCreateBuffer(g_Allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);
// Check res...
// YOUR OTHER CODE COMES HERE....
// At the end, don't forget to destroy it!
vmaDestroyBuffer(g_Allocator, buf, alloc);
\endcode
\section vk_khr_external_memory_win32_exporting_win32_handle Exporting Win32 handle
After the allocation is created, you can acquire a Win32 `HANDLE` to the `VkDeviceMemory` block it belongs to.
VMA function vmaGetMemoryWin32Handle() is a replacement of the Vulkan function `vkGetMemoryWin32HandleKHR`.
\code
HANDLE handle;
res = vmaGetMemoryWin32Handle(g_Allocator, alloc, nullptr, &handle);
// Check res...
// YOUR OTHER CODE COMES HERE....
// At the end, you must close the handle.
CloseHandle(handle);
\endcode
Documentation of the VK_KHR_external_memory_win32 extension states that:
> If handleType is defined as an NT handle, vkGetMemoryWin32HandleKHR must be called no more than once for each valid unique combination of memory and handleType.
This is ensured automatically inside VMA.
The library fetches the handle on first use, remembers it internally, and closes it when the memory block or dedicated allocation is destroyed.
Every time you call vmaGetMemoryWin32Handle(), VMA calls `DuplicateHandle` and returns a new handle that you need to close.
For further information, please check documentation of the vmaGetMemoryWin32Handle() function.
\page enabling_buffer_device_address Enabling buffer device address
Device extension VK_KHR_buffer_device_address