updated vk_mem_alloc.h to fix startup issue with AMD 6000 series GPUs using SteamVR on Windows

This commit is contained in:
Cyberrebell 2022-06-12 23:36:06 +02:00
parent 803d25a20a
commit 6a2bd6c936
2 changed files with 53 additions and 99 deletions

View File

@ -709,7 +709,7 @@ Files extracted from upstream source:
SDK release: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/layers/generated/vk_enum_string_helper.h
`vk_mem_alloc.h` is taken from https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
Version: 3.0.1-development (2022-03-28), commit `5b598e0a359381d7e2a94149210a1b7642024ae5`
Version: 3.0.1 (2022-06-10), commit `cfdc0f8775ab3258a3b9c4e47d8ce4b6f52a5441`
`vk_mem_alloc.cpp` is a Godot file and should be preserved on updates.
Patches in the `patches` directory should be re-applied after updates.

View File

@ -25,7 +25,7 @@
/** \mainpage Vulkan Memory Allocator
<b>Version 3.0.1-development (2022-03-28)</b>
<b>Version 3.0.1 (2022-05-26)</b>
Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT
@ -300,9 +300,9 @@ extern "C" {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// INTERFACE
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -488,7 +488,7 @@ typedef enum VmaMemoryUsage
When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
in VmaAllocationCreateInfo::flags.
It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
and not with generic memory allocation functions.
@ -552,7 +552,7 @@ typedef enum VmaAllocationCreateFlagBits
*/
VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
/** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead.
Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
null-terminated string. Instead of copying pointer value, a local copy of the
string is made and stored in allocation's `pName`. The string is automatically
@ -579,14 +579,14 @@ typedef enum VmaAllocationCreateFlagBits
*/
VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
/** \brief Set this flag if the allocated memory will have aliasing resources.
Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
*/
VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200,
/**
Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
@ -602,7 +602,7 @@ typedef enum VmaAllocationCreateFlagBits
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400,
/**
Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
- If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
- If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
@ -724,7 +724,7 @@ typedef enum VmaDefragmentationFlagBits
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8,
/// A bit mask to extract only `ALGORITHM` bits from entire set of flags.
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT |
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT |
VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT |
@ -980,7 +980,7 @@ typedef struct VmaVulkanFunctions
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
/// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR;
/// Fetch "vkGetImageMemoryRequirements 2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
/// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR;
#endif
#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
@ -1117,19 +1117,19 @@ typedef struct VmaStatistics
*/
uint32_t blockCount;
/** \brief Number of #VmaAllocation objects allocated.
Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`.
*/
uint32_t allocationCount;
/** \brief Number of bytes allocated in `VkDeviceMemory` blocks.
\note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object
(e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls
"allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image.
*/
VkDeviceSize blockBytes;
/** \brief Total number of bytes occupied by all #VmaAllocation objects.
Always less or equal than `blockBytes`.
Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan
but unused by any #VmaAllocation.
@ -1387,9 +1387,9 @@ typedef struct VmaAllocationInfo
*/
void* VMA_NULLABLE pUserData;
/** \brief Custom allocation name that was set with vmaSetAllocationName().
It can change after call to vmaSetAllocationName() for this allocation.
Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with
additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].
*/
@ -1429,7 +1429,7 @@ typedef struct VmaDefragmentationMove
/// Allocation that should be moved.
VmaAllocation VMA_NOT_NULL srcAllocation;
/** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`.
\warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,
to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory().
vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory.
@ -1446,16 +1446,16 @@ typedef struct VmaDefragmentationPassMoveInfo
/// Number of elements in the `pMoves` array.
uint32_t moveCount;
/** \brief Array of moves to be performed by the user in the current defragmentation pass.
Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass().
For each element, you should:
1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset.
2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`.
3. Make sure these commands finished executing on the GPU.
4. Destroy the old buffer/image.
Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass().
After this call, the allocation will point to the new place in memory.
@ -1539,7 +1539,7 @@ typedef struct VmaVirtualAllocationCreateInfo
typedef struct VmaVirtualAllocationInfo
{
/** \brief Offset of the allocation.
Offset at which the allocation was made.
*/
VkDeviceSize offset;
@ -2364,7 +2364,7 @@ vkDestroyBuffer(device, buffer, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
It it safe to pass null as buffer and/or allocation.
It is safe to pass null as buffer and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
VmaAllocator VMA_NOT_NULL allocator,
@ -2396,7 +2396,7 @@ vkDestroyImage(device, image, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
It it safe to pass null as image and/or allocation.
It is safe to pass null as image and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
VmaAllocator VMA_NOT_NULL allocator,
@ -2555,9 +2555,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// IMPLEMENTATION
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -2578,6 +2578,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
#ifdef _MSC_VER
#include <intrin.h> // For functions like __popcnt, _BitScanForward etc.
#endif
#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
#include <bit> // For std::popcount
#endif
/*******************************************************************************
CONFIGURATION SECTION
@ -3180,12 +3183,16 @@ But you need to check in runtime whether user's CPU supports these, as some old
*/
static inline uint32_t VmaCountBitsSet(uint32_t v)
{
#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
return std::popcount(v);
#else
uint32_t c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;
return c;
#endif
}
static inline uint8_t VmaBitScanLSB(uint64_t mask)
@ -3374,60 +3381,6 @@ static inline bool VmaStrIsEmpty(const char* pStr)
return pStr == VMA_NULL || *pStr == '\0';
}
#if VMA_STATS_STRING_ENABLED
static const char* VmaAlgorithmToStr(uint32_t algorithm)
{
switch (algorithm)
{
case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
return "Linear";
case 0:
return "TLSF";
default:
VMA_ASSERT(0);
return "";
}
}
#endif // VMA_STATS_STRING_ENABLED
#ifndef VMA_SORT
template<typename Iterator, typename Compare>
Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
{
Iterator centerValue = end; --centerValue;
Iterator insertIndex = beg;
for (Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
{
if (cmp(*memTypeIndex, *centerValue))
{
if (insertIndex != memTypeIndex)
{
VMA_SWAP(*memTypeIndex, *insertIndex);
}
++insertIndex;
}
}
if (insertIndex != centerValue)
{
VMA_SWAP(*insertIndex, *centerValue);
}
return insertIndex;
}
template<typename Iterator, typename Compare>
void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
{
if (beg < end)
{
Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
VmaQuickSort<Iterator, Compare>(beg, it, cmp);
VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
}
}
#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
#endif // VMA_SORT
/*
Returns true if two memory blocks occupy overlapping pages.
ResourceA must be in less memory offset than ResourceB.
@ -5073,7 +5026,7 @@ public:
VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src);
VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete;
~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); }
size_t GetCount() const { return m_Count; }
bool IsEmpty() const { return m_Count == 0; }
ItemType* Front() { return m_Front; }
@ -5485,7 +5438,7 @@ public:
// Writes a string value inside "".
// pStr can contain any ANSI characters, including '"', new line etc. - they will be properly escaped.
void WriteString(const char* pStr);
// Begins writing a string value.
// Call BeginString, ContinueString, ContinueString, ..., EndString instead of
// WriteString to conveniently build the string content incrementally, made of
@ -6463,7 +6416,7 @@ void VmaBlockMetadata::DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size
(uint32_t)allocation->GetSuballocationType());
#endif // VMA_STATS_STRING_ENABLED
}
}
#if VMA_STATS_STRING_ENABLED
@ -10941,7 +10894,7 @@ public:
uint32_t GetAlgorithm() const { return m_Algorithm; }
bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; }
float GetPriority() const { return m_Priority; }
void* const GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }
const void* GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }
// To be used only while the m_Mutex is locked. Used during defragmentation.
size_t GetBlockCount() const { return m_Blocks.size(); }
// To be used only while the m_Mutex is locked. Used during defragmentation.
@ -12783,7 +12736,7 @@ void VmaBlockVector::IncrementallySortBlocks()
void VmaBlockVector::SortByFreeSize()
{
VMA_SORT(m_Blocks.begin(), m_Blocks.end(),
[](auto* b1, auto* b2)
[](VmaDeviceMemoryBlock* b1, VmaDeviceMemoryBlock* b2) -> bool
{
return b1->m_pMetadata->GetSumFreeSize() < b2->m_pMetadata->GetSumFreeSize();
});
@ -13029,7 +12982,7 @@ VmaDefragmentationContext_T::VmaDefragmentationContext_T(
}
}
}
switch (m_Algorithm)
{
case 0: // Default algorithm
@ -13155,7 +13108,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
vector = m_pBlockVectors[vectorIndex];
VMA_ASSERT(vector != VMA_NULL);
}
switch (move.operation)
{
case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:
@ -13452,7 +13405,7 @@ bool VmaDefragmentationContext_T::ReallocWithinBlock(VmaBlockVector& vector, Vma
case CounterStatus::Pass:
break;
}
VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();
if (offset != 0 && metadata->GetSumFreeSize() >= moveData.size)
{
@ -13636,7 +13589,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Balanced(VmaBlockVector
prevFreeRegionSize = nextFreeRegionSize;
}
}
// No moves perfomed, update statistics to current vector state
if (startMoveCount == m_Moves.size() && !update)
{
@ -13923,7 +13876,7 @@ void VmaDefragmentationContext_T::UpdateVectorStatistics(VmaBlockVector& vector,
state.avgFreeSize /= freeCount;
}
bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,
bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,
VmaBlockVector& vector, size_t firstFreeBlock,
bool& texturePresent, bool& bufferPresent, bool& otherPresent)
{
@ -15919,6 +15872,7 @@ void VmaAllocator_T::UpdateVulkanBudget()
void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
{
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
hAllocation->IsMappingAllowed() &&
(m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
void* pData = VMA_NULL;
@ -16010,8 +15964,8 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
json.ContinueString_Size(index++);
if (pool->GetName())
{
json.WriteString(" - ");
json.WriteString(pool->GetName());
json.ContinueString(" - ");
json.ContinueString(pool->GetName());
}
json.EndString();
@ -18427,7 +18381,7 @@ for(;;)
VmaAllocationInfo allocInfo;
vmaGetAllocationInfo(allocator, pMoves[i].srcAllocation, &allocInfo);
MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData;
// Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.
VkImageCreateInfo imgCreateInfo = ...
VkImage newImg;
@ -18439,7 +18393,7 @@ for(;;)
// Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.
vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...);
}
// Make sure the copy commands finished executing.
vkWaitForFences(...);
@ -18451,7 +18405,7 @@ for(;;)
}
// Update appropriate descriptors to point to the new places...
res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);
if(res == VK_SUCCESS)
break;
@ -18605,7 +18559,7 @@ To do that, fill VmaAllocationCreateInfo::pUserData field when creating
an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer,
some handle, index, key, ordinal number or any other value that would associate
the allocation with your custom metadata.
It it useful to identify appropriate data structures in your engine given #VmaAllocation,
It is useful to identify appropriate data structures in your engine given #VmaAllocation,
e.g. when doing \ref defragmentation.
\code
@ -18836,14 +18790,14 @@ To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
#include "vk_mem_alloc.h"
\endcode
It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
It makes memory of new allocations initialized to bit pattern `0xDCDCDCDC`.
Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
Memory is automatically mapped and unmapped if necessary.
If you find these values while debugging your program, good chances are that you incorrectly
read Vulkan memory that is allocated but not initialized, or already freed, respectively.
Memory initialization works only with memory types that are `HOST_VISIBLE`.
Memory initialization works only with memory types that are `HOST_VISIBLE` and with allocations that can be mapped.
It works also with dedicated allocations.
\section debugging_memory_usage_margins Margins
@ -19116,13 +19070,13 @@ so you need to create another "staging" allocation and perform explicit transfer
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufCreateInfo.size = 65536;
bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
VkBuffer buf;
VmaAllocation alloc;
VmaAllocationInfo allocInfo;