3rdparty: Update VMA to version v3.4.0

This commit is contained in:
JordanTheToaster
2026-10-06 15:40:58 +02:00
committed by lightningterror
parent 32ac6e23e4
commit 9bb37321a0
3 changed files with 365 additions and 160 deletions
+7 -2
View File
@@ -1,14 +1,19 @@
# 3.4.0 (2026-??-??) # 3.4.0 (2026-06-05)
- Added file `AGENTS.md` for agentic AI.
- Added member `VmaAllocationCreateInfo::minAlignment` (#523). - Added member `VmaAllocationCreateInfo::minAlignment` (#523).
- Remember to always fully initialize structures with zeros and don't rely on their specific `sizeof` to ensure backward compatibility! - Remember to always fully initialize structures with zeros and don't rely on their specific `sizeof` to ensure backward compatibility!
- Function `vmaCreateBufferWithAlignment` is now deprecated. - Function `vmaCreateBufferWithAlignment` is now deprecated.
- Improvements for external memory export & import (#503): - Improvements for external memory export & import (#503):
- Added functions `vmaCreateDedicatedBuffer`, `vmaCreateDedicatedImage`, `vmaAllocateDedicatedMemory` offering extra parameter `void* pMemoryAllocateNext`. - Added functions `vmaCreateDedicatedBuffer`, `vmaCreateDedicatedImage`, `vmaAllocateDedicatedMemory` offering extra parameter `void* pMemoryAllocateNext`.
- Added function `vmaGetMemoryWin32Handle2` offering extra parameter `VkExternalMemoryHandleTypeFlagBits handleType`. - Added function `vmaGetMemoryWin32Handle2` offering extra parameter `VkExternalMemoryHandleTypeFlagBits handleType`.
- Added member `VmaVulkanFunctions::vkGetPhysicalDeviceProperties2KHR` and macro `VMA_GET_PHYSICAL_DEVICE_PROPERTIES2` to fix validation layer warnings about the usage of legacy commands on Vulkan >= 1.1 (#530, #531).
- Added `VMA_VERSION` macro with library version number (#507). - Added `VMA_VERSION` macro with library version number (#507).
- Added support for `VMA_VULKAN_HEADERS_ALREADY_INCLUDED`. When defined, VMA does not include `<vulkan/vulkan.h>`.
- Improvements in the algorithm choosing memory type when `VMA_MEMORY_USAGE_AUTO*` is used (#520). - Improvements in the algorithm choosing memory type when `VMA_MEMORY_USAGE_AUTO*` is used (#520).
- Fixes for compatibility with C++20 modules on Clang 21 and GCC15 (#513, #514). - Fixed compatibility with C++20 modules on Clang 21 and GCC15 (#513, #514).
- Fixed a bug in buffer-image granularity handling (#517).
- Fixed race conditions in defragmentation (#529, #313) and other places (#525).
- Other fixes and improvements, including compatibility with various platforms and compilers, improvements in documentation, sample application, and tests. - Other fixes and improvements, including compatibility with various platforms and compilers, improvements in documentation, sample application, and tests.
# 3.3.0 (2025-05-12) # 3.3.0 (2025-05-12)
+179 -79
View File
@@ -25,7 +25,7 @@
/** \mainpage Vulkan Memory Allocator /** \mainpage Vulkan Memory Allocator
<b>Version 3.4.0-development</b> <b>Version 3.4.0</b>
Copyright (c) 2017-2026 Advanced Micro Devices, Inc. All rights reserved. \n Copyright (c) 2017-2026 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT \n License: MIT \n
@@ -129,8 +129,10 @@ See documentation chapter: \ref statistics.
extern "C" { extern "C" {
#endif #endif
#if !defined(VULKAN_H_) #ifndef VMA_VULKAN_HEADERS_ALREADY_INCLUDED
#include <vulkan/vulkan.h> #if !defined(VULKAN_H_)
#include <vulkan/vulkan.h>
#endif
#endif #endif
#define VMA_VERSION (VK_MAKE_VERSION(3, 4, 0)) #define VMA_VERSION (VK_MAKE_VERSION(3, 4, 0))
@@ -194,8 +196,16 @@ extern "C" {
#endif #endif
#endif #endif
#if !defined(VMA_GET_PHYSICAL_DEVICE_PROPERTIES2)
#if VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000
#define VMA_GET_PHYSICAL_DEVICE_PROPERTIES2 1
#else
#define VMA_GET_PHYSICAL_DEVICE_PROPERTIES2 0
#endif
#endif
#if !defined(VMA_MEMORY_BUDGET) #if !defined(VMA_MEMORY_BUDGET)
#if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) #if VK_EXT_memory_budget && VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
#define VMA_MEMORY_BUDGET 1 #define VMA_MEMORY_BUDGET 1
#else #else
#define VMA_MEMORY_BUDGET 0 #define VMA_MEMORY_BUDGET 0
@@ -1049,7 +1059,7 @@ typedef struct VmaVulkanFunctions
/// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension.
PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR;
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
/// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2. /// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2.
PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR;
#endif #endif
@@ -1064,6 +1074,10 @@ typedef struct VmaVulkanFunctions
#else #else
void* VMA_NULLABLE vkGetMemoryWin32HandleKHR; void* VMA_NULLABLE vkGetMemoryWin32HandleKHR;
#endif #endif
#if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
/// Fetch from "vkGetPhysicalDeviceProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2.
PFN_vkGetPhysicalDeviceProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceProperties2KHR;
#endif
} VmaVulkanFunctions; } VmaVulkanFunctions;
/// Description of a Allocator to be created. /// Description of a Allocator to be created.
@@ -3125,7 +3139,7 @@ remove them if not needed.
*/ */
#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H) #if !defined(VMA_CONFIGURATION_USER_INCLUDES_H)
#include <cassert> // for assert #include <cassert> // for assert
#include <algorithm> // for min, max, swap #include <algorithm> // for min, max, swap, sort
#include <mutex> #include <mutex>
#else #else
#include VMA_CONFIGURATION_USER_INCLUDES_H #include VMA_CONFIGURATION_USER_INCLUDES_H
@@ -3442,6 +3456,11 @@ If providing your own implementation, you need to implement a subset of std::ato
#define VMA_ATOMIC_UINT64 std::atomic<uint64_t> #define VMA_ATOMIC_UINT64 std::atomic<uint64_t>
#endif #endif
#ifndef VMA_ATOMIC_BOOL
#include <atomic>
#define VMA_ATOMIC_BOOL std::atomic<bool>
#endif
#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY #ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
/** /**
Every allocation will have its own memory block. Every allocation will have its own memory block.
@@ -6549,6 +6568,7 @@ public:
uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
uint32_t GetId() const { return m_Id; } uint32_t GetId() const { return m_Id; }
void* GetMappedData() const { return m_pMappedData; } void* GetMappedData() const { return m_pMappedData; }
bool IsMapped() const { return m_IsMapped.load(); }
uint32_t GetMapRefCount() const { return m_MapCount; } uint32_t GetMapRefCount() const { return m_MapCount; }
// Call when allocation/free was made from m_pMetadata. // Call when allocation/free was made from m_pMetadata.
@@ -6596,12 +6616,18 @@ private:
/* /*
Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory. Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
Also protects m_MapCount, m_pMappedData. Also protects m_MapCount, m_pMappedData.
m_IsMapped mirrors whether m_pMappedData is non-null and can be read without this mutex in allocation heuristics.
Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex. Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
*/ */
VMA_MUTEX m_MapAndBindMutex; VMA_MUTEX m_MapAndBindMutex;
VmaMappingHysteresis m_MappingHysteresis; VmaMappingHysteresis m_MappingHysteresis;
uint32_t m_MapCount; uint32_t m_MapCount;
void* m_pMappedData; void* m_pMappedData;
/*
Mirrors `m_pMappedData != VMA_NULL` for allocation heuristics that only need mapped/unmapped state.
This is atomic so allocation scans don't race with Map/Unmap while the actual mapped pointer remains protected by m_MapAndBindMutex.
*/
VMA_ATOMIC_BOOL m_IsMapped;
VmaWin32Handle m_Handle; VmaWin32Handle m_Handle;
}; };
@@ -7166,6 +7192,14 @@ void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json)
#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY #ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY
// Before deleting object of this class remember to call 'Destroy()' // Before deleting object of this class remember to call 'Destroy()'
/*
Tracks block occupancy at VkPhysicalDeviceLimits::bufferImageGranularity page boundaries.
For each granularity-sized page in a memory block, m_RegionInfo stores:
- allocCount: how many allocations touch this page as their first or last page.
- allocType: the remembered VmaSuballocationType for that page while allocCount > 0.
Only boundary pages are tracked because buffer-image granularity conflicts matter when
adjacent allocations share the same granularity page at the start or end of an allocation.
*/
class VmaBlockBufferImageGranularity final class VmaBlockBufferImageGranularity final
{ {
public: public:
@@ -7188,6 +7222,21 @@ public:
VkDeviceSize& inOutAllocSize, VkDeviceSize& inOutAllocSize,
VkDeviceSize& inOutAllocAlignment) const; VkDeviceSize& inOutAllocAlignment) const;
/*
Checks whether an allocation placed in a free block would conflict with existing
allocations due to buffer-image granularity requirements and, if needed, aligns the
allocation start to the next granularity page.
Parameters:
- inOutAllocOffset: candidate allocation offset inside the block; may be increased.
- allocSize: size of the allocation being placed.
- blockOffset: start offset of the free block being considered.
- blockSize: size of the free block being considered.
- allocType: VmaSuballocationType of the allocation being placed.
Returns true when the placement conflicts or no longer fits in the free block after alignment.
Returns false when the placement is valid, possibly after updating inOutAllocOffset.
*/
bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset, bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,
VkDeviceSize allocSize, VkDeviceSize allocSize,
VkDeviceSize blockOffset, VkDeviceSize blockOffset,
@@ -7276,56 +7325,62 @@ bool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOut
VkDeviceSize blockSize, VkDeviceSize blockSize,
VmaSuballocationType allocType) const VmaSuballocationType allocType) const
{ {
if (IsEnabled()) if (!IsEnabled())
return false;
uint32_t startPage = GetStartPage(inOutAllocOffset);
if (m_RegionInfo[startPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
{ {
uint32_t startPage = GetStartPage(inOutAllocOffset); inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
if (blockSize < allocSize + inOutAllocOffset - blockOffset)
return true;
startPage = GetStartPage(inOutAllocOffset);
if (m_RegionInfo[startPage].allocCount > 0 && if (m_RegionInfo[startPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType)) VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
{
inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
if (blockSize < allocSize + inOutAllocOffset - blockOffset)
return true;
++startPage;
}
uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
if (endPage != startPage &&
m_RegionInfo[endPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
{ {
return true; return true;
} }
} }
uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
if (endPage != startPage &&
m_RegionInfo[endPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
{
return true;
}
return false; return false;
} }
void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size) void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size)
{ {
if (IsEnabled()) if (!IsEnabled())
{ return;
uint32_t startPage = GetStartPage(offset);
AllocPage(m_RegionInfo[startPage], allocType);
uint32_t endPage = GetEndPage(offset, size); uint32_t startPage = GetStartPage(offset);
if (startPage != endPage) AllocPage(m_RegionInfo[startPage], allocType);
AllocPage(m_RegionInfo[endPage], allocType);
} uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
AllocPage(m_RegionInfo[endPage], allocType);
} }
void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size) void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size)
{ {
if (IsEnabled()) if (!IsEnabled())
return;
uint32_t startPage = GetStartPage(offset);
--m_RegionInfo[startPage].allocCount;
if (m_RegionInfo[startPage].allocCount == 0)
m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
{ {
uint32_t startPage = GetStartPage(offset); --m_RegionInfo[endPage].allocCount;
--m_RegionInfo[startPage].allocCount; if (m_RegionInfo[endPage].allocCount == 0)
if (m_RegionInfo[startPage].allocCount == 0) m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
{
--m_RegionInfo[endPage].allocCount;
if (m_RegionInfo[endPage].allocCount == 0)
m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
}
} }
} }
@@ -7350,36 +7405,38 @@ VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity
bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx, bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx,
VkDeviceSize offset, VkDeviceSize size) const VkDeviceSize offset, VkDeviceSize size) const
{ {
if (IsEnabled()) if (!IsEnabled())
{ return true;
uint32_t start = GetStartPage(offset);
++ctx.pageAllocs[start];
VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
uint32_t end = GetEndPage(offset, size); uint32_t start = GetStartPage(offset);
if (start != end) ++ctx.pageAllocs[start];
{ VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
++ctx.pageAllocs[end];
VMA_VALIDATE(m_RegionInfo[end].allocCount > 0); uint32_t end = GetEndPage(offset, size);
} if (start != end)
{
++ctx.pageAllocs[end];
VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);
} }
return true; return true;
} }
bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const
{ {
// Check proper page structure if (!IsEnabled())
if (IsEnabled()) return true;
{
VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
for (uint32_t page = 0; page < m_RegionCount; ++page) // Check proper page structure
{ VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
} for (uint32_t page = 0; page < m_RegionCount; ++page)
vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount); {
ctx.pageAllocs = VMA_NULL; VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
} }
vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);
ctx.pageAllocs = VMA_NULL;
return true; return true;
} }
@@ -10921,7 +10978,8 @@ 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),
m_IsMapped(false){}
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock() VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
{ {
@@ -10977,6 +11035,8 @@ void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
VMA_ASSERT_LEAK(m_hMemory != VK_NULL_HANDLE); VMA_ASSERT_LEAK(m_hMemory != VK_NULL_HANDLE);
allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory); allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
m_hMemory = VK_NULL_HANDLE; m_hMemory = VK_NULL_HANDLE;
m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
vma_delete(allocator, m_pMetadata); vma_delete(allocator, m_pMetadata);
m_pMetadata = VMA_NULL; m_pMetadata = VMA_NULL;
@@ -10997,6 +11057,7 @@ void VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator)
if (m_MapCount == 0) if (m_MapCount == 0)
{ {
m_pMappedData = VMA_NULL; m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
} }
} }
@@ -11057,6 +11118,7 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void
if (result == VK_SUCCESS) if (result == VK_SUCCESS)
{ {
VMA_ASSERT(m_pMappedData != VMA_NULL); VMA_ASSERT(m_pMappedData != VMA_NULL);
m_IsMapped.store(true);
m_MappingHysteresis.PostMap(); m_MappingHysteresis.PostMap();
m_MapCount = count; m_MapCount = count;
if (ppData != VMA_NULL) if (ppData != VMA_NULL)
@@ -11082,6 +11144,7 @@ void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
if (totalMapCount == 0) if (totalMapCount == 0)
{ {
m_pMappedData = VMA_NULL; m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
} }
m_MappingHysteresis.PostUnmap(); m_MappingHysteresis.PostUnmap();
@@ -11743,7 +11806,7 @@ VkResult VmaBlockVector::AllocatePage(
{ {
VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
VMA_ASSERT(pCurrBlock); VMA_ASSERT(pCurrBlock);
const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL; const bool isBlockMapped = pCurrBlock->IsMapped();
if((mappingI == 0) == (isMappingAllowed == isBlockMapped)) if((mappingI == 0) == (isMappingAllowed == isBlockMapped))
{ {
VkResult res = AllocateFromBlock( VkResult res = AllocateFromBlock(
@@ -12221,6 +12284,8 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
m_BlockVectorCount = 1; m_BlockVectorCount = 1;
m_PoolBlockVector = &info.pool->m_BlockVector; m_PoolBlockVector = &info.pool->m_BlockVector;
m_pBlockVectors = &m_PoolBlockVector; m_pBlockVectors = &m_PoolBlockVector;
VmaMutexLockWrite lock(m_PoolBlockVector->m_Mutex, hAllocator->m_UseMutex);
m_PoolBlockVector->SetIncrementalSort(false); m_PoolBlockVector->SetIncrementalSort(false);
m_PoolBlockVector->SortByFreeSize(); m_PoolBlockVector->SortByFreeSize();
} }
@@ -12234,6 +12299,7 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
VmaBlockVector* vector = m_pBlockVectors[i]; VmaBlockVector* vector = m_pBlockVectors[i];
if (vector != VMA_NULL) if (vector != VMA_NULL)
{ {
VmaMutexLockWrite lock(vector->m_Mutex, hAllocator->m_UseMutex);
vector->SetIncrementalSort(false); vector->SetIncrementalSort(false);
vector->SortByFreeSize(); vector->SortByFreeSize();
} }
@@ -12264,6 +12330,7 @@ VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
{ {
if (m_PoolBlockVector != VMA_NULL) if (m_PoolBlockVector != VMA_NULL)
{ {
VmaMutexLockWrite lock(m_PoolBlockVector->m_Mutex, m_PoolBlockVector->m_hAllocator->m_UseMutex);
m_PoolBlockVector->SetIncrementalSort(true); m_PoolBlockVector->SetIncrementalSort(true);
} }
else else
@@ -12272,7 +12339,10 @@ VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
{ {
VmaBlockVector* vector = m_pBlockVectors[i]; VmaBlockVector* vector = m_pBlockVectors[i];
if (vector != VMA_NULL) if (vector != VMA_NULL)
{
VmaMutexLockWrite lock(vector->m_Mutex, vector->m_hAllocator->m_UseMutex);
vector->SetIncrementalSort(true); vector->SetIncrementalSort(true);
}
} }
} }
@@ -12370,7 +12440,11 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
{ {
case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY: case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:
{ {
uint8_t mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation); uint8_t mapCount = 0;
{
VmaMutexLockWrite swapLock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation);
}
if (mapCount > 0) if (mapCount > 0)
{ {
allocator = vector->m_hAllocator; allocator = vector->m_hAllocator;
@@ -13287,7 +13361,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
} }
#endif #endif
} }
#if !(VMA_MEMORY_BUDGET) #if !(VMA_MEMORY_BUDGET) || !(VMA_GET_PHYSICAL_DEVICE_PROPERTIES2)
if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
{ {
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros."); VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.");
@@ -13363,8 +13437,35 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
ImportVulkanFunctions(pCreateInfo->pVulkanFunctions); ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties); // Call vkGetPhysicalDeviceProperties[2][KHR].
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps); #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR)
{
VkPhysicalDeviceProperties2KHR props2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR)(m_PhysicalDevice, &props2);
memcpy(&m_PhysicalDeviceProperties, &props2.properties, sizeof(m_PhysicalDeviceProperties));
}
else
#endif
{
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);
}
// Call vkGetPhysicalDeviceMemoryProperties[2][KHR].
#if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR)
{
VkPhysicalDeviceMemoryProperties2KHR memProps2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR)(m_PhysicalDevice, &memProps2);
memcpy(&m_MemProps, &memProps2.memoryProperties, sizeof(m_MemProps));
}
else
#endif
{
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
}
VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT)); VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT));
VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY)); VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));
@@ -13507,6 +13608,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Static()
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;
m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2)vkGetPhysicalDeviceProperties2;
} }
#endif #endif
@@ -13558,8 +13660,9 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties2KHR);
#endif #endif
#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 #if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000
@@ -13618,18 +13721,22 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
} }
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
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");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2");
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. // 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"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR");
} }
else if(m_UseExtMemoryBudget) else if(m_UseExtMemoryBudget)
{ {
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR");
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. // 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"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2");
} }
#endif #endif
@@ -13649,17 +13756,6 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
} }
#endif // #if VMA_BIND_MEMORY2 #endif // #if VMA_BIND_MEMORY2
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
}
else if(m_UseExtMemoryBudget)
{
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
}
#endif // #if VMA_MEMORY_BUDGET
#if VMA_VULKAN_VERSION >= 1003000 #if VMA_VULKAN_VERSION >= 1003000
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
{ {
@@ -13722,12 +13818,14 @@ void VmaAllocator_T::ValidateVulkanFunctions() const
} }
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR != VMA_NULL);
} }
#endif #endif
#if VMA_EXTERNAL_MEMORY_WIN32 #if VMA_EXTERNAL_MEMORY_WIN32
if (m_UseKhrExternalMemoryWin32) if (m_UseKhrExternalMemoryWin32)
{ {
@@ -15608,6 +15706,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR) COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR) COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR) COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR) COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
@@ -15646,6 +15745,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
{ {
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR) COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2KHR, vkGetPhysicalDeviceProperties2KHR)
} }
#endif #endif
#if VMA_EXTERNAL_MEMORY_WIN32 #if VMA_EXTERNAL_MEMORY_WIN32
+179 -79
View File
@@ -25,7 +25,7 @@
/** \mainpage Vulkan Memory Allocator /** \mainpage Vulkan Memory Allocator
<b>Version 3.4.0-development</b> <b>Version 3.4.0</b>
Copyright (c) 2017-2026 Advanced Micro Devices, Inc. All rights reserved. \n Copyright (c) 2017-2026 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT \n License: MIT \n
@@ -129,8 +129,10 @@ See documentation chapter: \ref statistics.
extern "C" { extern "C" {
#endif #endif
#if !defined(VULKAN_H_) #ifndef VMA_VULKAN_HEADERS_ALREADY_INCLUDED
#include <vulkan/vulkan.h> #if !defined(VULKAN_H_)
#include <vulkan/vulkan.h>
#endif
#endif #endif
#define VMA_VERSION (VK_MAKE_VERSION(3, 4, 0)) #define VMA_VERSION (VK_MAKE_VERSION(3, 4, 0))
@@ -194,8 +196,16 @@ extern "C" {
#endif #endif
#endif #endif
#if !defined(VMA_GET_PHYSICAL_DEVICE_PROPERTIES2)
#if VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000
#define VMA_GET_PHYSICAL_DEVICE_PROPERTIES2 1
#else
#define VMA_GET_PHYSICAL_DEVICE_PROPERTIES2 0
#endif
#endif
#if !defined(VMA_MEMORY_BUDGET) #if !defined(VMA_MEMORY_BUDGET)
#if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) #if VK_EXT_memory_budget && VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
#define VMA_MEMORY_BUDGET 1 #define VMA_MEMORY_BUDGET 1
#else #else
#define VMA_MEMORY_BUDGET 0 #define VMA_MEMORY_BUDGET 0
@@ -1049,7 +1059,7 @@ typedef struct VmaVulkanFunctions
/// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension.
PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR;
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
/// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2. /// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2.
PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR;
#endif #endif
@@ -1064,6 +1074,10 @@ typedef struct VmaVulkanFunctions
#else #else
void* VMA_NULLABLE vkGetMemoryWin32HandleKHR; void* VMA_NULLABLE vkGetMemoryWin32HandleKHR;
#endif #endif
#if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
/// Fetch from "vkGetPhysicalDeviceProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2.
PFN_vkGetPhysicalDeviceProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceProperties2KHR;
#endif
} VmaVulkanFunctions; } VmaVulkanFunctions;
/// Description of a Allocator to be created. /// Description of a Allocator to be created.
@@ -3125,7 +3139,7 @@ remove them if not needed.
*/ */
#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H) #if !defined(VMA_CONFIGURATION_USER_INCLUDES_H)
#include <cassert> // for assert #include <cassert> // for assert
#include <algorithm> // for min, max, swap #include <algorithm> // for min, max, swap, sort
#include <mutex> #include <mutex>
#else #else
#include VMA_CONFIGURATION_USER_INCLUDES_H #include VMA_CONFIGURATION_USER_INCLUDES_H
@@ -3442,6 +3456,11 @@ If providing your own implementation, you need to implement a subset of std::ato
#define VMA_ATOMIC_UINT64 std::atomic<uint64_t> #define VMA_ATOMIC_UINT64 std::atomic<uint64_t>
#endif #endif
#ifndef VMA_ATOMIC_BOOL
#include <atomic>
#define VMA_ATOMIC_BOOL std::atomic<bool>
#endif
#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY #ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
/** /**
Every allocation will have its own memory block. Every allocation will have its own memory block.
@@ -6549,6 +6568,7 @@ public:
uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
uint32_t GetId() const { return m_Id; } uint32_t GetId() const { return m_Id; }
void* GetMappedData() const { return m_pMappedData; } void* GetMappedData() const { return m_pMappedData; }
bool IsMapped() const { return m_IsMapped.load(); }
uint32_t GetMapRefCount() const { return m_MapCount; } uint32_t GetMapRefCount() const { return m_MapCount; }
// Call when allocation/free was made from m_pMetadata. // Call when allocation/free was made from m_pMetadata.
@@ -6596,12 +6616,18 @@ private:
/* /*
Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory. Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
Also protects m_MapCount, m_pMappedData. Also protects m_MapCount, m_pMappedData.
m_IsMapped mirrors whether m_pMappedData is non-null and can be read without this mutex in allocation heuristics.
Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex. Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
*/ */
VMA_MUTEX m_MapAndBindMutex; VMA_MUTEX m_MapAndBindMutex;
VmaMappingHysteresis m_MappingHysteresis; VmaMappingHysteresis m_MappingHysteresis;
uint32_t m_MapCount; uint32_t m_MapCount;
void* m_pMappedData; void* m_pMappedData;
/*
Mirrors `m_pMappedData != VMA_NULL` for allocation heuristics that only need mapped/unmapped state.
This is atomic so allocation scans don't race with Map/Unmap while the actual mapped pointer remains protected by m_MapAndBindMutex.
*/
VMA_ATOMIC_BOOL m_IsMapped;
VmaWin32Handle m_Handle; VmaWin32Handle m_Handle;
}; };
@@ -7166,6 +7192,14 @@ void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json)
#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY #ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY
// Before deleting object of this class remember to call 'Destroy()' // Before deleting object of this class remember to call 'Destroy()'
/*
Tracks block occupancy at VkPhysicalDeviceLimits::bufferImageGranularity page boundaries.
For each granularity-sized page in a memory block, m_RegionInfo stores:
- allocCount: how many allocations touch this page as their first or last page.
- allocType: the remembered VmaSuballocationType for that page while allocCount > 0.
Only boundary pages are tracked because buffer-image granularity conflicts matter when
adjacent allocations share the same granularity page at the start or end of an allocation.
*/
class VmaBlockBufferImageGranularity final class VmaBlockBufferImageGranularity final
{ {
public: public:
@@ -7188,6 +7222,21 @@ public:
VkDeviceSize& inOutAllocSize, VkDeviceSize& inOutAllocSize,
VkDeviceSize& inOutAllocAlignment) const; VkDeviceSize& inOutAllocAlignment) const;
/*
Checks whether an allocation placed in a free block would conflict with existing
allocations due to buffer-image granularity requirements and, if needed, aligns the
allocation start to the next granularity page.
Parameters:
- inOutAllocOffset: candidate allocation offset inside the block; may be increased.
- allocSize: size of the allocation being placed.
- blockOffset: start offset of the free block being considered.
- blockSize: size of the free block being considered.
- allocType: VmaSuballocationType of the allocation being placed.
Returns true when the placement conflicts or no longer fits in the free block after alignment.
Returns false when the placement is valid, possibly after updating inOutAllocOffset.
*/
bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset, bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,
VkDeviceSize allocSize, VkDeviceSize allocSize,
VkDeviceSize blockOffset, VkDeviceSize blockOffset,
@@ -7276,56 +7325,62 @@ bool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOut
VkDeviceSize blockSize, VkDeviceSize blockSize,
VmaSuballocationType allocType) const VmaSuballocationType allocType) const
{ {
if (IsEnabled()) if (!IsEnabled())
return false;
uint32_t startPage = GetStartPage(inOutAllocOffset);
if (m_RegionInfo[startPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
{ {
uint32_t startPage = GetStartPage(inOutAllocOffset); inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
if (blockSize < allocSize + inOutAllocOffset - blockOffset)
return true;
startPage = GetStartPage(inOutAllocOffset);
if (m_RegionInfo[startPage].allocCount > 0 && if (m_RegionInfo[startPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType)) VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
{
inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
if (blockSize < allocSize + inOutAllocOffset - blockOffset)
return true;
++startPage;
}
uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
if (endPage != startPage &&
m_RegionInfo[endPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
{ {
return true; return true;
} }
} }
uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
if (endPage != startPage &&
m_RegionInfo[endPage].allocCount > 0 &&
VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
{
return true;
}
return false; return false;
} }
void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size) void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size)
{ {
if (IsEnabled()) if (!IsEnabled())
{ return;
uint32_t startPage = GetStartPage(offset);
AllocPage(m_RegionInfo[startPage], allocType);
uint32_t endPage = GetEndPage(offset, size); uint32_t startPage = GetStartPage(offset);
if (startPage != endPage) AllocPage(m_RegionInfo[startPage], allocType);
AllocPage(m_RegionInfo[endPage], allocType);
} uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
AllocPage(m_RegionInfo[endPage], allocType);
} }
void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size) void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size)
{ {
if (IsEnabled()) if (!IsEnabled())
return;
uint32_t startPage = GetStartPage(offset);
--m_RegionInfo[startPage].allocCount;
if (m_RegionInfo[startPage].allocCount == 0)
m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
{ {
uint32_t startPage = GetStartPage(offset); --m_RegionInfo[endPage].allocCount;
--m_RegionInfo[startPage].allocCount; if (m_RegionInfo[endPage].allocCount == 0)
if (m_RegionInfo[startPage].allocCount == 0) m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
uint32_t endPage = GetEndPage(offset, size);
if (startPage != endPage)
{
--m_RegionInfo[endPage].allocCount;
if (m_RegionInfo[endPage].allocCount == 0)
m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
}
} }
} }
@@ -7350,36 +7405,38 @@ VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity
bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx, bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx,
VkDeviceSize offset, VkDeviceSize size) const VkDeviceSize offset, VkDeviceSize size) const
{ {
if (IsEnabled()) if (!IsEnabled())
{ return true;
uint32_t start = GetStartPage(offset);
++ctx.pageAllocs[start];
VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
uint32_t end = GetEndPage(offset, size); uint32_t start = GetStartPage(offset);
if (start != end) ++ctx.pageAllocs[start];
{ VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
++ctx.pageAllocs[end];
VMA_VALIDATE(m_RegionInfo[end].allocCount > 0); uint32_t end = GetEndPage(offset, size);
} if (start != end)
{
++ctx.pageAllocs[end];
VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);
} }
return true; return true;
} }
bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const
{ {
// Check proper page structure if (!IsEnabled())
if (IsEnabled()) return true;
{
VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
for (uint32_t page = 0; page < m_RegionCount; ++page) // Check proper page structure
{ VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
} for (uint32_t page = 0; page < m_RegionCount; ++page)
vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount); {
ctx.pageAllocs = VMA_NULL; VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
} }
vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);
ctx.pageAllocs = VMA_NULL;
return true; return true;
} }
@@ -10921,7 +10978,8 @@ 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),
m_IsMapped(false){}
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock() VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
{ {
@@ -10977,6 +11035,8 @@ void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
VMA_ASSERT_LEAK(m_hMemory != VK_NULL_HANDLE); VMA_ASSERT_LEAK(m_hMemory != VK_NULL_HANDLE);
allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory); allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
m_hMemory = VK_NULL_HANDLE; m_hMemory = VK_NULL_HANDLE;
m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
vma_delete(allocator, m_pMetadata); vma_delete(allocator, m_pMetadata);
m_pMetadata = VMA_NULL; m_pMetadata = VMA_NULL;
@@ -10997,6 +11057,7 @@ void VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator)
if (m_MapCount == 0) if (m_MapCount == 0)
{ {
m_pMappedData = VMA_NULL; m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
} }
} }
@@ -11057,6 +11118,7 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void
if (result == VK_SUCCESS) if (result == VK_SUCCESS)
{ {
VMA_ASSERT(m_pMappedData != VMA_NULL); VMA_ASSERT(m_pMappedData != VMA_NULL);
m_IsMapped.store(true);
m_MappingHysteresis.PostMap(); m_MappingHysteresis.PostMap();
m_MapCount = count; m_MapCount = count;
if (ppData != VMA_NULL) if (ppData != VMA_NULL)
@@ -11082,6 +11144,7 @@ void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
if (totalMapCount == 0) if (totalMapCount == 0)
{ {
m_pMappedData = VMA_NULL; m_pMappedData = VMA_NULL;
m_IsMapped.store(false);
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
} }
m_MappingHysteresis.PostUnmap(); m_MappingHysteresis.PostUnmap();
@@ -11743,7 +11806,7 @@ VkResult VmaBlockVector::AllocatePage(
{ {
VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
VMA_ASSERT(pCurrBlock); VMA_ASSERT(pCurrBlock);
const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL; const bool isBlockMapped = pCurrBlock->IsMapped();
if((mappingI == 0) == (isMappingAllowed == isBlockMapped)) if((mappingI == 0) == (isMappingAllowed == isBlockMapped))
{ {
VkResult res = AllocateFromBlock( VkResult res = AllocateFromBlock(
@@ -12221,6 +12284,8 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
m_BlockVectorCount = 1; m_BlockVectorCount = 1;
m_PoolBlockVector = &info.pool->m_BlockVector; m_PoolBlockVector = &info.pool->m_BlockVector;
m_pBlockVectors = &m_PoolBlockVector; m_pBlockVectors = &m_PoolBlockVector;
VmaMutexLockWrite lock(m_PoolBlockVector->m_Mutex, hAllocator->m_UseMutex);
m_PoolBlockVector->SetIncrementalSort(false); m_PoolBlockVector->SetIncrementalSort(false);
m_PoolBlockVector->SortByFreeSize(); m_PoolBlockVector->SortByFreeSize();
} }
@@ -12234,6 +12299,7 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
VmaBlockVector* vector = m_pBlockVectors[i]; VmaBlockVector* vector = m_pBlockVectors[i];
if (vector != VMA_NULL) if (vector != VMA_NULL)
{ {
VmaMutexLockWrite lock(vector->m_Mutex, hAllocator->m_UseMutex);
vector->SetIncrementalSort(false); vector->SetIncrementalSort(false);
vector->SortByFreeSize(); vector->SortByFreeSize();
} }
@@ -12264,6 +12330,7 @@ VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
{ {
if (m_PoolBlockVector != VMA_NULL) if (m_PoolBlockVector != VMA_NULL)
{ {
VmaMutexLockWrite lock(m_PoolBlockVector->m_Mutex, m_PoolBlockVector->m_hAllocator->m_UseMutex);
m_PoolBlockVector->SetIncrementalSort(true); m_PoolBlockVector->SetIncrementalSort(true);
} }
else else
@@ -12272,7 +12339,10 @@ VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
{ {
VmaBlockVector* vector = m_pBlockVectors[i]; VmaBlockVector* vector = m_pBlockVectors[i];
if (vector != VMA_NULL) if (vector != VMA_NULL)
{
VmaMutexLockWrite lock(vector->m_Mutex, vector->m_hAllocator->m_UseMutex);
vector->SetIncrementalSort(true); vector->SetIncrementalSort(true);
}
} }
} }
@@ -12370,7 +12440,11 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
{ {
case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY: case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:
{ {
uint8_t mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation); uint8_t mapCount = 0;
{
VmaMutexLockWrite swapLock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation);
}
if (mapCount > 0) if (mapCount > 0)
{ {
allocator = vector->m_hAllocator; allocator = vector->m_hAllocator;
@@ -13287,7 +13361,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
} }
#endif #endif
} }
#if !(VMA_MEMORY_BUDGET) #if !(VMA_MEMORY_BUDGET) || !(VMA_GET_PHYSICAL_DEVICE_PROPERTIES2)
if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
{ {
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros."); VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.");
@@ -13363,8 +13437,35 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
ImportVulkanFunctions(pCreateInfo->pVulkanFunctions); ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties); // Call vkGetPhysicalDeviceProperties[2][KHR].
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps); #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR)
{
VkPhysicalDeviceProperties2KHR props2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR)(m_PhysicalDevice, &props2);
memcpy(&m_PhysicalDeviceProperties, &props2.properties, sizeof(m_PhysicalDeviceProperties));
}
else
#endif
{
(*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);
}
// Call vkGetPhysicalDeviceMemoryProperties[2][KHR].
#if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR)
{
VkPhysicalDeviceMemoryProperties2KHR memProps2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR)(m_PhysicalDevice, &memProps2);
memcpy(&m_MemProps, &memProps2.memoryProperties, sizeof(m_MemProps));
}
else
#endif
{
(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
}
VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT)); VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT));
VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY)); VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));
@@ -13507,6 +13608,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Static()
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;
m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2)vkGetPhysicalDeviceProperties2;
} }
#endif #endif
@@ -13558,8 +13660,9 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties2KHR);
#endif #endif
#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 #if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000
@@ -13618,18 +13721,22 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
} }
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
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");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2");
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. // 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"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR");
} }
else if(m_UseExtMemoryBudget) else if(m_UseExtMemoryBudget)
{ {
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR");
// Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. // 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"); VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR, PFN_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2");
} }
#endif #endif
@@ -13649,17 +13756,6 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
} }
#endif // #if VMA_BIND_MEMORY2 #endif // #if VMA_BIND_MEMORY2
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");
}
else if(m_UseExtMemoryBudget)
{
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
}
#endif // #if VMA_MEMORY_BUDGET
#if VMA_VULKAN_VERSION >= 1003000 #if VMA_VULKAN_VERSION >= 1003000
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
{ {
@@ -13722,12 +13818,14 @@ void VmaAllocator_T::ValidateVulkanFunctions() const
} }
#endif #endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 #if VMA_GET_PHYSICAL_DEVICE_PROPERTIES2
if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties2KHR != VMA_NULL);
} }
#endif #endif
#if VMA_EXTERNAL_MEMORY_WIN32 #if VMA_EXTERNAL_MEMORY_WIN32
if (m_UseKhrExternalMemoryWin32) if (m_UseKhrExternalMemoryWin32)
{ {
@@ -15608,6 +15706,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR) COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR)
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR) COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR) COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR)
COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR) COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR)
@@ -15646,6 +15745,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk(
if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
{ {
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR) COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR)
COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties2KHR, vkGetPhysicalDeviceProperties2KHR)
} }
#endif #endif
#if VMA_EXTERNAL_MEMORY_WIN32 #if VMA_EXTERNAL_MEMORY_WIN32