Designed new API for linear allocation algorithm: added flags VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT, VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT. Abstracted VmaBlockMetadata into base class VmaBlockMetadata and derived class VmaBlockMetadata_Generic. Few minor fixes.

This commit is contained in:
Adam Sawicki 2018-06-19 14:33:32 +02:00
parent e44c62684d
commit 00f620f398

View File

@ -485,7 +485,7 @@ To use custom memory pools:
-# Fill VmaPoolCreateInfo structure. -# Fill VmaPoolCreateInfo structure.
-# Call vmaCreatePool() to obtain #VmaPool handle. -# Call vmaCreatePool() to obtain #VmaPool handle.
-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle. -# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
You don't need to specify any other parameters of this structure, like usage. You don't need to specify any other parameters of this structure, like `usage`.
Example: Example:
@ -822,7 +822,7 @@ you can use debug features of this library to verify this.
\section debugging_memory_usage_initialization Memory initialization \section debugging_memory_usage_initialization Memory initialization
If you experience a bug with incorrect data in your program and you suspect uninitialized memory to be used, If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
you can enable automatic memory initialization to verify this. you can enable automatic memory initialization to verify this.
To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1. To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
@ -841,7 +841,7 @@ read Vulkan memory that is allocated but not initialized, or already freed, resp
Memory initialization works only with memory types that are `HOST_VISIBLE`. Memory initialization works only with memory types that are `HOST_VISIBLE`.
It works also with dedicated allocations. It works also with dedicated allocations.
It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag, It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
as these they cannot be mapped. as they cannot be mapped.
\section debugging_memory_usage_margins Margins \section debugging_memory_usage_margins Margins
@ -970,7 +970,7 @@ You can map it and write to it directly on CPU, as well as read from it on GPU.
This is a more complex situation. Different solutions are possible, This is a more complex situation. Different solutions are possible,
and the best one depends on specific GPU type, but you can use this simple approach for the start. and the best one depends on specific GPU type, but you can use this simple approach for the start.
Prefer to write to such resource sequentially (e.g. using `memcpy`). Prefer to write to such resource sequentially (e.g. using `memcpy`).
Don't perform random access or any reads from it, as it may be very slow. Don't perform random access or any reads from it on CPU, as it may be very slow.
\subsection usage_patterns_readback Readback \subsection usage_patterns_readback Readback
@ -990,7 +990,7 @@ You can support integrated graphics (like Intel HD Graphics, AMD APU) better
by detecting it in Vulkan. by detecting it in Vulkan.
To do it, call `vkGetPhysicalDeviceProperties()`, inspect To do it, call `vkGetPhysicalDeviceProperties()`, inspect
`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`. `VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`.
When you find it, you can assume that memory is unified and all memory types are equally fast When you find it, you can assume that memory is unified and all memory types are comparably fast
to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
You can then sum up sizes of all available memory heaps and treat them as useful for You can then sum up sizes of all available memory heaps and treat them as useful for
@ -1014,7 +1014,7 @@ It is best to measure it and then make the decision.
Some general recommendations: Some general recommendations:
- On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead - On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead
related to using a second copy. related to using a second copy and making transfer.
- For small resources (e.g. constant buffers) use (2). - For small resources (e.g. constant buffers) use (2).
Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable. Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable.
Even if the resource ends up in system memory, its data may be cached on GPU after first Even if the resource ends up in system memory, its data may be cached on GPU after first
@ -1585,6 +1585,9 @@ typedef enum VmaAllocationCreateFlagBits {
freed together with the allocation. It is also used in vmaBuildStatsString(). freed together with the allocation. It is also used in vmaBuildStatsString().
*/ */
VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
/** TODO
*/
VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VmaAllocationCreateFlagBits; } VmaAllocationCreateFlagBits;
@ -1695,7 +1698,7 @@ VkResult vmaFindMemoryTypeIndexForImageInfo(
typedef enum VmaPoolCreateFlagBits { typedef enum VmaPoolCreateFlagBits {
/** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
This is na optional optimization flag. This is an optional optimization flag.
If you always allocate using vmaCreateBuffer(), vmaCreateImage(), If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
@ -1712,6 +1715,12 @@ typedef enum VmaPoolCreateFlagBits {
*/ */
VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
/** \brief TODO
TODO
*/
VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VmaPoolCreateFlagBits; } VmaPoolCreateFlagBits;
typedef VkFlags VmaPoolCreateFlags; typedef VkFlags VmaPoolCreateFlags;
@ -4240,32 +4249,83 @@ in a single VkDeviceMemory block.
*/ */
class VmaBlockMetadata class VmaBlockMetadata
{ {
VMA_CLASS_NO_COPY(VmaBlockMetadata)
public: public:
VmaBlockMetadata(VmaAllocator hAllocator); virtual ~VmaBlockMetadata() { }
~VmaBlockMetadata(); virtual void Init(VkDeviceSize size) = 0;
void Init(VkDeviceSize size);
// Validates all data structures inside this object. If not valid, returns false. // Validates all data structures inside this object. If not valid, returns false.
bool Validate() const; virtual bool Validate() const = 0;
VkDeviceSize GetSize() const { return m_Size; } virtual VkDeviceSize GetSize() const = 0;
size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; } virtual size_t GetAllocationCount() const = 0;
VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; } virtual VkDeviceSize GetSumFreeSize() const = 0;
VkDeviceSize GetUnusedRangeSizeMax() const; virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0;
// Returns true if this block is empty - contains only single free suballocation. // Returns true if this block is empty - contains only single free suballocation.
bool IsEmpty() const; virtual bool IsEmpty() const = 0;
void CalcAllocationStatInfo(VmaStatInfo& outInfo) const; virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
void AddPoolStats(VmaPoolStats& inoutStats) const; virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
#if VMA_STATS_STRING_ENABLED #if VMA_STATS_STRING_ENABLED
void PrintDetailedMap(class VmaJsonWriter& json) const; virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
#endif #endif
// Tries to find a place for suballocation with given parameters inside this block. // Tries to find a place for suballocation with given parameters inside this block.
// If succeeded, fills pAllocationRequest and returns true. // If succeeded, fills pAllocationRequest and returns true.
// If failed, returns false. // If failed, returns false.
bool CreateAllocationRequest( virtual bool CreateAllocationRequest(
uint32_t currentFrameIndex,
uint32_t frameInUseCount,
VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
VmaSuballocationType allocType,
bool canMakeOtherLost,
VmaAllocationRequest* pAllocationRequest) = 0;
virtual bool MakeRequestedAllocationsLost(
uint32_t currentFrameIndex,
uint32_t frameInUseCount,
VmaAllocationRequest* pAllocationRequest) = 0;
virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;
virtual VkResult CheckCorruption(const void* pBlockData) = 0;
// Makes actual allocation based on request. Request must already be checked and valid.
virtual void Alloc(
const VmaAllocationRequest& request,
VmaSuballocationType type,
VkDeviceSize allocSize,
VmaAllocation hAllocation) = 0;
// Frees suballocation assigned to given memory region.
virtual void Free(const VmaAllocation allocation) = 0;
virtual void FreeAtOffset(VkDeviceSize offset) = 0;
};
class VmaBlockMetadata_Generic : public VmaBlockMetadata
{
VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
public:
VmaBlockMetadata_Generic(VmaAllocator hAllocator);
virtual ~VmaBlockMetadata_Generic();
virtual void Init(VkDeviceSize size);
virtual bool Validate() const;
virtual VkDeviceSize GetSize() const { return m_Size; }
virtual size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; }
virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
virtual VkDeviceSize GetUnusedRangeSizeMax() const;
virtual bool IsEmpty() const;
virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
#if VMA_STATS_STRING_ENABLED
virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
#endif
virtual bool CreateAllocationRequest(
uint32_t currentFrameIndex, uint32_t currentFrameIndex,
uint32_t frameInUseCount, uint32_t frameInUseCount,
VkDeviceSize bufferImageGranularity, VkDeviceSize bufferImageGranularity,
@ -4275,25 +4335,23 @@ public:
bool canMakeOtherLost, bool canMakeOtherLost,
VmaAllocationRequest* pAllocationRequest); VmaAllocationRequest* pAllocationRequest);
bool MakeRequestedAllocationsLost( virtual bool MakeRequestedAllocationsLost(
uint32_t currentFrameIndex, uint32_t currentFrameIndex,
uint32_t frameInUseCount, uint32_t frameInUseCount,
VmaAllocationRequest* pAllocationRequest); VmaAllocationRequest* pAllocationRequest);
uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount); virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
VkResult CheckCorruption(const void* pBlockData); virtual VkResult CheckCorruption(const void* pBlockData);
// Makes actual allocation based on request. Request must already be checked and valid. virtual void Alloc(
void Alloc(
const VmaAllocationRequest& request, const VmaAllocationRequest& request,
VmaSuballocationType type, VmaSuballocationType type,
VkDeviceSize allocSize, VkDeviceSize allocSize,
VmaAllocation hAllocation); VmaAllocation hAllocation);
// Frees suballocation assigned to given memory region. virtual void Free(const VmaAllocation allocation);
void Free(const VmaAllocation allocation); virtual void FreeAtOffset(VkDeviceSize offset);
void FreeAtOffset(VkDeviceSize offset);
private: private:
VkDeviceSize m_Size; VkDeviceSize m_Size;
@ -4345,7 +4403,7 @@ class VmaDeviceMemoryBlock
{ {
VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock) VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
public: public:
VmaBlockMetadata m_Metadata; VmaBlockMetadata* m_pMetadata;
VmaDeviceMemoryBlock(VmaAllocator hAllocator); VmaDeviceMemoryBlock(VmaAllocator hAllocator);
@ -4357,6 +4415,7 @@ public:
// Always call after construction. // Always call after construction.
void Init( void Init(
VmaAllocator hAllocator,
uint32_t newMemoryTypeIndex, uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory, VkDeviceMemory newMemory,
VkDeviceSize newSize, VkDeviceSize newSize,
@ -4430,7 +4489,8 @@ public:
size_t maxBlockCount, size_t maxBlockCount,
VkDeviceSize bufferImageGranularity, VkDeviceSize bufferImageGranularity,
uint32_t frameInUseCount, uint32_t frameInUseCount,
bool isCustomPool); bool isCustomPool,
bool linearAlgorithm);
~VmaBlockVector(); ~VmaBlockVector();
VkResult CreateMinBlocks(); VkResult CreateMinBlocks();
@ -4439,6 +4499,7 @@ public:
VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; } VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; } uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; }
bool UsesLinearAlgorithm() const { return m_LinearAlgorithm; }
void GetPoolStats(VmaPoolStats* pStats); void GetPoolStats(VmaPoolStats* pStats);
@ -4491,13 +4552,14 @@ private:
const VkDeviceSize m_BufferImageGranularity; const VkDeviceSize m_BufferImageGranularity;
const uint32_t m_FrameInUseCount; const uint32_t m_FrameInUseCount;
const bool m_IsCustomPool; const bool m_IsCustomPool;
const bool m_LinearAlgorithm;
bool m_HasEmptyBlock;
VMA_MUTEX m_Mutex; VMA_MUTEX m_Mutex;
// Incrementally sorted by sumFreeSize, ascending. // Incrementally sorted by sumFreeSize, ascending.
VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks; VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks;
/* There can be at most one allocation that is completely empty - a /* There can be at most one allocation that is completely empty - a
hysteresis to avoid pessimistic case of alternating creation and destruction hysteresis to avoid pessimistic case of alternating creation and destruction
of a VkDeviceMemory. */ of a VkDeviceMemory. */
bool m_HasEmptyBlock;
VmaDefragmentator* m_pDefragmentator; VmaDefragmentator* m_pDefragmentator;
uint32_t m_NextBlockId; uint32_t m_NextBlockId;
@ -4585,7 +4647,7 @@ private:
void CalcHasNonMovableAllocations() void CalcHasNonMovableAllocations()
{ {
const size_t blockAllocCount = m_pBlock->m_Metadata.GetAllocationCount(); const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount();
const size_t defragmentAllocCount = m_Allocations.size(); const size_t defragmentAllocCount = m_Allocations.size();
m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount; m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;
} }
@ -4629,7 +4691,7 @@ private:
{ {
return false; return false;
} }
if(pLhsBlockInfo->m_pBlock->m_Metadata.GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_Metadata.GetSumFreeSize()) if(pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize())
{ {
return true; return true;
} }
@ -5628,9 +5690,9 @@ struct VmaSuballocationItemSizeLess
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class VmaBlockMetadata // class VmaBlockMetadata_Generic
VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) : VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) :
m_Size(0), m_Size(0),
m_FreeCount(0), m_FreeCount(0),
m_SumFreeSize(0), m_SumFreeSize(0),
@ -5639,11 +5701,11 @@ VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) :
{ {
} }
VmaBlockMetadata::~VmaBlockMetadata() VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()
{ {
} }
void VmaBlockMetadata::Init(VkDeviceSize size) void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
{ {
m_Size = size; m_Size = size;
m_FreeCount = 1; m_FreeCount = 1;
@ -5661,7 +5723,7 @@ void VmaBlockMetadata::Init(VkDeviceSize size)
m_FreeSuballocationsBySize.push_back(suballocItem); m_FreeSuballocationsBySize.push_back(suballocItem);
} }
bool VmaBlockMetadata::Validate() const bool VmaBlockMetadata_Generic::Validate() const
{ {
if(m_Suballocations.empty()) if(m_Suballocations.empty())
{ {
@ -5779,7 +5841,7 @@ bool VmaBlockMetadata::Validate() const
return true; return true;
} }
VkDeviceSize VmaBlockMetadata::GetUnusedRangeSizeMax() const VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax() const
{ {
if(!m_FreeSuballocationsBySize.empty()) if(!m_FreeSuballocationsBySize.empty())
{ {
@ -5791,12 +5853,12 @@ VkDeviceSize VmaBlockMetadata::GetUnusedRangeSizeMax() const
} }
} }
bool VmaBlockMetadata::IsEmpty() const bool VmaBlockMetadata_Generic::IsEmpty() const
{ {
return (m_Suballocations.size() == 1) && (m_FreeCount == 1); return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
} }
void VmaBlockMetadata::CalcAllocationStatInfo(VmaStatInfo& outInfo) const void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
{ {
outInfo.blockCount = 1; outInfo.blockCount = 1;
@ -5830,7 +5892,7 @@ void VmaBlockMetadata::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
} }
} }
void VmaBlockMetadata::AddPoolStats(VmaPoolStats& inoutStats) const void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const
{ {
const uint32_t rangeCount = (uint32_t)m_Suballocations.size(); const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
@ -5843,7 +5905,7 @@ void VmaBlockMetadata::AddPoolStats(VmaPoolStats& inoutStats) const
#if VMA_STATS_STRING_ENABLED #if VMA_STATS_STRING_ENABLED
void VmaBlockMetadata::PrintDetailedMap(class VmaJsonWriter& json) const void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const
{ {
json.BeginObject(); json.BeginObject();
@ -5903,7 +5965,7 @@ How many suitable free suballocations to analyze before choosing best one.
*/ */
//static const uint32_t MAX_SUITABLE_SUBALLOCATIONS_TO_CHECK = 8; //static const uint32_t MAX_SUITABLE_SUBALLOCATIONS_TO_CHECK = 8;
bool VmaBlockMetadata::CreateAllocationRequest( bool VmaBlockMetadata_Generic::CreateAllocationRequest(
uint32_t currentFrameIndex, uint32_t currentFrameIndex,
uint32_t frameInUseCount, uint32_t frameInUseCount,
VkDeviceSize bufferImageGranularity, VkDeviceSize bufferImageGranularity,
@ -6032,7 +6094,7 @@ bool VmaBlockMetadata::CreateAllocationRequest(
return false; return false;
} }
bool VmaBlockMetadata::MakeRequestedAllocationsLost( bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(
uint32_t currentFrameIndex, uint32_t currentFrameIndex,
uint32_t frameInUseCount, uint32_t frameInUseCount,
VmaAllocationRequest* pAllocationRequest) VmaAllocationRequest* pAllocationRequest)
@ -6064,7 +6126,7 @@ bool VmaBlockMetadata::MakeRequestedAllocationsLost(
return true; return true;
} }
uint32_t VmaBlockMetadata::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
{ {
uint32_t lostAllocationCount = 0; uint32_t lostAllocationCount = 0;
for(VmaSuballocationList::iterator it = m_Suballocations.begin(); for(VmaSuballocationList::iterator it = m_Suballocations.begin();
@ -6082,7 +6144,7 @@ uint32_t VmaBlockMetadata::MakeAllocationsLost(uint32_t currentFrameIndex, uint3
return lostAllocationCount; return lostAllocationCount;
} }
VkResult VmaBlockMetadata::CheckCorruption(const void* pBlockData) VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
{ {
for(VmaSuballocationList::iterator it = m_Suballocations.begin(); for(VmaSuballocationList::iterator it = m_Suballocations.begin();
it != m_Suballocations.end(); it != m_Suballocations.end();
@ -6106,7 +6168,7 @@ VkResult VmaBlockMetadata::CheckCorruption(const void* pBlockData)
return VK_SUCCESS; return VK_SUCCESS;
} }
void VmaBlockMetadata::Alloc( void VmaBlockMetadata_Generic::Alloc(
const VmaAllocationRequest& request, const VmaAllocationRequest& request,
VmaSuballocationType type, VmaSuballocationType type,
VkDeviceSize allocSize, VkDeviceSize allocSize,
@ -6170,7 +6232,7 @@ void VmaBlockMetadata::Alloc(
m_SumFreeSize -= allocSize; m_SumFreeSize -= allocSize;
} }
void VmaBlockMetadata::Free(const VmaAllocation allocation) void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation)
{ {
for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
suballocItem != m_Suballocations.end(); suballocItem != m_Suballocations.end();
@ -6187,7 +6249,7 @@ void VmaBlockMetadata::Free(const VmaAllocation allocation)
VMA_ASSERT(0 && "Not found!"); VMA_ASSERT(0 && "Not found!");
} }
void VmaBlockMetadata::FreeAtOffset(VkDeviceSize offset) void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)
{ {
for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
suballocItem != m_Suballocations.end(); suballocItem != m_Suballocations.end();
@ -6203,7 +6265,7 @@ void VmaBlockMetadata::FreeAtOffset(VkDeviceSize offset)
VMA_ASSERT(0 && "Not found!"); VMA_ASSERT(0 && "Not found!");
} }
bool VmaBlockMetadata::ValidateFreeSuballocationList() const bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
{ {
VkDeviceSize lastSize = 0; VkDeviceSize lastSize = 0;
for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i) for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
@ -6231,7 +6293,7 @@ bool VmaBlockMetadata::ValidateFreeSuballocationList() const
return true; return true;
} }
bool VmaBlockMetadata::CheckAllocation( bool VmaBlockMetadata_Generic::CheckAllocation(
uint32_t currentFrameIndex, uint32_t currentFrameIndex,
uint32_t frameInUseCount, uint32_t frameInUseCount,
VkDeviceSize bufferImageGranularity, VkDeviceSize bufferImageGranularity,
@ -6505,7 +6567,7 @@ bool VmaBlockMetadata::CheckAllocation(
return true; return true;
} }
void VmaBlockMetadata::MergeFreeWithNext(VmaSuballocationList::iterator item) void VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)
{ {
VMA_ASSERT(item != m_Suballocations.end()); VMA_ASSERT(item != m_Suballocations.end());
VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
@ -6520,7 +6582,7 @@ void VmaBlockMetadata::MergeFreeWithNext(VmaSuballocationList::iterator item)
m_Suballocations.erase(nextItem); m_Suballocations.erase(nextItem);
} }
VmaSuballocationList::iterator VmaBlockMetadata::FreeSuballocation(VmaSuballocationList::iterator suballocItem) VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)
{ {
// Change this suballocation to be marked as free. // Change this suballocation to be marked as free.
VmaSuballocation& suballoc = *suballocItem; VmaSuballocation& suballoc = *suballocItem;
@ -6572,7 +6634,7 @@ VmaSuballocationList::iterator VmaBlockMetadata::FreeSuballocation(VmaSuballocat
} }
} }
void VmaBlockMetadata::RegisterFreeSuballocation(VmaSuballocationList::iterator item) void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)
{ {
VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
VMA_ASSERT(item->size > 0); VMA_ASSERT(item->size > 0);
@ -6597,7 +6659,7 @@ void VmaBlockMetadata::RegisterFreeSuballocation(VmaSuballocationList::iterator
} }
void VmaBlockMetadata::UnregisterFreeSuballocation(VmaSuballocationList::iterator item) void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)
{ {
VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
VMA_ASSERT(item->size > 0); VMA_ASSERT(item->size > 0);
@ -6634,7 +6696,7 @@ void VmaBlockMetadata::UnregisterFreeSuballocation(VmaSuballocationList::iterato
// class VmaDeviceMemoryBlock // class VmaDeviceMemoryBlock
VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) : VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
m_Metadata(hAllocator), m_pMetadata(VMA_NULL),
m_MemoryTypeIndex(UINT32_MAX), m_MemoryTypeIndex(UINT32_MAX),
m_Id(0), m_Id(0),
m_hMemory(VK_NULL_HANDLE), m_hMemory(VK_NULL_HANDLE),
@ -6644,6 +6706,7 @@ VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
} }
void VmaDeviceMemoryBlock::Init( void VmaDeviceMemoryBlock::Init(
VmaAllocator hAllocator,
uint32_t newMemoryTypeIndex, uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory, VkDeviceMemory newMemory,
VkDeviceSize newSize, VkDeviceSize newSize,
@ -6655,29 +6718,33 @@ void VmaDeviceMemoryBlock::Init(
m_Id = id; m_Id = id;
m_hMemory = newMemory; m_hMemory = newMemory;
m_Metadata.Init(newSize); m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);
m_pMetadata->Init(newSize);
} }
void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator) void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
{ {
// This is the most important assert in the entire library. // This is the most important assert in the entire library.
// Hitting it means you have some memory leak - unreleased VmaAllocation objects. // Hitting it means you have some memory leak - unreleased VmaAllocation objects.
VMA_ASSERT(m_Metadata.IsEmpty() && "Some allocations were not freed before destruction of this memory block!"); VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");
VMA_ASSERT(m_hMemory != VK_NULL_HANDLE); VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);
allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_Metadata.GetSize(), m_hMemory); allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
m_hMemory = VK_NULL_HANDLE; m_hMemory = VK_NULL_HANDLE;
vma_delete(allocator, m_pMetadata);
m_pMetadata = VMA_NULL;
} }
bool VmaDeviceMemoryBlock::Validate() const bool VmaDeviceMemoryBlock::Validate() const
{ {
if((m_hMemory == VK_NULL_HANDLE) || if((m_hMemory == VK_NULL_HANDLE) ||
(m_Metadata.GetSize() == 0)) (m_pMetadata->GetSize() == 0))
{ {
return false; return false;
} }
return m_Metadata.Validate(); return m_pMetadata->Validate();
} }
VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator) VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
@ -6689,7 +6756,7 @@ VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
return res; return res;
} }
res = m_Metadata.CheckCorruption(pData); res = m_pMetadata->CheckCorruption(pData);
Unmap(hAllocator, 1); Unmap(hAllocator, 1);
@ -6876,7 +6943,8 @@ VmaPool_T::VmaPool_T(
createInfo.maxBlockCount, createInfo.maxBlockCount,
(createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
createInfo.frameInUseCount, createInfo.frameInUseCount,
true), // isCustomPool true, // isCustomPool
(createInfo.flags & VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) != 0), // linearAlgorithm
m_Id(0) m_Id(0)
{ {
} }
@ -6897,7 +6965,8 @@ VmaBlockVector::VmaBlockVector(
size_t maxBlockCount, size_t maxBlockCount,
VkDeviceSize bufferImageGranularity, VkDeviceSize bufferImageGranularity,
uint32_t frameInUseCount, uint32_t frameInUseCount,
bool isCustomPool) : bool isCustomPool,
bool linearAlgorithm) :
m_hAllocator(hAllocator), m_hAllocator(hAllocator),
m_MemoryTypeIndex(memoryTypeIndex), m_MemoryTypeIndex(memoryTypeIndex),
m_PreferredBlockSize(preferredBlockSize), m_PreferredBlockSize(preferredBlockSize),
@ -6906,6 +6975,7 @@ VmaBlockVector::VmaBlockVector(
m_BufferImageGranularity(bufferImageGranularity), m_BufferImageGranularity(bufferImageGranularity),
m_FrameInUseCount(frameInUseCount), m_FrameInUseCount(frameInUseCount),
m_IsCustomPool(isCustomPool), m_IsCustomPool(isCustomPool),
m_LinearAlgorithm(linearAlgorithm),
m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())), m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
m_HasEmptyBlock(false), m_HasEmptyBlock(false),
m_pDefragmentator(VMA_NULL), m_pDefragmentator(VMA_NULL),
@ -6952,7 +7022,7 @@ void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats)
const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
VMA_ASSERT(pBlock); VMA_ASSERT(pBlock);
VMA_HEAVY_ASSERT(pBlock->Validate()); VMA_HEAVY_ASSERT(pBlock->Validate());
pBlock->m_Metadata.AddPoolStats(*pStats); pBlock->m_pMetadata->AddPoolStats(*pStats);
} }
} }
@ -6993,7 +7063,7 @@ VkResult VmaBlockVector::Allocate(
VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
VMA_ASSERT(pCurrBlock); VMA_ASSERT(pCurrBlock);
VmaAllocationRequest currRequest = {}; VmaAllocationRequest currRequest = {};
if(pCurrBlock->m_Metadata.CreateAllocationRequest( if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
currentFrameIndex, currentFrameIndex,
m_FrameInUseCount, m_FrameInUseCount,
m_BufferImageGranularity, m_BufferImageGranularity,
@ -7016,13 +7086,13 @@ VkResult VmaBlockVector::Allocate(
} }
// We no longer have an empty Allocation. // We no longer have an empty Allocation.
if(pCurrBlock->m_Metadata.IsEmpty()) if(pCurrBlock->m_pMetadata->IsEmpty())
{ {
m_HasEmptyBlock = false; m_HasEmptyBlock = false;
} }
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pCurrBlock->m_Metadata.Alloc(currRequest, suballocType, size, *pAllocation); pCurrBlock->m_pMetadata->Alloc(currRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation( (*pAllocation)->InitBlockAllocation(
hCurrentPool, hCurrentPool,
pCurrBlock, pCurrBlock,
@ -7105,7 +7175,7 @@ VkResult VmaBlockVector::Allocate(
if(res == VK_SUCCESS) if(res == VK_SUCCESS)
{ {
VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex]; VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
VMA_ASSERT(pBlock->m_Metadata.GetSize() >= size); VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
if(mapped) if(mapped)
{ {
@ -7118,7 +7188,7 @@ VkResult VmaBlockVector::Allocate(
// Allocate from pBlock. Because it is empty, dstAllocRequest can be trivially filled. // Allocate from pBlock. Because it is empty, dstAllocRequest can be trivially filled.
VmaAllocationRequest allocRequest; VmaAllocationRequest allocRequest;
if(pBlock->m_Metadata.CreateAllocationRequest( if(pBlock->m_pMetadata->CreateAllocationRequest(
currentFrameIndex, currentFrameIndex,
m_FrameInUseCount, m_FrameInUseCount,
m_BufferImageGranularity, m_BufferImageGranularity,
@ -7129,7 +7199,7 @@ VkResult VmaBlockVector::Allocate(
&allocRequest)) &allocRequest))
{ {
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pBlock->m_Metadata.Alloc(allocRequest, suballocType, size, *pAllocation); pBlock->m_pMetadata->Alloc(allocRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation( (*pAllocation)->InitBlockAllocation(
hCurrentPool, hCurrentPool,
pBlock, pBlock,
@ -7180,7 +7250,7 @@ VkResult VmaBlockVector::Allocate(
VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
VMA_ASSERT(pCurrBlock); VMA_ASSERT(pCurrBlock);
VmaAllocationRequest currRequest = {}; VmaAllocationRequest currRequest = {};
if(pCurrBlock->m_Metadata.CreateAllocationRequest( if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
currentFrameIndex, currentFrameIndex,
m_FrameInUseCount, m_FrameInUseCount,
m_BufferImageGranularity, m_BufferImageGranularity,
@ -7217,19 +7287,19 @@ VkResult VmaBlockVector::Allocate(
} }
} }
if(pBestRequestBlock->m_Metadata.MakeRequestedAllocationsLost( if(pBestRequestBlock->m_pMetadata->MakeRequestedAllocationsLost(
currentFrameIndex, currentFrameIndex,
m_FrameInUseCount, m_FrameInUseCount,
&bestRequest)) &bestRequest))
{ {
// We no longer have an empty Allocation. // We no longer have an empty Allocation.
if(pBestRequestBlock->m_Metadata.IsEmpty()) if(pBestRequestBlock->m_pMetadata->IsEmpty())
{ {
m_HasEmptyBlock = false; m_HasEmptyBlock = false;
} }
// Allocate from this pBlock. // Allocate from this pBlock.
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pBestRequestBlock->m_Metadata.Alloc(bestRequest, suballocType, size, *pAllocation); pBestRequestBlock->m_pMetadata->Alloc(bestRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation( (*pAllocation)->InitBlockAllocation(
hCurrentPool, hCurrentPool,
pBestRequestBlock, pBestRequestBlock,
@ -7295,13 +7365,13 @@ void VmaBlockVector::Free(
pBlock->Unmap(m_hAllocator, 1); pBlock->Unmap(m_hAllocator, 1);
} }
pBlock->m_Metadata.Free(hAllocation); pBlock->m_pMetadata->Free(hAllocation);
VMA_HEAVY_ASSERT(pBlock->Validate()); VMA_HEAVY_ASSERT(pBlock->Validate());
VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", memTypeIndex); VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", memTypeIndex);
// pBlock became empty after this deallocation. // pBlock became empty after this deallocation.
if(pBlock->m_Metadata.IsEmpty()) if(pBlock->m_pMetadata->IsEmpty())
{ {
// Already has empty Allocation. We don't want to have two, so delete this one. // Already has empty Allocation. We don't want to have two, so delete this one.
if(m_HasEmptyBlock && m_Blocks.size() > m_MinBlockCount) if(m_HasEmptyBlock && m_Blocks.size() > m_MinBlockCount)
@ -7320,7 +7390,7 @@ void VmaBlockVector::Free(
else if(m_HasEmptyBlock) else if(m_HasEmptyBlock)
{ {
VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back(); VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
if(pLastBlock->m_Metadata.IsEmpty() && m_Blocks.size() > m_MinBlockCount) if(pLastBlock->m_pMetadata->IsEmpty() && m_Blocks.size() > m_MinBlockCount)
{ {
pBlockToDelete = pLastBlock; pBlockToDelete = pLastBlock;
m_Blocks.pop_back(); m_Blocks.pop_back();
@ -7346,7 +7416,7 @@ VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
VkDeviceSize result = 0; VkDeviceSize result = 0;
for(size_t i = m_Blocks.size(); i--; ) for(size_t i = m_Blocks.size(); i--; )
{ {
result = VMA_MAX(result, m_Blocks[i]->m_Metadata.GetSize()); result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());
if(result >= m_PreferredBlockSize) if(result >= m_PreferredBlockSize)
{ {
break; break;
@ -7373,7 +7443,7 @@ void VmaBlockVector::IncrementallySortBlocks()
// Bubble sort only until first swap. // Bubble sort only until first swap.
for(size_t i = 1; i < m_Blocks.size(); ++i) for(size_t i = 1; i < m_Blocks.size(); ++i)
{ {
if(m_Blocks[i - 1]->m_Metadata.GetSumFreeSize() > m_Blocks[i]->m_Metadata.GetSumFreeSize()) if(m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
{ {
VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]); VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);
return; return;
@ -7398,6 +7468,7 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
// Create new Allocation for it. // Create new Allocation for it.
VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator); VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
pBlock->Init( pBlock->Init(
m_hAllocator,
m_MemoryTypeIndex, m_MemoryTypeIndex,
mem, mem,
allocInfo.allocationSize, allocInfo.allocationSize,
@ -7464,7 +7535,7 @@ void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
json.ContinueString(m_Blocks[i]->GetId()); json.ContinueString(m_Blocks[i]->GetId());
json.EndString(); json.EndString();
m_Blocks[i]->m_Metadata.PrintDetailedMap(json); m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
} }
json.EndObject(); json.EndObject();
@ -7521,14 +7592,14 @@ VkResult VmaBlockVector::Defragment(
for(size_t blockIndex = m_Blocks.size(); blockIndex--; ) for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
{ {
VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
if(pBlock->m_Metadata.IsEmpty()) if(pBlock->m_pMetadata->IsEmpty())
{ {
if(m_Blocks.size() > m_MinBlockCount) if(m_Blocks.size() > m_MinBlockCount)
{ {
if(pDefragmentationStats != VMA_NULL) if(pDefragmentationStats != VMA_NULL)
{ {
++pDefragmentationStats->deviceMemoryBlocksFreed; ++pDefragmentationStats->deviceMemoryBlocksFreed;
pDefragmentationStats->bytesFreed += pBlock->m_Metadata.GetSize(); pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize();
} }
VmaVectorRemove(m_Blocks, blockIndex); VmaVectorRemove(m_Blocks, blockIndex);
@ -7564,7 +7635,7 @@ void VmaBlockVector::MakePoolAllocationsLost(
{ {
VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
VMA_ASSERT(pBlock); VMA_ASSERT(pBlock);
lostAllocationCount += pBlock->m_Metadata.MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount); lostAllocationCount += pBlock->m_pMetadata->MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);
} }
if(pLostAllocationCount != VMA_NULL) if(pLostAllocationCount != VMA_NULL)
{ {
@ -7606,7 +7677,7 @@ void VmaBlockVector::AddStats(VmaStats* pStats)
VMA_ASSERT(pBlock); VMA_ASSERT(pBlock);
VMA_HEAVY_ASSERT(pBlock->Validate()); VMA_HEAVY_ASSERT(pBlock->Validate());
VmaStatInfo allocationStatInfo; VmaStatInfo allocationStatInfo;
pBlock->m_Metadata.CalcAllocationStatInfo(allocationStatInfo); pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo);
VmaAddStatInfo(pStats->total, allocationStatInfo); VmaAddStatInfo(pStats->total, allocationStatInfo);
VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo); VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo); VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
@ -7726,7 +7797,7 @@ VkResult VmaDefragmentator::DefragmentRound(
{ {
BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex]; BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];
VmaAllocationRequest dstAllocRequest; VmaAllocationRequest dstAllocRequest;
if(pDstBlockInfo->m_pBlock->m_Metadata.CreateAllocationRequest( if(pDstBlockInfo->m_pBlock->m_pMetadata->CreateAllocationRequest(
m_CurrentFrameIndex, m_CurrentFrameIndex,
m_pBlockVector->GetFrameInUseCount(), m_pBlockVector->GetFrameInUseCount(),
m_pBlockVector->GetBufferImageGranularity(), m_pBlockVector->GetBufferImageGranularity(),
@ -7773,8 +7844,8 @@ VkResult VmaDefragmentator::DefragmentRound(
VmaWriteMagicValue(pDstMappedData, dstAllocRequest.offset + size); VmaWriteMagicValue(pDstMappedData, dstAllocRequest.offset + size);
} }
pDstBlockInfo->m_pBlock->m_Metadata.Alloc(dstAllocRequest, suballocType, size, allocInfo.m_hAllocation); pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(dstAllocRequest, suballocType, size, allocInfo.m_hAllocation);
pSrcBlockInfo->m_pBlock->m_Metadata.FreeAtOffset(srcOffset); pSrcBlockInfo->m_pBlock->m_pMetadata->FreeAtOffset(srcOffset);
allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset); allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset);
@ -7985,7 +8056,8 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
SIZE_MAX, SIZE_MAX,
GetBufferImageGranularity(), GetBufferImageGranularity(),
pCreateInfo->frameInUseCount, pCreateInfo->frameInUseCount,
false); // isCustomPool false, // isCustomPool
false); // linearAlgorithm
// No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here, // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
// becase minBlockCount is 0. // becase minBlockCount is 0.
m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks())); m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));
@ -9141,7 +9213,7 @@ void VmaAllocator_T::FlushOrInvalidateAllocation(
// 2. Adjust to whole block. // 2. Adjust to whole block.
const VkDeviceSize allocationOffset = hAllocation->GetOffset(); const VkDeviceSize allocationOffset = hAllocation->GetOffset();
VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0); VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);
const VkDeviceSize blockSize = hAllocation->GetBlock()->m_Metadata.GetSize(); const VkDeviceSize blockSize = hAllocation->GetBlock()->m_pMetadata->GetSize();
memRange.offset += allocationOffset; memRange.offset += allocationOffset;
memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset); memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);