Update VulkanMemoryAllocator to 3.2.1
Now that Vulkan 1.4 is available in Qt (ff7dfd72162423e98d73728c5c9ea007b5960fe7), we set allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_4; in QRhiVulkan::create(). But vmaCreateAllocator() asserts because the VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 3 check fails. Older versions of the VulkanMemoryAllocator aren't compatible with Vulkan 1.4. (issue https://github.com/GPUOpen-LibrariesAndSDKs/ VulkanMemoryAllocator/issues/457) Update VulkanMemoryAllocator to the latest version, which is compatible with Vulkan 1.4. [ChangeLog][Third-Party Code] Updated VulkanMemoryAllocator to 3.2.1 Change-Id: Ic6446ad6ee61a7f35ee70b19716f88eeda5eaa60 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
4b8659ebf6
commit
3bfc5d0b3b
@ -1,26 +0,0 @@
|
|||||||
From 1e4a10230381acc79768fd577987dde4255d6148 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Laszlo Agocs <laszlo.agocs@qt.io>
|
|
||||||
Date: Thu, 14 Jan 2021 11:22:09 +0100
|
|
||||||
Subject: [PATCH 1/4] Disable SRWLOCK for MinGW
|
|
||||||
|
|
||||||
Change-Id: Ie671e7bcf88ef28eb177a6fba17964a5e8ae30c0
|
|
||||||
---
|
|
||||||
src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
|
||||||
index 0dfb66efc6..8e579967d9 100644
|
|
||||||
--- a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
|
||||||
+++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
|
||||||
@@ -3691,7 +3691,7 @@ void *aligned_alloc(size_t alignment, size_t size)
|
|
||||||
std::shared_mutex m_Mutex;
|
|
||||||
};
|
|
||||||
#define VMA_RW_MUTEX VmaRWMutex
|
|
||||||
- #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600
|
|
||||||
+ #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600 && !defined(__MINGW32__)
|
|
||||||
// Use SRWLOCK from WinAPI.
|
|
||||||
// Minimum supported client = Windows Vista, server = Windows Server 2008.
|
|
||||||
class VmaRWMutex
|
|
||||||
--
|
|
||||||
2.23.0.windows.1
|
|
||||||
|
|
25
src/3rdparty/VulkanMemoryAllocator/patches/0007-Ignore-unused-private-field-warnings.patch
vendored
Normal file
25
src/3rdparty/VulkanMemoryAllocator/patches/0007-Ignore-unused-private-field-warnings.patch
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
From 713fd01631dea4295e9036065cebb851af035258 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Aur=C3=A9lien=20Brooke?= <aurelien@bahiasoft.fr>
|
||||||
|
Date: Mon, 24 Mar 2025 13:33:39 +0100
|
||||||
|
Subject: [PATCH] Ignore unused-private-field warnings
|
||||||
|
|
||||||
|
Change-Id: I64593efbfbda9b0d7676542b328b336c11d570f0
|
||||||
|
---
|
||||||
|
src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
||||||
|
index ae395514951..f1a976042f9 100644
|
||||||
|
--- a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
||||||
|
+++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
|
||||||
|
@@ -2829,6 +2829,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
+#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#pragma clang diagnostic ignored "-Wparentheses"
|
||||||
|
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
|
--
|
||||||
|
2.48.1
|
||||||
|
|
@ -7,12 +7,12 @@
|
|||||||
"QtUsage": "Memory management for the Vulkan backend of QRhi.",
|
"QtUsage": "Memory management for the Vulkan backend of QRhi.",
|
||||||
|
|
||||||
"Homepage": "https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator",
|
"Homepage": "https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator",
|
||||||
"Version": "3.1.0",
|
"Version": "3.2.1",
|
||||||
"PURL": "pkg:github/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@v$<VERSION>",
|
"PURL": "pkg:github/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@v$<VERSION>",
|
||||||
"License": "MIT License",
|
"License": "MIT License",
|
||||||
"LicenseId": "MIT",
|
"LicenseId": "MIT",
|
||||||
"LicenseFile": "LICENSE.txt",
|
"LicenseFile": "LICENSE.txt",
|
||||||
"Copyright": "Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved.",
|
"Copyright": "Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved.",
|
||||||
"Comment": "no relevant CPE found"
|
"Comment": "no relevant CPE found"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
578
src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
vendored
578
src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
vendored
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved.
|
// Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
/** \mainpage Vulkan Memory Allocator
|
/** \mainpage Vulkan Memory Allocator
|
||||||
|
|
||||||
<b>Version 3.1.0</b>
|
<b>Version 3.2.1</b>
|
||||||
|
|
||||||
Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. \n
|
Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||||
License: MIT \n
|
License: MIT \n
|
||||||
See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/),
|
See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/),
|
||||||
[repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
|
[repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
|
||||||
@ -95,6 +95,7 @@ See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-me
|
|||||||
- \subpage enabling_buffer_device_address
|
- \subpage enabling_buffer_device_address
|
||||||
- \subpage vk_ext_memory_priority
|
- \subpage vk_ext_memory_priority
|
||||||
- \subpage vk_amd_device_coherent_memory
|
- \subpage vk_amd_device_coherent_memory
|
||||||
|
- \subpage vk_khr_external_memory_win32
|
||||||
- \subpage general_considerations
|
- \subpage general_considerations
|
||||||
- [Thread safety](@ref general_considerations_thread_safety)
|
- [Thread safety](@ref general_considerations_thread_safety)
|
||||||
- [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
|
- [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
|
||||||
@ -127,10 +128,14 @@ See documentation chapter: \ref statistics.
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(VULKAN_H_)
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(VMA_VULKAN_VERSION)
|
#if !defined(VMA_VULKAN_VERSION)
|
||||||
#if defined(VK_VERSION_1_3)
|
#if defined(VK_VERSION_1_4)
|
||||||
|
#define VMA_VULKAN_VERSION 1004000
|
||||||
|
#elif defined(VK_VERSION_1_3)
|
||||||
#define VMA_VULKAN_VERSION 1003000
|
#define VMA_VULKAN_VERSION 1003000
|
||||||
#elif defined(VK_VERSION_1_2)
|
#elif defined(VK_VERSION_1_2)
|
||||||
#define VMA_VULKAN_VERSION 1002000
|
#define VMA_VULKAN_VERSION 1002000
|
||||||
@ -240,6 +245,15 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Defined to 1 when VK_KHR_external_memory_win32 device extension is defined in Vulkan headers.
|
||||||
|
#if !defined(VMA_EXTERNAL_MEMORY_WIN32)
|
||||||
|
#if VK_KHR_external_memory_win32
|
||||||
|
#define VMA_EXTERNAL_MEMORY_WIN32 1
|
||||||
|
#else
|
||||||
|
#define VMA_EXTERNAL_MEMORY_WIN32 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Define these macros to decorate all public functions with additional code,
|
// Define these macros to decorate all public functions with additional code,
|
||||||
// before and after returned type, appropriately. This may be useful for
|
// before and after returned type, appropriately. This may be useful for
|
||||||
// exporting the functions when compiling VMA as a separate library. Example:
|
// exporting the functions when compiling VMA as a separate library. Example:
|
||||||
@ -459,6 +473,15 @@ typedef enum VmaAllocatorCreateFlagBits
|
|||||||
*/
|
*/
|
||||||
VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100,
|
VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enables usage of VK_KHR_external_memory_win32 extension in the library.
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VmaAllocatorCreateFlagBits;
|
} VmaAllocatorCreateFlagBits;
|
||||||
/// See #VmaAllocatorCreateFlagBits.
|
/// See #VmaAllocatorCreateFlagBits.
|
||||||
@ -1033,6 +1056,11 @@ typedef struct VmaVulkanFunctions
|
|||||||
/// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
|
/// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
|
||||||
PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements;
|
PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements;
|
||||||
#endif
|
#endif
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||||
|
#else
|
||||||
|
void* VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||||
|
#endif
|
||||||
} VmaVulkanFunctions;
|
} VmaVulkanFunctions;
|
||||||
|
|
||||||
/// Description of a Allocator to be created.
|
/// Description of a Allocator to be created.
|
||||||
@ -1095,7 +1123,7 @@ typedef struct VmaAllocatorCreateInfo
|
|||||||
|
|
||||||
It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
|
It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
|
||||||
The patch version number specified is ignored. Only the major and minor versions are considered.
|
The patch version number specified is ignored. Only the major and minor versions are considered.
|
||||||
Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation.
|
Only versions 1.0...1.4 are supported by the current implementation.
|
||||||
Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
|
Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
|
||||||
It must match the Vulkan version used by the application and supported on the selected physical device,
|
It must match the Vulkan version used by the application and supported on the selected physical device,
|
||||||
so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance`
|
so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance`
|
||||||
@ -1810,6 +1838,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
|
|||||||
\param allocator Allocator object.
|
\param allocator Allocator object.
|
||||||
\param pool Pool object.
|
\param pool Pool object.
|
||||||
\param[out] pPoolStats Statistics of specified pool.
|
\param[out] pPoolStats Statistics of specified pool.
|
||||||
|
|
||||||
|
Note that when using the pool from multiple threads, returned information may immediately
|
||||||
|
become outdated.
|
||||||
*/
|
*/
|
||||||
VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
|
VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
|
||||||
VmaAllocator VMA_NOT_NULL allocator,
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
@ -2050,6 +2081,40 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
|
|||||||
VmaAllocation VMA_NOT_NULL allocation,
|
VmaAllocation VMA_NOT_NULL allocation,
|
||||||
VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
|
VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
|
||||||
|
|
||||||
|
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
/**
|
||||||
|
\brief Given an allocation, returns Win32 handle that may be imported by other processes or APIs.
|
||||||
|
|
||||||
|
\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.
|
||||||
|
|
||||||
|
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 vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle);
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
|
||||||
/** \brief Maps memory represented by given allocation and returns pointer to it.
|
/** \brief Maps memory represented by given allocation and returns pointer to it.
|
||||||
|
|
||||||
Maps memory represented by given allocation to make it accessible to CPU code.
|
Maps memory represented by given allocation to make it accessible to CPU code.
|
||||||
@ -2764,6 +2829,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
|
|||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||||
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||||
#pragma clang diagnostic ignored "-Wparentheses"
|
#pragma clang diagnostic ignored "-Wparentheses"
|
||||||
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
@ -3114,7 +3180,7 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr)
|
|||||||
std::shared_mutex m_Mutex;
|
std::shared_mutex m_Mutex;
|
||||||
};
|
};
|
||||||
#define VMA_RW_MUTEX VmaRWMutex
|
#define VMA_RW_MUTEX VmaRWMutex
|
||||||
#elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600 && !defined(__MINGW32__)
|
#elif defined(_WIN32) && defined(WINVER) && defined(SRWLOCK_INIT) && WINVER >= 0x0600
|
||||||
// Use SRWLOCK from WinAPI.
|
// Use SRWLOCK from WinAPI.
|
||||||
// Minimum supported client = Windows Vista, server = Windows Server 2008.
|
// Minimum supported client = Windows Vista, server = Windows Server 2008.
|
||||||
class VmaRWMutex
|
class VmaRWMutex
|
||||||
@ -3855,12 +3921,6 @@ struct VmaBufferImageUsage
|
|||||||
|
|
||||||
const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0);
|
const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0);
|
||||||
|
|
||||||
// static void swap(VmaBufferImageUsage& lhs, VmaBufferImageUsage& rhs) noexcept
|
|
||||||
// {
|
|
||||||
// using std::swap;
|
|
||||||
// swap(lhs.Value, rhs.Value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo,
|
VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo,
|
||||||
bool useKhrMaintenance5)
|
bool useKhrMaintenance5)
|
||||||
{
|
{
|
||||||
@ -6090,6 +6150,84 @@ private:
|
|||||||
|
|
||||||
#endif // _VMA_MAPPING_HYSTERESIS
|
#endif // _VMA_MAPPING_HYSTERESIS
|
||||||
|
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
class VmaWin32Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VmaWin32Handle() noexcept : m_hHandle(VMA_NULL) { }
|
||||||
|
explicit VmaWin32Handle(HANDLE hHandle) noexcept : m_hHandle(hHandle) { }
|
||||||
|
~VmaWin32Handle() noexcept { if (m_hHandle != VMA_NULL) { ::CloseHandle(m_hHandle); } }
|
||||||
|
VMA_CLASS_NO_COPY_NO_MOVE(VmaWin32Handle)
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Strengthened
|
||||||
|
VkResult GetHandle(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, bool useMutex, HANDLE* pHandle) noexcept
|
||||||
|
{
|
||||||
|
*pHandle = VMA_NULL;
|
||||||
|
// Try to get handle first.
|
||||||
|
if (m_hHandle != VMA_NULL)
|
||||||
|
{
|
||||||
|
*pHandle = Duplicate(hTargetProcess);
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult res = VK_SUCCESS;
|
||||||
|
// If failed, try to create it.
|
||||||
|
{
|
||||||
|
VmaMutexLockWrite lock(m_Mutex, useMutex);
|
||||||
|
if (m_hHandle == VMA_NULL)
|
||||||
|
{
|
||||||
|
res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &m_hHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pHandle = Duplicate(hTargetProcess);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const noexcept { return m_hHandle != VMA_NULL; }
|
||||||
|
private:
|
||||||
|
// Not atomic
|
||||||
|
static VkResult Create(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE* pHandle) noexcept
|
||||||
|
{
|
||||||
|
VkResult res = VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
if (pvkGetMemoryWin32HandleKHR != VMA_NULL)
|
||||||
|
{
|
||||||
|
VkMemoryGetWin32HandleInfoKHR handleInfo{ };
|
||||||
|
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
||||||
|
handleInfo.memory = memory;
|
||||||
|
handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
|
||||||
|
res = pvkGetMemoryWin32HandleKHR(device, &handleInfo, pHandle);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
HANDLE Duplicate(HANDLE hTargetProcess = VMA_NULL) const noexcept
|
||||||
|
{
|
||||||
|
if (!m_hHandle)
|
||||||
|
return m_hHandle;
|
||||||
|
|
||||||
|
HANDLE hCurrentProcess = ::GetCurrentProcess();
|
||||||
|
HANDLE hDupHandle = VMA_NULL;
|
||||||
|
if (!::DuplicateHandle(hCurrentProcess, m_hHandle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
VMA_ASSERT(0 && "Failed to duplicate handle.");
|
||||||
|
}
|
||||||
|
return hDupHandle;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
HANDLE m_hHandle;
|
||||||
|
VMA_RW_MUTEX m_Mutex; // Protects access m_Handle
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class VmaWin32Handle
|
||||||
|
{
|
||||||
|
// ABI compatibility
|
||||||
|
void* placeholder = VMA_NULL;
|
||||||
|
VMA_RW_MUTEX placeholder2;
|
||||||
|
};
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
|
||||||
|
|
||||||
#ifndef _VMA_DEVICE_MEMORY_BLOCK
|
#ifndef _VMA_DEVICE_MEMORY_BLOCK
|
||||||
/*
|
/*
|
||||||
Represents a single block of device memory (`VkDeviceMemory`) with all the
|
Represents a single block of device memory (`VkDeviceMemory`) with all the
|
||||||
@ -6156,7 +6294,13 @@ public:
|
|||||||
VkDeviceSize allocationLocalOffset,
|
VkDeviceSize allocationLocalOffset,
|
||||||
VkImage hImage,
|
VkImage hImage,
|
||||||
const void* pNext);
|
const void* pNext);
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
VkResult CreateWin32Handle(
|
||||||
|
const VmaAllocator hAllocator,
|
||||||
|
PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR,
|
||||||
|
HANDLE hTargetProcess,
|
||||||
|
HANDLE* pHandle)noexcept;
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
private:
|
private:
|
||||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||||
uint32_t m_MemoryTypeIndex;
|
uint32_t m_MemoryTypeIndex;
|
||||||
@ -6172,10 +6316,18 @@ private:
|
|||||||
VmaMappingHysteresis m_MappingHysteresis;
|
VmaMappingHysteresis m_MappingHysteresis;
|
||||||
uint32_t m_MapCount;
|
uint32_t m_MapCount;
|
||||||
void* m_pMappedData;
|
void* m_pMappedData;
|
||||||
|
|
||||||
|
VmaWin32Handle m_Handle;
|
||||||
};
|
};
|
||||||
#endif // _VMA_DEVICE_MEMORY_BLOCK
|
#endif // _VMA_DEVICE_MEMORY_BLOCK
|
||||||
|
|
||||||
#ifndef _VMA_ALLOCATION_T
|
#ifndef _VMA_ALLOCATION_T
|
||||||
|
struct VmaAllocationExtraData
|
||||||
|
{
|
||||||
|
void* m_pMappedData = VMA_NULL; // Not null means memory is mapped.
|
||||||
|
VmaWin32Handle m_Handle;
|
||||||
|
};
|
||||||
|
|
||||||
struct VmaAllocation_T
|
struct VmaAllocation_T
|
||||||
{
|
{
|
||||||
friend struct VmaDedicatedAllocationListItemTraits;
|
friend struct VmaDedicatedAllocationListItemTraits;
|
||||||
@ -6208,12 +6360,14 @@ public:
|
|||||||
bool mapped);
|
bool mapped);
|
||||||
// pMappedData not null means allocation is created with MAPPED flag.
|
// pMappedData not null means allocation is created with MAPPED flag.
|
||||||
void InitDedicatedAllocation(
|
void InitDedicatedAllocation(
|
||||||
|
VmaAllocator allocator,
|
||||||
VmaPool hParentPool,
|
VmaPool hParentPool,
|
||||||
uint32_t memoryTypeIndex,
|
uint32_t memoryTypeIndex,
|
||||||
VkDeviceMemory hMemory,
|
VkDeviceMemory hMemory,
|
||||||
VmaSuballocationType suballocationType,
|
VmaSuballocationType suballocationType,
|
||||||
void* pMappedData,
|
void* pMappedData,
|
||||||
VkDeviceSize size);
|
VkDeviceSize size);
|
||||||
|
void Destroy(VmaAllocator allocator);
|
||||||
|
|
||||||
ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
|
ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
|
||||||
VkDeviceSize GetAlignment() const { return m_Alignment; }
|
VkDeviceSize GetAlignment() const { return m_Alignment; }
|
||||||
@ -6257,6 +6411,10 @@ public:
|
|||||||
void PrintParameters(class VmaJsonWriter& json) const;
|
void PrintParameters(class VmaJsonWriter& json) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
VkResult GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* hHandle) noexcept;
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Allocation out of VmaDeviceMemoryBlock.
|
// Allocation out of VmaDeviceMemoryBlock.
|
||||||
struct BlockAllocation
|
struct BlockAllocation
|
||||||
@ -6269,7 +6427,7 @@ private:
|
|||||||
{
|
{
|
||||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||||
VkDeviceMemory m_hMemory;
|
VkDeviceMemory m_hMemory;
|
||||||
void* m_pMappedData; // Not null means memory is mapped.
|
VmaAllocationExtraData* m_ExtraData;
|
||||||
VmaAllocation_T* m_Prev;
|
VmaAllocation_T* m_Prev;
|
||||||
VmaAllocation_T* m_Next;
|
VmaAllocation_T* m_Next;
|
||||||
};
|
};
|
||||||
@ -6294,6 +6452,8 @@ private:
|
|||||||
#if VMA_STATS_STRING_ENABLED
|
#if VMA_STATS_STRING_ENABLED
|
||||||
VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown.
|
VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void EnsureExtraData(VmaAllocator hAllocator);
|
||||||
};
|
};
|
||||||
#endif // _VMA_ALLOCATION_T
|
#endif // _VMA_ALLOCATION_T
|
||||||
|
|
||||||
@ -9174,10 +9334,10 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
RemoveFreeBlock(currentBlock);
|
RemoveFreeBlock(currentBlock);
|
||||||
|
|
||||||
VkDeviceSize debugMargin = GetDebugMargin();
|
VkDeviceSize debugMargin = GetDebugMargin();
|
||||||
VkDeviceSize misssingAlignment = offset - currentBlock->offset;
|
VkDeviceSize missingAlignment = offset - currentBlock->offset;
|
||||||
|
|
||||||
// Append missing alignment to prev block or create new one
|
// Append missing alignment to prev block or create new one
|
||||||
if (misssingAlignment)
|
if (missingAlignment)
|
||||||
{
|
{
|
||||||
Block* prevBlock = currentBlock->prevPhysical;
|
Block* prevBlock = currentBlock->prevPhysical;
|
||||||
VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!");
|
VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!");
|
||||||
@ -9185,17 +9345,17 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
if (prevBlock->IsFree() && prevBlock->size != debugMargin)
|
if (prevBlock->IsFree() && prevBlock->size != debugMargin)
|
||||||
{
|
{
|
||||||
uint32_t oldList = GetListIndex(prevBlock->size);
|
uint32_t oldList = GetListIndex(prevBlock->size);
|
||||||
prevBlock->size += misssingAlignment;
|
prevBlock->size += missingAlignment;
|
||||||
// Check if new size crosses list bucket
|
// Check if new size crosses list bucket
|
||||||
if (oldList != GetListIndex(prevBlock->size))
|
if (oldList != GetListIndex(prevBlock->size))
|
||||||
{
|
{
|
||||||
prevBlock->size -= misssingAlignment;
|
prevBlock->size -= missingAlignment;
|
||||||
RemoveFreeBlock(prevBlock);
|
RemoveFreeBlock(prevBlock);
|
||||||
prevBlock->size += misssingAlignment;
|
prevBlock->size += missingAlignment;
|
||||||
InsertFreeBlock(prevBlock);
|
InsertFreeBlock(prevBlock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_BlocksFreeSize += misssingAlignment;
|
m_BlocksFreeSize += missingAlignment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -9204,15 +9364,15 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
prevBlock->nextPhysical = newBlock;
|
prevBlock->nextPhysical = newBlock;
|
||||||
newBlock->prevPhysical = prevBlock;
|
newBlock->prevPhysical = prevBlock;
|
||||||
newBlock->nextPhysical = currentBlock;
|
newBlock->nextPhysical = currentBlock;
|
||||||
newBlock->size = misssingAlignment;
|
newBlock->size = missingAlignment;
|
||||||
newBlock->offset = currentBlock->offset;
|
newBlock->offset = currentBlock->offset;
|
||||||
newBlock->MarkTaken();
|
newBlock->MarkTaken();
|
||||||
|
|
||||||
InsertFreeBlock(newBlock);
|
InsertFreeBlock(newBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBlock->size -= misssingAlignment;
|
currentBlock->size -= missingAlignment;
|
||||||
currentBlock->offset += misssingAlignment;
|
currentBlock->offset += missingAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceSize size = request.size + debugMargin;
|
VkDeviceSize size = request.size + debugMargin;
|
||||||
@ -10092,6 +10252,7 @@ public:
|
|||||||
bool m_UseExtMemoryPriority;
|
bool m_UseExtMemoryPriority;
|
||||||
bool m_UseKhrMaintenance4;
|
bool m_UseKhrMaintenance4;
|
||||||
bool m_UseKhrMaintenance5;
|
bool m_UseKhrMaintenance5;
|
||||||
|
bool m_UseKhrExternalMemoryWin32;
|
||||||
const VkDevice m_hDevice;
|
const VkDevice m_hDevice;
|
||||||
const VkInstance m_hInstance;
|
const VkInstance m_hInstance;
|
||||||
const bool m_AllocationCallbacksSpecified;
|
const bool m_AllocationCallbacksSpecified;
|
||||||
@ -10455,7 +10616,7 @@ VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)
|
|||||||
m_Id(0),
|
m_Id(0),
|
||||||
m_hMemory(VK_NULL_HANDLE),
|
m_hMemory(VK_NULL_HANDLE),
|
||||||
m_MapCount(0),
|
m_MapCount(0),
|
||||||
m_pMappedData(VMA_NULL) {}
|
m_pMappedData(VMA_NULL){}
|
||||||
|
|
||||||
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
|
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
|
||||||
{
|
{
|
||||||
@ -10698,6 +10859,14 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory(
|
|||||||
VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
|
VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
|
||||||
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
|
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||||
|
{
|
||||||
|
VMA_ASSERT(pHandle);
|
||||||
|
return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||||
|
}
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
|
#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
|
||||||
|
|
||||||
#ifndef _VMA_ALLOCATION_T_FUNCTIONS
|
#ifndef _VMA_ALLOCATION_T_FUNCTIONS
|
||||||
@ -10750,6 +10919,7 @@ void VmaAllocation_T::InitBlockAllocation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VmaAllocation_T::InitDedicatedAllocation(
|
void VmaAllocation_T::InitDedicatedAllocation(
|
||||||
|
VmaAllocator allocator,
|
||||||
VmaPool hParentPool,
|
VmaPool hParentPool,
|
||||||
uint32_t memoryTypeIndex,
|
uint32_t memoryTypeIndex,
|
||||||
VkDeviceMemory hMemory,
|
VkDeviceMemory hMemory,
|
||||||
@ -10764,16 +10934,29 @@ void VmaAllocation_T::InitDedicatedAllocation(
|
|||||||
m_Size = size;
|
m_Size = size;
|
||||||
m_MemoryTypeIndex = memoryTypeIndex;
|
m_MemoryTypeIndex = memoryTypeIndex;
|
||||||
m_SuballocationType = (uint8_t)suballocationType;
|
m_SuballocationType = (uint8_t)suballocationType;
|
||||||
if(pMappedData != VMA_NULL)
|
m_DedicatedAllocation.m_ExtraData = VMA_NULL;
|
||||||
|
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
||||||
|
m_DedicatedAllocation.m_hMemory = hMemory;
|
||||||
|
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
||||||
|
m_DedicatedAllocation.m_Next = VMA_NULL;
|
||||||
|
|
||||||
|
if (pMappedData != VMA_NULL)
|
||||||
{
|
{
|
||||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||||
m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
|
m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
|
||||||
|
EnsureExtraData(allocator);
|
||||||
|
m_DedicatedAllocation.m_ExtraData->m_pMappedData = pMappedData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaAllocation_T::Destroy(VmaAllocator allocator)
|
||||||
|
{
|
||||||
|
FreeName(allocator);
|
||||||
|
|
||||||
|
if (GetType() == ALLOCATION_TYPE_DEDICATED)
|
||||||
|
{
|
||||||
|
vma_delete(allocator, m_DedicatedAllocation.m_ExtraData);
|
||||||
}
|
}
|
||||||
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
|
||||||
m_DedicatedAllocation.m_hMemory = hMemory;
|
|
||||||
m_DedicatedAllocation.m_pMappedData = pMappedData;
|
|
||||||
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
|
||||||
m_DedicatedAllocation.m_Next = VMA_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
|
void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
|
||||||
@ -10878,8 +11061,9 @@ void* VmaAllocation_T::GetMappedData() const
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ALLOCATION_TYPE_DEDICATED:
|
case ALLOCATION_TYPE_DEDICATED:
|
||||||
VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));
|
VMA_ASSERT((m_DedicatedAllocation.m_ExtraData != VMA_NULL && m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL) ==
|
||||||
return m_DedicatedAllocation.m_pMappedData;
|
(m_MapCount != 0 || IsPersistentMap()));
|
||||||
|
return m_DedicatedAllocation.m_ExtraData != VMA_NULL ? m_DedicatedAllocation.m_ExtraData->m_pMappedData : VMA_NULL;
|
||||||
default:
|
default:
|
||||||
VMA_ASSERT(0);
|
VMA_ASSERT(0);
|
||||||
return VMA_NULL;
|
return VMA_NULL;
|
||||||
@ -10920,12 +11104,14 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
|||||||
VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
|
VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
|
||||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||||
|
|
||||||
|
EnsureExtraData(hAllocator);
|
||||||
|
|
||||||
if (m_MapCount != 0 || IsPersistentMap())
|
if (m_MapCount != 0 || IsPersistentMap())
|
||||||
{
|
{
|
||||||
if (m_MapCount < 0xFF)
|
if (m_MapCount < 0xFF)
|
||||||
{
|
{
|
||||||
VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
|
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL);
|
||||||
*ppData = m_DedicatedAllocation.m_pMappedData;
|
*ppData = m_DedicatedAllocation.m_ExtraData->m_pMappedData;
|
||||||
++m_MapCount;
|
++m_MapCount;
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -10946,7 +11132,7 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
|||||||
ppData);
|
ppData);
|
||||||
if (result == VK_SUCCESS)
|
if (result == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
m_DedicatedAllocation.m_pMappedData = *ppData;
|
m_DedicatedAllocation.m_ExtraData->m_pMappedData = *ppData;
|
||||||
m_MapCount = 1;
|
m_MapCount = 1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -10962,7 +11148,8 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
|
|||||||
--m_MapCount;
|
--m_MapCount;
|
||||||
if (m_MapCount == 0 && !IsPersistentMap())
|
if (m_MapCount == 0 && !IsPersistentMap())
|
||||||
{
|
{
|
||||||
m_DedicatedAllocation.m_pMappedData = VMA_NULL;
|
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData != VMA_NULL);
|
||||||
|
m_DedicatedAllocation.m_ExtraData->m_pMappedData = VMA_NULL;
|
||||||
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
|
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
|
||||||
hAllocator->m_hDevice,
|
hAllocator->m_hDevice,
|
||||||
m_DedicatedAllocation.m_hMemory);
|
m_DedicatedAllocation.m_hMemory);
|
||||||
@ -10998,8 +11185,33 @@ void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
|
|||||||
json.WriteString(m_pName);
|
json.WriteString(m_pName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||||
|
{
|
||||||
|
auto pvkGetMemoryWin32HandleKHR = hAllocator->GetVulkanFunctions().vkGetMemoryWin32HandleKHR;
|
||||||
|
switch (m_Type)
|
||||||
|
{
|
||||||
|
case ALLOCATION_TYPE_BLOCK:
|
||||||
|
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
|
||||||
|
case ALLOCATION_TYPE_DEDICATED:
|
||||||
|
EnsureExtraData(hAllocator);
|
||||||
|
return m_DedicatedAllocation.m_ExtraData->m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||||
|
default:
|
||||||
|
VMA_ASSERT(0);
|
||||||
|
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
#endif // VMA_STATS_STRING_ENABLED
|
#endif // VMA_STATS_STRING_ENABLED
|
||||||
|
|
||||||
|
void VmaAllocation_T::EnsureExtraData(VmaAllocator hAllocator)
|
||||||
|
{
|
||||||
|
if (m_DedicatedAllocation.m_ExtraData == VMA_NULL)
|
||||||
|
{
|
||||||
|
m_DedicatedAllocation.m_ExtraData = vma_new(hAllocator, VmaAllocationExtraData)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
|
void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
|
||||||
{
|
{
|
||||||
if(m_pName)
|
if(m_pName)
|
||||||
@ -11416,6 +11628,10 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IncrementallySortBlocks();
|
IncrementallySortBlocks();
|
||||||
|
|
||||||
|
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
||||||
|
hAllocation->Destroy(m_hAllocator);
|
||||||
|
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destruction of a free block. Deferred until this point, outside of mutex
|
// Destruction of a free block. Deferred until this point, outside of mutex
|
||||||
@ -11426,9 +11642,6 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
|||||||
pBlockToDelete->Destroy(m_hAllocator);
|
pBlockToDelete->Destroy(m_hAllocator);
|
||||||
vma_delete(m_hAllocator, pBlockToDelete);
|
vma_delete(m_hAllocator, pBlockToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
|
||||||
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
|
VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
|
||||||
@ -12728,6 +12941,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
|||||||
m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0),
|
m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0),
|
||||||
m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0),
|
m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0),
|
||||||
m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0),
|
m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0),
|
||||||
|
m_UseKhrExternalMemoryWin32((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0),
|
||||||
m_hDevice(pCreateInfo->device),
|
m_hDevice(pCreateInfo->device),
|
||||||
m_hInstance(pCreateInfo->instance),
|
m_hInstance(pCreateInfo->instance),
|
||||||
m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
|
m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
|
||||||
@ -12783,23 +12997,17 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
|||||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if VMA_VULKAN_VERSION < 1004000
|
||||||
|
VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 4, 0) && "vulkanApiVersion >= VK_API_VERSION_1_4 but required Vulkan version is disabled by preprocessor macros.");
|
||||||
|
#endif
|
||||||
#if VMA_VULKAN_VERSION < 1003000
|
#if VMA_VULKAN_VERSION < 1003000
|
||||||
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
|
VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 3, 0) && "vulkanApiVersion >= VK_API_VERSION_1_3 but required Vulkan version is disabled by preprocessor macros.");
|
||||||
{
|
|
||||||
VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_3 but required Vulkan version is disabled by preprocessor macros.");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if VMA_VULKAN_VERSION < 1002000
|
#if VMA_VULKAN_VERSION < 1002000
|
||||||
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0))
|
VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 2, 0) && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.");
|
||||||
{
|
|
||||||
VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if VMA_VULKAN_VERSION < 1001000
|
#if VMA_VULKAN_VERSION < 1001000
|
||||||
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
|
VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0) && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.");
|
||||||
{
|
|
||||||
VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if !(VMA_MEMORY_PRIORITY)
|
#if !(VMA_MEMORY_PRIORITY)
|
||||||
if(m_UseExtMemoryPriority)
|
if(m_UseExtMemoryPriority)
|
||||||
@ -12819,6 +13027,19 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
|||||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if !(VMA_KHR_MAINTENANCE5)
|
||||||
|
if(m_UseKhrMaintenance5)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(VMA_EXTERNAL_MEMORY_WIN32)
|
||||||
|
if(m_UseKhrExternalMemoryWin32)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
|
memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
|
||||||
memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
|
memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
|
||||||
@ -13043,7 +13264,9 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
|
|||||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);
|
VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);
|
||||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);
|
VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);
|
||||||
#endif
|
#endif
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
VMA_COPY_IF_NOT_NULL(vkGetMemoryWin32HandleKHR);
|
||||||
|
#endif
|
||||||
#undef VMA_COPY_IF_NOT_NULL
|
#undef VMA_COPY_IF_NOT_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13097,10 +13320,14 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
|
|||||||
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
|
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
|
||||||
{
|
{
|
||||||
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
|
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
|
||||||
|
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410.
|
||||||
|
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
|
||||||
}
|
}
|
||||||
else if(m_UseExtMemoryBudget)
|
else if(m_UseExtMemoryBudget)
|
||||||
{
|
{
|
||||||
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
|
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
|
||||||
|
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410.
|
||||||
|
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -13145,7 +13372,12 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
|
|||||||
VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR");
|
VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
if (m_UseKhrExternalMemoryWin32)
|
||||||
|
{
|
||||||
|
VMA_FETCH_DEVICE_FUNC(vkGetMemoryWin32HandleKHR, PFN_vkGetMemoryWin32HandleKHR, "vkGetMemoryWin32HandleKHR");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#undef VMA_FETCH_DEVICE_FUNC
|
#undef VMA_FETCH_DEVICE_FUNC
|
||||||
#undef VMA_FETCH_INSTANCE_FUNC
|
#undef VMA_FETCH_INSTANCE_FUNC
|
||||||
}
|
}
|
||||||
@ -13194,6 +13426,12 @@ void VmaAllocator_T::ValidateVulkanFunctions()
|
|||||||
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
|
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
if (m_UseKhrExternalMemoryWin32)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(m_VulkanFunctions.vkGetMemoryWin32HandleKHR != VMA_NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Not validating these due to suspected driver bugs with these function
|
// Not validating these due to suspected driver bugs with these function
|
||||||
// pointers being null despite correct extension or Vulkan version is enabled.
|
// pointers being null despite correct extension or Vulkan version is enabled.
|
||||||
@ -13544,7 +13782,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
|
*pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
|
||||||
(*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
(*pAllocation)->InitDedicatedAllocation(this, pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
||||||
if (isUserDataString)
|
if (isUserDataString)
|
||||||
(*pAllocation)->SetName(this, (const char*)pUserData);
|
(*pAllocation)->SetName(this, (const char*)pUserData);
|
||||||
else
|
else
|
||||||
@ -13880,8 +14118,6 @@ void VmaAllocator_T::FreeMemory(
|
|||||||
FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
|
FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocation->FreeName(this);
|
|
||||||
|
|
||||||
switch(allocation->GetType())
|
switch(allocation->GetType())
|
||||||
{
|
{
|
||||||
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
|
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
|
||||||
@ -14352,7 +14588,6 @@ VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
VMA_FALLTHROUGH; // Fallthrough
|
|
||||||
case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
|
case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
|
||||||
return hAllocation->DedicatedAllocMap(this, ppData);
|
return hAllocation->DedicatedAllocMap(this, ppData);
|
||||||
default:
|
default:
|
||||||
@ -14566,6 +14801,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
|
|||||||
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
|
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
|
||||||
|
|
||||||
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
|
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
|
||||||
|
allocation->Destroy(this);
|
||||||
m_AllocationObjectAllocator.Free(allocation);
|
m_AllocationObjectAllocator.Free(allocation);
|
||||||
|
|
||||||
VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex);
|
VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex);
|
||||||
@ -14852,7 +15088,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
|
|||||||
{
|
{
|
||||||
VMA_ASSERT(pCreateInfo && pAllocator);
|
VMA_ASSERT(pCreateInfo && pAllocator);
|
||||||
VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||
|
VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||
|
||||||
(VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 3));
|
(VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 4));
|
||||||
VMA_DEBUG_LOG("vmaCreateAllocator");
|
VMA_DEBUG_LOG("vmaCreateAllocator");
|
||||||
*pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
|
*pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
|
||||||
VkResult result = (*pAllocator)->Init(pCreateInfo);
|
VkResult result = (*pAllocator)->Init(pCreateInfo);
|
||||||
@ -16186,7 +16422,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
|||||||
pImageCreateInfo,
|
pImageCreateInfo,
|
||||||
allocator->GetAllocationCallbacks(),
|
allocator->GetAllocationCallbacks(),
|
||||||
pImage);
|
pImage);
|
||||||
if(res >= 0)
|
if(res == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
|
VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
|
||||||
VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
|
VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
|
||||||
@ -16211,14 +16447,14 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
|||||||
1, // allocationCount
|
1, // allocationCount
|
||||||
pAllocation);
|
pAllocation);
|
||||||
|
|
||||||
if(res >= 0)
|
if(res == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
// 3. Bind image with memory.
|
// 3. Bind image with memory.
|
||||||
if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
|
if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
|
||||||
{
|
{
|
||||||
res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
|
res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
|
||||||
}
|
}
|
||||||
if(res >= 0)
|
if(res == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
// All steps succeeded.
|
// All steps succeeded.
|
||||||
#if VMA_STATS_STRING_ENABLED
|
#if VMA_STATS_STRING_ENABLED
|
||||||
@ -16451,6 +16687,15 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
|
|||||||
VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);
|
VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||||
|
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);
|
||||||
|
VMA_DEBUG_GLOBAL_MUTEX_LOCK;
|
||||||
|
return allocation->GetWin32Handle(allocator, hTargetProcess, pHandle);
|
||||||
|
}
|
||||||
|
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||||
#endif // VMA_STATS_STRING_ENABLED
|
#endif // VMA_STATS_STRING_ENABLED
|
||||||
#endif // _VMA_PUBLIC_INTERFACE
|
#endif // _VMA_PUBLIC_INTERFACE
|
||||||
|
|
||||||
@ -16591,6 +16836,7 @@ VK_EXT_memory_budget | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
|
|||||||
VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
|
VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
|
||||||
VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
|
VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
|
||||||
VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
|
VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
|
||||||
|
VK_KHR_external_memory_win32 | #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
|
||||||
|
|
||||||
Example with fetching pointers to Vulkan functions dynamically:
|
Example with fetching pointers to Vulkan functions dynamically:
|
||||||
|
|
||||||
@ -17077,7 +17323,7 @@ implementation whether the allocation succeeds or fails. You can change this beh
|
|||||||
by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
|
by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
|
||||||
not made if it would exceed the budget or if the budget is already exceeded.
|
not made if it would exceed the budget or if the budget is already exceeded.
|
||||||
VMA then tries to make the allocation from the next eligible Vulkan memory type.
|
VMA then tries to make the allocation from the next eligible Vulkan memory type.
|
||||||
The all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
If all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
||||||
Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
|
Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
|
||||||
when creating resources that are not essential for the application (e.g. the texture
|
when creating resources that are not essential for the application (e.g. the texture
|
||||||
of a specific object) and not to pass it when creating critically important resources
|
of a specific object) and not to pass it when creating critically important resources
|
||||||
@ -18217,7 +18463,8 @@ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
|||||||
VkBuffer buf;
|
VkBuffer buf;
|
||||||
VmaAllocation alloc;
|
VmaAllocation alloc;
|
||||||
VmaAllocationInfo allocInfo;
|
VmaAllocationInfo allocInfo;
|
||||||
vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
VkResult result = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
||||||
|
// Check result...
|
||||||
|
|
||||||
VkMemoryPropertyFlags memPropFlags;
|
VkMemoryPropertyFlags memPropFlags;
|
||||||
vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);
|
vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);
|
||||||
@ -18228,10 +18475,24 @@ if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
|||||||
|
|
||||||
// [Executed in runtime]:
|
// [Executed in runtime]:
|
||||||
memcpy(allocInfo.pMappedData, myData, myDataSize);
|
memcpy(allocInfo.pMappedData, myData, myDataSize);
|
||||||
|
result = vmaFlushAllocation(allocator, alloc, 0, VK_WHOLE_SIZE);
|
||||||
|
// Check result...
|
||||||
|
|
||||||
|
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||||
|
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||||
|
bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
|
||||||
|
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier.buffer = buf;
|
||||||
|
bufMemBarrier.offset = 0;
|
||||||
|
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||||
|
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Allocation ended up in a non-mappable memory - need to transfer.
|
// Allocation ended up in a non-mappable memory - a transfer using a staging buffer is required.
|
||||||
VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
stagingBufCreateInfo.size = 65536;
|
stagingBufCreateInfo.size = 65536;
|
||||||
stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
@ -18244,18 +18505,46 @@ else
|
|||||||
VkBuffer stagingBuf;
|
VkBuffer stagingBuf;
|
||||||
VmaAllocation stagingAlloc;
|
VmaAllocation stagingAlloc;
|
||||||
VmaAllocationInfo stagingAllocInfo;
|
VmaAllocationInfo stagingAllocInfo;
|
||||||
vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
result = vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
||||||
&stagingBuf, &stagingAlloc, stagingAllocInfo);
|
&stagingBuf, &stagingAlloc, &stagingAllocInfo);
|
||||||
|
// Check result...
|
||||||
|
|
||||||
// [Executed in runtime]:
|
// [Executed in runtime]:
|
||||||
memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);
|
memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);
|
||||||
vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
result = vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
||||||
//vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT
|
// Check result...
|
||||||
|
|
||||||
|
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||||
|
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||||
|
bufMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier.buffer = stagingBuf;
|
||||||
|
bufMemBarrier.offset = 0;
|
||||||
|
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||||
|
|
||||||
VkBufferCopy bufCopy = {
|
VkBufferCopy bufCopy = {
|
||||||
0, // srcOffset
|
0, // srcOffset
|
||||||
0, // dstOffset,
|
0, // dstOffset,
|
||||||
myDataSize); // size
|
myDataSize, // size
|
||||||
|
};
|
||||||
|
|
||||||
vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);
|
vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);
|
||||||
|
|
||||||
|
VkBufferMemoryBarrier bufMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||||
|
bufMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
bufMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // We created a uniform buffer
|
||||||
|
bufMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
bufMemBarrier2.buffer = buf;
|
||||||
|
bufMemBarrier2.offset = 0;
|
||||||
|
bufMemBarrier2.size = VK_WHOLE_SIZE;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||||
|
0, 0, nullptr, 1, &bufMemBarrier2, 0, nullptr);
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
@ -18288,14 +18577,22 @@ Please check "CONFIGURATION SECTION" in the code to find macros that you can def
|
|||||||
before each include of this file or change directly in this file to provide
|
before each include of this file or change directly in this file to provide
|
||||||
your own implementation of basic facilities like assert, `min()` and `max()` functions,
|
your own implementation of basic facilities like assert, `min()` and `max()` functions,
|
||||||
mutex, atomic etc.
|
mutex, atomic etc.
|
||||||
The library uses its own implementation of containers by default, but you can switch to using
|
|
||||||
STL containers instead.
|
|
||||||
|
|
||||||
For example, define `VMA_ASSERT(expr)` before including the library to provide
|
For example, define `VMA_ASSERT(expr)` before including the library to provide
|
||||||
custom implementation of the assertion, compatible with your project.
|
custom implementation of the assertion, compatible with your project.
|
||||||
By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
|
By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
|
||||||
and empty otherwise.
|
and empty otherwise.
|
||||||
|
|
||||||
|
Similarly, you can define `VMA_LEAK_LOG_FORMAT` macro to enable printing of leaked (unfreed) allocations,
|
||||||
|
including their names and other parameters. Example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
#define VMA_LEAK_LOG_FORMAT(format, ...) do { \
|
||||||
|
printf((format), __VA_ARGS__); \
|
||||||
|
printf("\n"); \
|
||||||
|
} while(false)
|
||||||
|
\endcode
|
||||||
|
|
||||||
\section config_Vulkan_functions Pointers to Vulkan functions
|
\section config_Vulkan_functions Pointers to Vulkan functions
|
||||||
|
|
||||||
There are multiple ways to import pointers to Vulkan functions in the library.
|
There are multiple ways to import pointers to Vulkan functions in the library.
|
||||||
@ -18550,6 +18847,145 @@ Example use of this extension can be found in the code of the sample and test su
|
|||||||
accompanying this library.
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
\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
|
\page enabling_buffer_device_address Enabling buffer device address
|
||||||
|
|
||||||
Device extension VK_KHR_buffer_device_address
|
Device extension VK_KHR_buffer_device_address
|
||||||
|
Loading…
x
Reference in New Issue
Block a user