Skip to content

Commit 9b76877

Browse files
Added comprehensive tests for all kinds of statistics
1 parent 71309c5 commit 9b76877

File tree

1 file changed

+227
-15
lines changed

1 file changed

+227
-15
lines changed

src/Tests.cpp

Lines changed: 227 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,23 @@ static const wchar_t* DefragmentationAlgorithmToStr(uint32_t algorithm)
117117
}
118118
}
119119

120+
static inline bool operator==(const VmaStatistics& lhs, const VmaStatistics& rhs)
121+
{
122+
return lhs.allocationBytes == rhs.allocationBytes &&
123+
lhs.allocationCount == rhs.allocationCount &&
124+
lhs.blockBytes == rhs.blockBytes &&
125+
lhs.blockCount == rhs.blockCount;
126+
}
127+
static inline bool operator==(const VmaDetailedStatistics& lhs, const VmaDetailedStatistics& rhs)
128+
{
129+
return lhs.statistics == rhs.statistics &&
130+
lhs.unusedRangeCount == rhs.unusedRangeCount &&
131+
lhs.allocationSizeMax == rhs.allocationSizeMax &&
132+
lhs.allocationSizeMin == rhs.allocationSizeMin &&
133+
lhs.unusedRangeSizeMax == rhs.unusedRangeSizeMax &&
134+
lhs.unusedRangeSizeMin == rhs.unusedRangeSizeMin;
135+
}
136+
120137
struct AllocationSize
121138
{
122139
uint32_t Probability;
@@ -6213,22 +6230,70 @@ static void TestDeviceCoherentMemory()
62136230
vmaDestroyAllocator(localAllocator);
62146231
}
62156232

6216-
static void TestBudget()
6233+
static void InitEmptyDetailedStatistics(VmaDetailedStatistics& outStats)
62176234
{
6218-
wprintf(L"Testing budget...\n");
6235+
outStats = {};
6236+
outStats.allocationSizeMin = VK_WHOLE_SIZE;
6237+
outStats.unusedRangeSizeMin = VK_WHOLE_SIZE;
6238+
}
62196239

