Refactoring: Added function VmaAddStatInfoAllocation, VmaAddStatInfoUnusedRange
Submitting improved tests.
diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h
index 5d1e378..2134a8c 100644
--- a/include/vk_mem_alloc.h
+++ b/include/vk_mem_alloc.h
@@ -5091,6 +5091,7 @@
virtual bool IsEmpty() const = 0;
virtual void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) = 0;
+ // Must set blockCount to 1.
virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
// Shouldn't modify blockCount.
virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
@@ -5603,7 +5604,7 @@
bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
- void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const;
+ void CalcAllocationStatInfoNode(VmaStatInfo& inoutInfo, const Node* node, VkDeviceSize levelNodeSize) const;
// Adds node to the front of FreeList at given level.
// node->type must be FREE.
// node->free.prev, next can be undefined.
@@ -6869,7 +6870,7 @@
class VmaStringBuilder;
-static void InitStatInfo(VmaStatInfo& outInfo)
+static void VmaInitStatInfo(VmaStatInfo& outInfo)
{
memset(&outInfo, 0, sizeof(outInfo));
outInfo.allocationSizeMin = UINT64_MAX;
@@ -6890,6 +6891,34 @@
inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax);
}
+static void VmaAddStatInfoAllocation(VmaStatInfo& inoutInfo, VkDeviceSize size)
+{
+ ++inoutInfo.allocationCount;
+ inoutInfo.usedBytes += size;
+ if(size < inoutInfo.allocationSizeMin)
+ {
+ inoutInfo.allocationSizeMin = size;
+ }
+ if(size > inoutInfo.allocationSizeMax)
+ {
+ inoutInfo.allocationSizeMax = size;
+ }
+}
+
+static void VmaAddStatInfoUnusedRange(VmaStatInfo& inoutInfo, VkDeviceSize size)
+{
+ ++inoutInfo.unusedRangeCount;
+ inoutInfo.unusedBytes += size;
+ if(size < inoutInfo.unusedRangeSizeMin)
+ {
+ inoutInfo.unusedRangeSizeMin = size;
+ }
+ if(size > inoutInfo.unusedRangeSizeMax)
+ {
+ inoutInfo.unusedRangeSizeMax = size;
+ }
+}
+
static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo)
{
inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ?
@@ -7941,31 +7970,19 @@
void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
{
- outInfo.blockCount = 1;
-
const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
- outInfo.allocationCount = rangeCount - m_FreeCount;
- outInfo.unusedRangeCount = m_FreeCount;
-
- outInfo.unusedBytes = m_SumFreeSize;
- outInfo.usedBytes = GetSize() - outInfo.unusedBytes;
-
- outInfo.allocationSizeMin = UINT64_MAX;
- outInfo.allocationSizeMax = 0;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMax = 0;
+ VmaInitStatInfo(outInfo);
+ outInfo.blockCount = 1;
for(const auto& suballoc : m_Suballocations)
{
if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
{
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddStatInfoAllocation(outInfo, suballoc.size);
}
else
{
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size);
+ VmaAddStatInfoUnusedRange(outInfo, suballoc.size);
}
}
}
@@ -9077,14 +9094,8 @@
const size_t suballoc1stCount = suballocations1st.size();
const size_t suballoc2ndCount = suballocations2nd.size();
+ VmaInitStatInfo(outInfo);
outInfo.blockCount = 1;
- outInfo.allocationCount = (uint32_t)GetAllocationCount();
- outInfo.unusedRangeCount = 0;
- outInfo.usedBytes = 0;
- outInfo.allocationSizeMin = UINT64_MAX;
- outInfo.allocationSizeMax = 0;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMax = 0;
VkDeviceSize lastOffset = 0;
@@ -9111,17 +9122,12 @@
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddStatInfoAllocation(outInfo, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -9134,10 +9140,7 @@
if(lastOffset < freeSpace2ndTo1stEnd)
{
const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// End of loop.
@@ -9168,17 +9171,12 @@
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddStatInfoAllocation(outInfo, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -9191,10 +9189,7 @@
if(lastOffset < freeSpace1stTo2ndEnd)
{
const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// End of loop.
@@ -9224,17 +9219,12 @@
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddStatInfoAllocation(outInfo, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -9247,10 +9237,7 @@
if(lastOffset < size)
{
const VkDeviceSize unusedRangeSize = size - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize);
}
// End of loop.
@@ -10761,24 +10748,15 @@
void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
{
+ VmaInitStatInfo(outInfo);
outInfo.blockCount = 1;
- outInfo.allocationCount = outInfo.unusedRangeCount = 0;
- outInfo.usedBytes = outInfo.unusedBytes = 0;
-
- outInfo.allocationSizeMax = outInfo.unusedRangeSizeMax = 0;
- outInfo.allocationSizeMin = outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.allocationSizeAvg = outInfo.unusedRangeSizeAvg = 0; // Unused.
-
CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));
const VkDeviceSize unusableSize = GetUnusableSize();
if(unusableSize > 0)
{
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusableSize;
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusableSize);
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusableSize);
+ VmaAddStatInfoUnusedRange(outInfo, unusableSize);
}
}
@@ -11135,29 +11113,23 @@
AddToFreeListFront(level, node);
}
-void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& inoutInfo, const Node* node, VkDeviceSize levelNodeSize) const
{
switch(node->type)
{
case Node::TYPE_FREE:
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += levelNodeSize;
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, levelNodeSize);
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, levelNodeSize);
+ VmaAddStatInfoUnusedRange(inoutInfo, levelNodeSize);
break;
case Node::TYPE_ALLOCATION:
- ++outInfo.allocationCount;
- outInfo.usedBytes += levelNodeSize;
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, levelNodeSize);
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, levelNodeSize);
+ VmaAddStatInfoAllocation(inoutInfo, levelNodeSize);
break;
case Node::TYPE_SPLIT:
{
const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
const Node* const leftChild = node->split.leftChild;
- CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);
+ CalcAllocationStatInfoNode(inoutInfo, leftChild, childrenNodeSize);
const Node* const rightChild = leftChild->buddy;
- CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);
+ CalcAllocationStatInfoNode(inoutInfo, rightChild, childrenNodeSize);
}
break;
default:
@@ -15658,11 +15630,11 @@
void VmaAllocator_T::CalculateStats(VmaStats* pStats)
{
// Initialize.
- InitStatInfo(pStats->total);
+ VmaInitStatInfo(pStats->total);
for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
- InitStatInfo(pStats->memoryType[i]);
+ VmaInitStatInfo(pStats->memoryType[i]);
for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
- InitStatInfo(pStats->memoryHeap[i]);
+ VmaInitStatInfo(pStats->memoryHeap[i]);
// Process default pools.
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 50b34cc..1dde2dc 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -2824,7 +2824,7 @@
RandomNumberGenerator rand{3454335};
auto calcRandomAllocSize = [&rand]() -> VkDeviceSize { return rand.Generate() % 20 + 5; };
- for(size_t algorithmIndex = 0; algorithmIndex < 1/*3*/; ++algorithmIndex)
+ for(size_t algorithmIndex = 0; algorithmIndex < 3; ++algorithmIndex)
{
// Create the block
VmaVirtualBlockCreateInfo blockCreateInfo = {};
@@ -2841,7 +2841,7 @@
struct AllocData
{
- VkDeviceSize offset, size;
+ VkDeviceSize offset, requestedSize, allocationSize;
};
std::vector<AllocData> allocations;
@@ -2858,9 +2858,15 @@
else if(i < 18 && algorithmIndex == 1) allocCreateInfo.flags = VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
AllocData alloc = {};
- alloc.size = allocCreateInfo.size;
+ alloc.requestedSize = allocCreateInfo.size;
res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc.offset);
TEST(res == VK_SUCCESS);
+
+ VmaVirtualAllocationInfo allocInfo;
+ vmaGetVirtualAllocationInfo(block, alloc.offset, &allocInfo);
+ TEST(allocInfo.size >= allocCreateInfo.size);
+ alloc.allocationSize = allocInfo.size;
+
allocations.push_back(alloc);
}
@@ -2880,9 +2886,15 @@
allocCreateInfo.pUserData = (void*)(uintptr_t)(allocCreateInfo.size * 10);
AllocData alloc = {};
- alloc.size = allocCreateInfo.size;
+ alloc.requestedSize = allocCreateInfo.size;
res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc.offset);
TEST(res == VK_SUCCESS);
+
+ VmaVirtualAllocationInfo allocInfo;
+ vmaGetVirtualAllocationInfo(block, alloc.offset, &allocInfo);
+ TEST(allocInfo.size >= allocCreateInfo.size);
+ alloc.allocationSize = allocInfo.size;
+
allocations.push_back(alloc);
}
@@ -2895,10 +2907,16 @@
allocCreateInfo.pUserData = (void*)(uintptr_t)(allocCreateInfo.size * 10);
AllocData alloc = {};
- alloc.size = allocCreateInfo.size;
+ alloc.requestedSize = allocCreateInfo.size;
res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc.offset);
TEST(res == VK_SUCCESS);
TEST(alloc.offset % 16 == 0);
+
+ VmaVirtualAllocationInfo allocInfo;
+ vmaGetVirtualAllocationInfo(block, alloc.offset, &allocInfo);
+ TEST(allocInfo.size >= allocCreateInfo.size);
+ alloc.allocationSize = allocInfo.size;
+
allocations.push_back(alloc);
}
@@ -2907,7 +2925,7 @@
return lhs.offset < rhs.offset; });
for(size_t i = 0; i < allocations.size() - 1; ++i)
{
- TEST(allocations[i+1].offset >= allocations[i].offset + allocations[i].size);
+ TEST(allocations[i+1].offset >= allocations[i].offset + allocations[i].allocationSize);
}
// Check pUserData
@@ -2915,7 +2933,7 @@
const AllocData& alloc = allocations.back();
VmaVirtualAllocationInfo allocInfo = {};
vmaGetVirtualAllocationInfo(block, alloc.offset, &allocInfo);
- TEST((uintptr_t)allocInfo.pUserData == alloc.size * 10);
+ TEST((uintptr_t)allocInfo.pUserData == alloc.requestedSize * 10);
vmaSetVirtualAllocationUserData(block, alloc.offset, (void*)(uintptr_t)666);
vmaGetVirtualAllocationInfo(block, alloc.offset, &allocInfo);
@@ -2924,11 +2942,11 @@
// Calculate statistics
{
- VkDeviceSize allocSizeMin = VK_WHOLE_SIZE, allocSizeMax = 0, allocSizeSum = 0;
+ VkDeviceSize actualAllocSizeMin = VK_WHOLE_SIZE, actualAllocSizeMax = 0, actualAllocSizeSum = 0;
std::for_each(allocations.begin(), allocations.end(), [&](const AllocData& a) {
- allocSizeMin = std::min(allocSizeMin, a.size);
- allocSizeMax = std::max(allocSizeMax, a.size);
- allocSizeSum += a.size;
+ actualAllocSizeMin = std::min(actualAllocSizeMin, a.allocationSize);
+ actualAllocSizeMax = std::max(actualAllocSizeMax, a.allocationSize);
+ actualAllocSizeSum += a.allocationSize;
});
VmaStatInfo statInfo = {};
@@ -2936,9 +2954,9 @@
TEST(statInfo.allocationCount == allocations.size());
TEST(statInfo.blockCount == 1);
TEST(statInfo.usedBytes + statInfo.unusedBytes == blockCreateInfo.size);
- TEST(statInfo.allocationSizeMax == allocSizeMax);
- TEST(statInfo.allocationSizeMin == allocSizeMin);
- TEST(statInfo.usedBytes >= allocSizeSum);
+ TEST(statInfo.allocationSizeMax == actualAllocSizeMax);
+ TEST(statInfo.allocationSizeMin == actualAllocSizeMin);
+ TEST(statInfo.usedBytes >= actualAllocSizeSum);
}
// Build JSON dump string
@@ -6834,6 +6852,7 @@
{
////////////////////////////////////////////////////////////////////////////////
// Temporarily insert custom tests here:
+ TestVirtualBlocks();
TestVirtualBlocksAlgorithms();
return;
}
@@ -6842,6 +6861,7 @@
TestBasics();
TestVirtualBlocks();
+ TestVirtualBlocksAlgorithms();
TestAllocationVersusResourceSize();
//TestGpuData(); // Not calling this because it's just testing the testing environment.
#if VMA_DEBUG_MARGIN