6220-
static const VkDeviceSize BUF_SIZE = 10ull * 1024 * 1024;
6221-
static const uint32_t BUF_COUNT = 4;
6240+
static void AddDetailedStatistics(VmaDetailedStatistics& inoutSum, const VmaDetailedStatistics& stats)
6241+
{
6242+
inoutSum.statistics.allocationBytes += stats.statistics.allocationBytes;
6243+
inoutSum.statistics.allocationCount += stats.statistics.allocationCount;
6244+
inoutSum.statistics.blockBytes += stats.statistics.blockBytes;
6245+
inoutSum.statistics.blockCount += stats.statistics.blockCount;
6246+
inoutSum.unusedRangeCount += stats.unusedRangeCount;
6247+
inoutSum.allocationSizeMax = std::max(inoutSum.allocationSizeMax, stats.allocationSizeMax);
6248+
inoutSum.allocationSizeMin = std::min(inoutSum.allocationSizeMin, stats.allocationSizeMin);
6249+
inoutSum.unusedRangeSizeMax = std::max(inoutSum.unusedRangeSizeMax, stats.unusedRangeSizeMax);
6250+
inoutSum.unusedRangeSizeMin = std::min(inoutSum.unusedRangeSizeMin, stats.unusedRangeSizeMin);
6251+
}
6252+
6253+
static void ValidateTotalStatistics(const VmaTotalStatistics& stats)
6254+
{
6255+
const VkPhysicalDeviceMemoryProperties* memProps = nullptr;
6256+
vmaGetMemoryProperties(g_hAllocator, &memProps);
6257+
6258+
VmaDetailedStatistics sum;
6259+
InitEmptyDetailedStatistics(sum);
6260+
for(uint32_t i = 0; i < memProps->memoryHeapCount; ++i)
6261+
AddDetailedStatistics(sum, stats.memoryHeap[i]);
6262+
TEST(sum == stats.total);
6263+
6264+
InitEmptyDetailedStatistics(sum);
6265+
for(uint32_t i = 0; i < memProps->memoryTypeCount; ++i)
6266+
AddDetailedStatistics(sum, stats.memoryType[i]);
6267+
TEST(sum == stats.total);
6268+
}
6269+
6270+
static void TestStatistics()
6271+
{
6272+
wprintf(L"Testing statistics...\n");
6273+
6274+
constexpr VkDeviceSize BUF_SIZE = 10ull * 1024 * 1024;
6275+
constexpr uint32_t BUF_COUNT = 4;
6276+
constexpr VkDeviceSize PREALLOCATED_BLOCK_SIZE = BUF_SIZE * (BUF_COUNT + 1);
62226277

62236278
const VkPhysicalDeviceMemoryProperties* memProps = {};
62246279
vmaGetMemoryProperties(g_hAllocator, &memProps);
62256280

6226-
for(uint32_t testIndex = 0; testIndex < 2; ++testIndex)
6281+
/*
6282+
Test 0: VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
6283+
Test 1: normal allocations.
6284+
Test 2: allocations in a custom pool.
6285+
Test 3: allocations in a custom pool, DEDICATED_MEMORY.
6286+
Test 4: allocations in a custom pool with preallocated memory.
6287+
*/
6288+
uint32_t memTypeIndex = UINT32_MAX;
6289+
for(uint32_t testIndex = 0; testIndex < 5; ++testIndex)
62276290
{
62286291
vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
62296292

62306293
VmaBudget budgetBeg[VK_MAX_MEMORY_HEAPS] = {};
62316294
vmaGetHeapBudgets(g_hAllocator, budgetBeg);
6295+
VmaTotalStatistics statsBeg = {};
6296+
vmaCalculateStatistics(g_hAllocator, &statsBeg);
62326297

62336298
for(uint32_t i = 0; i < memProps->memoryHeapCount; ++i)
62346299
{
@@ -6237,18 +6302,45 @@ static void TestBudget()
62376302
TEST(budgetBeg[i].statistics.allocationBytes <= budgetBeg[i].statistics.blockBytes);
62386303
}
62396304

6305+
// Create pool.
6306+
const bool usePool = testIndex >= 2;
6307+
const bool useDedicated = testIndex == 0 || testIndex == 3;
6308+
const bool usePreallocated = testIndex == 4;
6309+
VmaPool pool = VK_NULL_HANDLE;
6310+
if(usePool)
6311+
{
6312+
assert(memTypeIndex != UINT32_MAX);
6313+
VmaPoolCreateInfo poolCreateInfo = {};
6314+
poolCreateInfo.memoryTypeIndex = memTypeIndex;
6315+
if(usePreallocated)
6316+
{
6317+
poolCreateInfo.blockSize = PREALLOCATED_BLOCK_SIZE;
6318+
poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
6319+
}
6320+
TEST(vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) == VK_SUCCESS);
6321+
}
6322+
6323+
VmaStatistics poolStatsBeg = {};
6324+
VmaDetailedStatistics detailedPoolStatsBeg = {};
6325+
if(usePool)
6326+
{
6327+
vmaGetPoolStatistics(g_hAllocator, pool, &poolStatsBeg);
6328+
vmaCalculatePoolStatistics(g_hAllocator, pool, &detailedPoolStatsBeg);
6329+
}
6330+
6331+
// CREATE BUFFERS
62406332
VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
62416333
bufInfo.size = BUF_SIZE;
62426334
bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
62436335

62446336
VmaAllocationCreateInfo allocCreateInfo = {};
6245-
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
6246-
if(testIndex == 0)
6247-
{
6337+
if(usePool)
6338+
allocCreateInfo.pool = pool;
6339+
else
6340+
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
6341+
if(useDedicated)
62486342
allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
6249-
}
62506343

6251-
// CREATE BUFFERS
62526344
uint32_t heapIndex = 0;
62536345
BufferInfo bufInfos[BUF_COUNT] = {};
62546346
for(uint32_t bufIndex = 0; bufIndex < BUF_COUNT; ++bufIndex)
@@ -6259,6 +6351,8 @@ static void TestBudget()
62596351
TEST(res == VK_SUCCESS);
62606352
if(bufIndex == 0)
62616353
{
6354+
if(testIndex == 1)
6355+
memTypeIndex = allocInfo.memoryType;
62626356
heapIndex = MemoryTypeToHeap(allocInfo.memoryType);
62636357
}
62646358
else
@@ -6270,32 +6364,150 @@ static void TestBudget()
62706364

62716365
VmaBudget budgetWithBufs[VK_MAX_MEMORY_HEAPS] = {};
62726366
vmaGetHeapBudgets(g_hAllocator, budgetWithBufs);
6367+
VmaTotalStatistics statsWithBufs = {};
6368+
vmaCalculateStatistics(g_hAllocator, &statsWithBufs);
6369+
6370+
VmaStatistics poolStatsWithBufs = {};
6371+
VmaDetailedStatistics detailedPoolStatsWithBufs = {};
6372+
if(usePool)
6373+
{
6374+
vmaGetPoolStatistics(g_hAllocator, pool, &poolStatsWithBufs);
6375+
vmaCalculatePoolStatistics(g_hAllocator, pool, &detailedPoolStatsWithBufs);
6376+
}
62736377

62746378
// DESTROY BUFFERS
62756379
for(size_t bufIndex = BUF_COUNT; bufIndex--; )
62766380
{
62776381
vmaDestroyBuffer(g_hAllocator, bufInfos[bufIndex].Buffer, bufInfos[bufIndex].Allocation);
62786382
}
62796383

6384+
VmaStatistics poolStatsEnd = {};
6385+
VmaDetailedStatistics detailedPoolStatsEnd = {};
6386+
if(usePool)
6387+
{
6388+
vmaGetPoolStatistics(g_hAllocator, pool, &poolStatsEnd);
6389+
vmaCalculatePoolStatistics(g_hAllocator, pool, &detailedPoolStatsEnd);
6390+
}
6391+
6392+
// Destroy the pool.
6393+
vmaDestroyPool(g_hAllocator, pool);
6394+
62806395
VmaBudget budgetEnd[VK_MAX_MEMORY_HEAPS] = {};
62816396
vmaGetHeapBudgets(g_hAllocator, budgetEnd);
6397+
VmaTotalStatistics statsEnd = {};
6398+
vmaCalculateStatistics(g_hAllocator, &statsEnd);
62826399

6283-
// CHECK
6400+
// CHECK MEMORY HEAPS
62846401
for(uint32_t i = 0; i < memProps->memoryHeapCount; ++i)
62856402
{
62866403
TEST(budgetEnd[i].statistics.allocationBytes <= budgetEnd[i].statistics.blockBytes);
6404+
6405+
// The heap in which we allocated the testing buffers.
62876406
if(i == heapIndex)
62886407
{
6408+
// VmaBudget::usage
6409+
TEST(budgetWithBufs[i].usage >= budgetBeg[i].usage);
6410+
TEST(budgetEnd[i].usage <= budgetWithBufs[i].usage);
6411+
6412+
// VmaBudget - VmaStatistics::allocationBytes
62896413
TEST(budgetEnd[i].statistics.allocationBytes == budgetBeg[i].statistics.allocationBytes);
62906414
TEST(budgetWithBufs[i].statistics.allocationBytes == budgetBeg[i].statistics.allocationBytes + BUF_SIZE * BUF_COUNT);
6291-
TEST(budgetWithBufs[i].statistics.blockBytes >= budgetEnd[i].statistics.blockBytes);
6415+
6416+
// VmaBudget - VmaStatistics::blockBytes
6417+
if(usePool)
6418+
{
6419+
TEST(budgetEnd[i].statistics.blockBytes == budgetBeg[i].statistics.blockBytes);
6420+
TEST(budgetWithBufs[i].statistics.blockBytes > budgetBeg[i].statistics.blockBytes);
6421+
}
6422+
else
6423+
TEST(budgetWithBufs[i].statistics.blockBytes >= budgetBeg[i].statistics.blockBytes);
6424+
6425+
// VmaBudget - VmaStatistics::allocationCount
6426+
TEST(budgetEnd[i].statistics.allocationCount == budgetBeg[i].statistics.allocationCount);
6427+
TEST(budgetWithBufs[i].statistics.allocationCount == budgetBeg[i].statistics.allocationCount + BUF_COUNT);
6428+
6429+
// VmaBudget - VmaStatistics::blockCount
6430+
if(useDedicated)
6431+
{
6432+
TEST(budgetEnd[i].statistics.blockCount == budgetBeg[i].statistics.blockCount);
6433+
TEST(budgetWithBufs[i].statistics.blockCount == budgetBeg[i].statistics.blockCount + BUF_COUNT);
6434+
}
6435+
else if(usePool)
6436+
{
6437+
TEST(budgetEnd[i].statistics.blockCount == budgetBeg[i].statistics.blockCount);
6438+
if(usePreallocated)
6439+
TEST(budgetWithBufs[i].statistics.blockCount == budgetBeg[i].statistics.blockCount + 1);
6440+
else
6441+
TEST(budgetWithBufs[i].statistics.blockCount > budgetBeg[i].statistics.blockCount);
6442+
}
62926443
}
62936444
else
62946445
{
6295-
TEST(budgetEnd[i].statistics.allocationBytes == budgetEnd[i].statistics.allocationBytes &&
6446+
TEST(budgetEnd[i].statistics.allocationBytes == budgetBeg[i].statistics.allocationBytes &&
62966447
budgetEnd[i].statistics.allocationBytes == budgetWithBufs[i].statistics.allocationBytes);
6297-
TEST(budgetEnd[i].statistics.blockBytes == budgetEnd[i].statistics.blockBytes &&
6448+
TEST(budgetEnd[i].statistics.blockBytes == budgetBeg[i].statistics.blockBytes &&
62986449
budgetEnd[i].statistics.blockBytes == budgetWithBufs[i].statistics.blockBytes);
6450+
TEST(budgetEnd[i].statistics.allocationCount == budgetBeg[i].statistics.allocationCount &&
6451+
budgetEnd[i].statistics.allocationCount == budgetWithBufs[i].statistics.allocationCount);
6452+
TEST(budgetEnd[i].statistics.blockCount == budgetBeg[i].statistics.blockCount &&
6453+
budgetEnd[i].statistics.blockCount == budgetWithBufs[i].statistics.blockCount);
6454+
}
6455+
6456+
// Validate that statistics per heap and per type sum up to total correctly.
6457+
ValidateTotalStatistics(statsBeg);
6458+
ValidateTotalStatistics(statsWithBufs);
6459+
ValidateTotalStatistics(statsEnd);
6460+
6461+
// Compare vmaCalculateStatistics per heap with vmaGetBudget.
6462+
TEST(statsBeg.memoryHeap[i].statistics == budgetBeg[i].statistics);
6463+
TEST(statsWithBufs.memoryHeap[i].statistics == budgetWithBufs[i].statistics);
6464+
TEST(statsEnd.memoryHeap[i].statistics == budgetEnd[i].statistics);
6465+
6466+
if(usePool)
6467+
{
6468+
// Compare simple stats with calculated stats to make sure they are identical.
6469+
TEST(poolStatsBeg == detailedPoolStatsBeg.statistics);
6470+
TEST(poolStatsWithBufs == detailedPoolStatsWithBufs.statistics);
6471+
TEST(poolStatsEnd == detailedPoolStatsEnd.statistics);
6472+
6473+
// Validate stats of an empty pool.
6474+
TEST(detailedPoolStatsBeg.allocationSizeMax == 0);
6475+
TEST(detailedPoolStatsEnd.allocationSizeMax == 0);
6476+
TEST(detailedPoolStatsBeg.allocationSizeMin == VK_WHOLE_SIZE);
6477+
TEST(detailedPoolStatsEnd.allocationSizeMin == VK_WHOLE_SIZE);
6478+
TEST(poolStatsBeg.allocationCount == 0);
6479+
TEST(poolStatsBeg.allocationBytes == 0);
6480+
TEST(poolStatsEnd.allocationCount == 0);
6481+
TEST(poolStatsEnd.allocationBytes == 0);
6482+
if(usePreallocated)
6483+
{
6484+
TEST(poolStatsBeg.blockCount == 1);
6485+
TEST(poolStatsEnd.blockCount == 1);
6486+
TEST(poolStatsBeg.blockBytes == PREALLOCATED_BLOCK_SIZE);
6487+
TEST(poolStatsEnd.blockBytes == PREALLOCATED_BLOCK_SIZE);
6488+
}
6489+
else
6490+
{
6491+
TEST(poolStatsBeg.blockCount == 0);
6492+
TEST(poolStatsBeg.blockBytes == 0);
6493+
// Not checking poolStatsEnd.blockCount, blockBytes, because an empty block may stay allocated.
6494+
}
6495+
6496+
// Validate stats of a pool with buffers.
6497+
TEST(detailedPoolStatsWithBufs.allocationSizeMin == BUF_SIZE);
6498+
TEST(detailedPoolStatsWithBufs.allocationSizeMax == BUF_SIZE);
6499+
TEST(poolStatsWithBufs.allocationCount == BUF_COUNT);
6500+
TEST(poolStatsWithBufs.allocationBytes == BUF_COUNT * BUF_SIZE);
6501+
if(usePreallocated)
6502+
{
6503+
TEST(poolStatsWithBufs.blockCount == 1);
6504+
TEST(poolStatsWithBufs.blockBytes == PREALLOCATED_BLOCK_SIZE);
6505+
}
6506+
else
6507+
{
6508+
TEST(poolStatsWithBufs.blockCount > 0);
6509+
TEST(poolStatsWithBufs.blockBytes >= poolStatsWithBufs.allocationBytes);
6510+
}
62996511
}
63006512
}
63016513
}
@@ -8146,7 +8358,7 @@ void Test()
81468358
#endif
81478359
TestMemoryUsage();
81488360
TestDeviceCoherentMemory();
8149-
TestBudget();
8361+
TestStatistics();
81508362
TestAliasing();
81518363
TestAllocationAliasing();
81528364
TestMapping();

0 commit comments

Comments
 (0)