mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
synced 2025-05-15 01:08:31 +00:00
parent
fbd9e6eae6
commit
0d5359c30f
1 changed files with 87 additions and 113 deletions
200
src/Tests.cpp
200
src/Tests.cpp
|
@ -760,6 +760,7 @@ struct AllocInfo
|
||||||
VkBufferCreateInfo m_BufferInfo;
|
VkBufferCreateInfo m_BufferInfo;
|
||||||
VkImageCreateInfo m_ImageInfo;
|
VkImageCreateInfo m_ImageInfo;
|
||||||
};
|
};
|
||||||
|
bool m_DefragmentationMovable = true;
|
||||||
|
|
||||||
// After defragmentation.
|
// After defragmentation.
|
||||||
VkBuffer m_NewBuffer = VK_NULL_HANDLE;
|
VkBuffer m_NewBuffer = VK_NULL_HANDLE;
|
||||||
|
@ -1447,13 +1448,14 @@ static void ProcessDefragmentationPass(VmaDefragmentationPassMoveInfo& stepInfo)
|
||||||
|
|
||||||
for (uint32_t i = 0; i < stepInfo.moveCount; ++i)
|
for (uint32_t i = 0; i < stepInfo.moveCount; ++i)
|
||||||
{
|
{
|
||||||
if (stepInfo.pMoves[i].operation == VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY)
|
VmaAllocationInfo info;
|
||||||
|
vmaGetAllocationInfo(g_hAllocator, stepInfo.pMoves[i].srcAllocation, &info);
|
||||||
|
|
||||||
|
AllocInfo* allocInfo = (AllocInfo*)info.pUserData;
|
||||||
|
// Allocation comes from this test and it is movable.
|
||||||
|
if(stepInfo.pMoves[i].operation == VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY &&
|
||||||
|
allocInfo != nullptr && allocInfo->m_DefragmentationMovable)
|
||||||
{
|
{
|
||||||
VmaAllocationInfo info;
|
|
||||||
vmaGetAllocationInfo(g_hAllocator, stepInfo.pMoves[i].srcAllocation, &info);
|
|
||||||
|
|
||||||
AllocInfo* allocInfo = (AllocInfo*)info.pUserData;
|
|
||||||
|
|
||||||
if (allocInfo->m_Image)
|
if (allocInfo->m_Image)
|
||||||
{
|
{
|
||||||
VkImage newImage;
|
VkImage newImage;
|
||||||
|
@ -1531,6 +1533,11 @@ static void ProcessDefragmentationPass(VmaDefragmentationPassMoveInfo& stepInfo)
|
||||||
wantsMemoryBarrier = true;
|
wantsMemoryBarrier = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Some unrelated allocation not from this test or non-movable.
|
||||||
|
stepInfo.pMoves[i].operation = VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!beginImageBarriers.empty() || wantsMemoryBarrier)
|
if (!beginImageBarriers.empty() || wantsMemoryBarrier)
|
||||||
|
@ -1626,6 +1633,8 @@ static void Defragment(VmaDefragmentationInfo& defragmentationInfo,
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
BeginSingleTimeCommands();
|
BeginSingleTimeCommands();
|
||||||
ProcessDefragmentationPass(pass);
|
ProcessDefragmentationPass(pass);
|
||||||
EndSingleTimeCommands();
|
EndSingleTimeCommands();
|
||||||
|
@ -1637,23 +1646,26 @@ static void Defragment(VmaDefragmentationInfo& defragmentationInfo,
|
||||||
VmaAllocationInfo vmaAllocInfo;
|
VmaAllocationInfo vmaAllocInfo;
|
||||||
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
||||||
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
||||||
|
if(pass.pMoves[i].operation != VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE)
|
||||||
if(allocInfo->m_Buffer)
|
|
||||||
{
|
{
|
||||||
assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
TEST(allocInfo != nullptr && allocInfo->m_DefragmentationMovable);
|
||||||
vkDestroyBuffer(g_hDevice, allocInfo->m_Buffer, g_Allocs);
|
if (allocInfo->m_Buffer)
|
||||||
allocInfo->m_Buffer = allocInfo->m_NewBuffer;
|
{
|
||||||
allocInfo->m_NewBuffer = VK_NULL_HANDLE;
|
TEST(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
||||||
|
vkDestroyBuffer(g_hDevice, allocInfo->m_Buffer, g_Allocs);
|
||||||
|
allocInfo->m_Buffer = allocInfo->m_NewBuffer;
|
||||||
|
allocInfo->m_NewBuffer = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
else if (allocInfo->m_Image)
|
||||||
|
{
|
||||||
|
TEST(allocInfo->m_NewImage && !allocInfo->m_Buffer && !allocInfo->m_NewBuffer);
|
||||||
|
vkDestroyImage(g_hDevice, allocInfo->m_Image, g_Allocs);
|
||||||
|
allocInfo->m_Image = allocInfo->m_NewImage;
|
||||||
|
allocInfo->m_NewImage = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
else if(allocInfo->m_Image)
|
|
||||||
{
|
|
||||||
assert(allocInfo->m_NewImage && !allocInfo->m_Buffer && !allocInfo->m_NewBuffer);
|
|
||||||
vkDestroyImage(g_hDevice, allocInfo->m_Image, g_Allocs);
|
|
||||||
allocInfo->m_Image = allocInfo->m_NewImage;
|
|
||||||
allocInfo->m_NewImage = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
if ((res = vmaEndDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_SUCCESS)
|
if ((res = vmaEndDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
@ -1897,7 +1909,6 @@ void TestDefragmentationSimple()
|
||||||
// persistentlyMappedOption = 1 - persistently mapped.
|
// persistentlyMappedOption = 1 - persistently mapped.
|
||||||
for (uint32_t persistentlyMappedOption = 0; persistentlyMappedOption < 2; ++persistentlyMappedOption)
|
for (uint32_t persistentlyMappedOption = 0; persistentlyMappedOption < 2; ++persistentlyMappedOption)
|
||||||
{
|
{
|
||||||
wprintf(L" Persistently mapped option = %u\n", persistentlyMappedOption);
|
|
||||||
const bool persistentlyMapped = persistentlyMappedOption != 0;
|
const bool persistentlyMapped = persistentlyMappedOption != 0;
|
||||||
|
|
||||||
// # Test 1
|
// # Test 1
|
||||||
|
@ -1905,6 +1916,8 @@ void TestDefragmentationSimple()
|
||||||
// Fill 2 blocks. Remove odd buffers. Defragment everything.
|
// Fill 2 blocks. Remove odd buffers. Defragment everything.
|
||||||
// Expected result: at least 1 block freed.
|
// Expected result: at least 1 block freed.
|
||||||
{
|
{
|
||||||
|
wprintf(L" Persistently mapped option = %u test 1\n", persistentlyMappedOption);
|
||||||
|
|
||||||
for (size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
|
for (size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
|
||||||
{
|
{
|
||||||
AllocInfo allocInfo;
|
AllocInfo allocInfo;
|
||||||
|
@ -1935,6 +1948,8 @@ void TestDefragmentationSimple()
|
||||||
// Fill 2 blocks. Remove odd buffers. Defragment one buffer at time.
|
// Fill 2 blocks. Remove odd buffers. Defragment one buffer at time.
|
||||||
// Expected result: Each of 4 interations makes some progress.
|
// Expected result: Each of 4 interations makes some progress.
|
||||||
{
|
{
|
||||||
|
wprintf(L" Persistently mapped option = %u test 2\n", persistentlyMappedOption);
|
||||||
|
|
||||||
for (size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
|
for (size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
|
||||||
{
|
{
|
||||||
AllocInfo allocInfo;
|
AllocInfo allocInfo;
|
||||||
|
@ -1964,6 +1979,7 @@ void TestDefragmentationSimple()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass);
|
res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass);
|
||||||
TEST(res == VK_INCOMPLETE);
|
TEST(res == VK_INCOMPLETE);
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
BeginSingleTimeCommands();
|
BeginSingleTimeCommands();
|
||||||
ProcessDefragmentationPass(pass);
|
ProcessDefragmentationPass(pass);
|
||||||
|
@ -1977,6 +1993,7 @@ void TestDefragmentationSimple()
|
||||||
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
||||||
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
||||||
|
|
||||||
|
if(allocInfo != nullptr && allocInfo->m_DefragmentationMovable)
|
||||||
if (allocInfo->m_Buffer)
|
if (allocInfo->m_Buffer)
|
||||||
{
|
{
|
||||||
assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
||||||
|
@ -2013,6 +2030,8 @@ void TestDefragmentationSimple()
|
||||||
// Defragment while having some percent of them unmovable.
|
// Defragment while having some percent of them unmovable.
|
||||||
// Expected result: Just simple validation.
|
// Expected result: Just simple validation.
|
||||||
{
|
{
|
||||||
|
wprintf(L" Persistently mapped option = %u test 3\n", persistentlyMappedOption);
|
||||||
|
|
||||||
for (size_t i = 0; i < 100; ++i)
|
for (size_t i = 0; i < 100; ++i)
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo localBufCreateInfo = bufCreateInfo;
|
VkBufferCreateInfo localBufCreateInfo = bufCreateInfo;
|
||||||
|
@ -2039,7 +2058,10 @@ void TestDefragmentationSimple()
|
||||||
{
|
{
|
||||||
size_t indexNonMovable = i + rand.Generate() % (uint32_t)(allocations.size() - i);
|
size_t indexNonMovable = i + rand.Generate() % (uint32_t)(allocations.size() - i);
|
||||||
if (indexNonMovable != i)
|
if (indexNonMovable != i)
|
||||||
|
{
|
||||||
std::swap(allocations[i], allocations[indexNonMovable]);
|
std::swap(allocations[i], allocations[indexNonMovable]);
|
||||||
|
allocations[i].m_DefragmentationMovable = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set data for defragmentation retrieval
|
// Set data for defragmentation retrieval
|
||||||
|
@ -2056,13 +2078,7 @@ void TestDefragmentationSimple()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
VmaDefragmentationMove* end = pass.pMoves + pass.moveCount;
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
for (uint32_t i = 0; i < numberNonMovable; ++i)
|
|
||||||
{
|
|
||||||
VmaDefragmentationMove* move = std::find_if(pass.pMoves, end, [&](VmaDefragmentationMove& move) { return move.srcAllocation == allocations[i].m_Allocation; });
|
|
||||||
if (move != end)
|
|
||||||
move->operation = VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginSingleTimeCommands();
|
BeginSingleTimeCommands();
|
||||||
ProcessDefragmentationPass(pass);
|
ProcessDefragmentationPass(pass);
|
||||||
|
@ -2191,8 +2207,7 @@ void TestDefragmentationVsMapping()
|
||||||
if(res == VK_SUCCESS)
|
if(res == VK_SUCCESS)
|
||||||
break;
|
break;
|
||||||
TEST(res == VK_INCOMPLETE);
|
TEST(res == VK_INCOMPLETE);
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", passInfo.moveCount);
|
||||||
wprintf(L" Pass %u moving %u allocations\n", passIndex, passInfo.moveCount);
|
|
||||||
|
|
||||||
for(uint32_t moveIndex = 0; moveIndex < passInfo.moveCount; ++moveIndex)
|
for(uint32_t moveIndex = 0; moveIndex < passInfo.moveCount; ++moveIndex)
|
||||||
{
|
{
|
||||||
|
@ -2382,6 +2397,8 @@ void TestDefragmentationAlgorithms()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
VmaDefragmentationMove* end = pass.pMoves + pass.moveCount;
|
VmaDefragmentationMove* end = pass.pMoves + pass.moveCount;
|
||||||
for (uint32_t i = 0; i < numberNonMovable; ++i)
|
for (uint32_t i = 0; i < numberNonMovable; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2402,13 +2419,13 @@ void TestDefragmentationAlgorithms()
|
||||||
// Destroy old buffers/images and replace them with new handles.
|
// Destroy old buffers/images and replace them with new handles.
|
||||||
for (size_t i = 0; i < pass.moveCount; ++i)
|
for (size_t i = 0; i < pass.moveCount; ++i)
|
||||||
{
|
{
|
||||||
if (pass.pMoves[i].operation == VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY)
|
if (pass.pMoves[i].operation != VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE)
|
||||||
{
|
{
|
||||||
VmaAllocation const alloc = pass.pMoves[i].srcAllocation;
|
VmaAllocation const alloc = pass.pMoves[i].srcAllocation;
|
||||||
VmaAllocationInfo vmaAllocInfo;
|
VmaAllocationInfo vmaAllocInfo;
|
||||||
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
|
||||||
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
|
||||||
|
TEST(allocInfo != nullptr);
|
||||||
if (allocInfo->m_Buffer)
|
if (allocInfo->m_Buffer)
|
||||||
{
|
{
|
||||||
assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
|
||||||
|
@ -2433,7 +2450,7 @@ void TestDefragmentationAlgorithms()
|
||||||
TEST(res == VK_INCOMPLETE);
|
TEST(res == VK_INCOMPLETE);
|
||||||
}
|
}
|
||||||
TEST(res == VK_SUCCESS);
|
TEST(res == VK_SUCCESS);
|
||||||
|
|
||||||
VmaDefragmentationStats defragStats;
|
VmaDefragmentationStats defragStats;
|
||||||
vmaEndDefragmentation(g_hAllocator, defragCtx, &defragStats);
|
vmaEndDefragmentation(g_hAllocator, defragCtx, &defragStats);
|
||||||
|
|
||||||
|
@ -2448,6 +2465,8 @@ void TestDefragmentationAlgorithms()
|
||||||
|
|
||||||
void TestDefragmentationFull()
|
void TestDefragmentationFull()
|
||||||
{
|
{
|
||||||
|
wprintf(L"Test defragmentation full\n");
|
||||||
|
|
||||||
std::vector<AllocInfo> allocations;
|
std::vector<AllocInfo> allocations;
|
||||||
|
|
||||||
// Create initial allocations.
|
// Create initial allocations.
|
||||||
|
@ -2487,39 +2506,23 @@ void TestDefragmentationFull()
|
||||||
for (auto& alloc : allocations)
|
for (auto& alloc : allocations)
|
||||||
vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
|
vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
|
||||||
|
|
||||||
const uint32_t defragCount = 1;
|
VmaDefragmentationInfo defragmentationInfo = {};
|
||||||
for(uint32_t defragIndex = 0; defragIndex < defragCount; ++defragIndex)
|
defragmentationInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT;
|
||||||
{
|
|
||||||
std::vector<VkBool32> allocationsChanged(vmaAllocations.size());
|
|
||||||
|
|
||||||
VmaDefragmentationInfo defragmentationInfo = {};
|
time_point begTime = std::chrono::high_resolution_clock::now();
|
||||||
defragmentationInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT;
|
|
||||||
|
|
||||||
wprintf(L"Defragmentation #%u\n", defragIndex);
|
VmaDefragmentationStats stats;
|
||||||
|
Defragment(defragmentationInfo, &stats);
|
||||||
|
|
||||||
time_point begTime = std::chrono::high_resolution_clock::now();
|
float defragmentDuration = ToFloatSeconds(std::chrono::high_resolution_clock::now() - begTime);
|
||||||
|
|
||||||
VmaDefragmentationStats stats;
|
wprintf(L" Moved allocations %u, bytes %llu\n", stats.allocationsMoved, stats.bytesMoved);
|
||||||
Defragment(defragmentationInfo, &stats);
|
wprintf(L" Freed blocks %u, bytes %llu\n", stats.deviceMemoryBlocksFreed, stats.bytesFreed);
|
||||||
|
wprintf(L" Time: %.2f s\n", defragmentDuration);
|
||||||
|
|
||||||
float defragmentDuration = ToFloatSeconds(std::chrono::high_resolution_clock::now() - begTime);
|
//wchar_t fileName[MAX_PATH];
|
||||||
|
//swprintf(fileName, MAX_PATH, L"After_%02u.csv", defragIndex);
|
||||||
wprintf(L"Moved allocations %u, bytes %llu\n", stats.allocationsMoved, stats.bytesMoved);
|
//SaveAllocatorStatsToFile(fileName);
|
||||||
wprintf(L"Freed blocks %u, bytes %llu\n", stats.deviceMemoryBlocksFreed, stats.bytesFreed);
|
|
||||||
wprintf(L"Time: %.2f s\n", defragmentDuration);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < vmaAllocations.size(); ++i)
|
|
||||||
{
|
|
||||||
if(allocationsChanged[i])
|
|
||||||
{
|
|
||||||
RecreateAllocationResource(allocations[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//wchar_t fileName[MAX_PATH];
|
|
||||||
//swprintf(fileName, MAX_PATH, L"After_%02u.csv", defragIndex);
|
|
||||||
//SaveAllocatorStatsToFile(fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy all remaining allocations.
|
// Destroy all remaining allocations.
|
||||||
|
@ -2527,12 +2530,16 @@ void TestDefragmentationFull()
|
||||||
DestroyAllAllocations(allocations);
|
DestroyAllAllocations(allocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PrintDefragmentationStats(const VmaDefragmentationStats& stats)
|
||||||
|
{
|
||||||
|
wprintf(L" Stats: bytesMoved=%llu, bytesFreed=%llu, allocationsMoved=%u, deviceMemoryBlocksFreed=%u\n",
|
||||||
|
stats.bytesMoved, stats.bytesFreed, stats.allocationsMoved, stats.deviceMemoryBlocksFreed);
|
||||||
|
}
|
||||||
|
|
||||||
static void TestDefragmentationGpu()
|
static void TestDefragmentationGpu()
|
||||||
{
|
{
|
||||||
wprintf(L"Test defragmentation GPU\n");
|
wprintf(L"Test defragmentation GPU\n");
|
||||||
|
|
||||||
std::vector<AllocInfo> allocations;
|
|
||||||
|
|
||||||
// Create that many allocations to surely fill 3 new blocks of 256 MB.
|
// Create that many allocations to surely fill 3 new blocks of 256 MB.
|
||||||
const VkDeviceSize bufSizeMin = 5ull * 1024 * 1024;
|
const VkDeviceSize bufSizeMin = 5ull * 1024 * 1024;
|
||||||
const VkDeviceSize bufSizeMax = 10ull * 1024 * 1024;
|
const VkDeviceSize bufSizeMax = 10ull * 1024 * 1024;
|
||||||
|
@ -2542,6 +2549,9 @@ static void TestDefragmentationGpu()
|
||||||
const size_t percentNonMovable = 3;
|
const size_t percentNonMovable = 3;
|
||||||
RandomNumberGenerator rand = { 234522 };
|
RandomNumberGenerator rand = { 234522 };
|
||||||
|
|
||||||
|
std::vector<AllocInfo> allocations;
|
||||||
|
allocations.reserve(bufCount);
|
||||||
|
|
||||||
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||||
|
@ -2552,12 +2562,14 @@ static void TestDefragmentationGpu()
|
||||||
{
|
{
|
||||||
bufCreateInfo.size = align_up(rand.Generate() % (bufSizeMax - bufSizeMin) + bufSizeMin, 32ull);
|
bufCreateInfo.size = align_up(rand.Generate() % (bufSizeMax - bufSizeMin) + bufSizeMin, 32ull);
|
||||||
|
|
||||||
|
AllocInfo alloc;
|
||||||
|
|
||||||
if(rand.Generate() % 100 < percentNonMovable)
|
if(rand.Generate() % 100 < percentNonMovable)
|
||||||
{
|
{
|
||||||
bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
allocCreateInfo.pUserData = (void*)(uintptr_t)2;
|
alloc.m_DefragmentationMovable = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2566,10 +2578,8 @@ static void TestDefragmentationGpu()
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
// And in JSON dump.
|
// And in JSON dump.
|
||||||
allocCreateInfo.pUserData = (void*)(uintptr_t)1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocInfo alloc;
|
|
||||||
alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
|
alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
|
||||||
alloc.m_StartValue = rand.Generate();
|
alloc.m_StartValue = rand.Generate();
|
||||||
allocations.push_back(alloc);
|
allocations.push_back(alloc);
|
||||||
|
@ -2599,38 +2609,10 @@ static void TestDefragmentationGpu()
|
||||||
|
|
||||||
// Defragment using GPU only.
|
// Defragment using GPU only.
|
||||||
{
|
{
|
||||||
const size_t allocCount = allocations.size();
|
|
||||||
|
|
||||||
std::vector<VmaAllocation> allocationPtrs;
|
|
||||||
std::vector<VkBool32> allocationChanged;
|
|
||||||
std::vector<size_t> allocationOriginalIndex;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < allocCount; ++i)
|
|
||||||
{
|
|
||||||
VmaAllocationInfo allocInfo = {};
|
|
||||||
vmaGetAllocationInfo(g_hAllocator, allocations[i].m_Allocation, &allocInfo);
|
|
||||||
if((uintptr_t)allocInfo.pUserData == 1) // Movable
|
|
||||||
{
|
|
||||||
allocationPtrs.push_back(allocations[i].m_Allocation);
|
|
||||||
allocationChanged.push_back(VK_FALSE);
|
|
||||||
allocationOriginalIndex.push_back(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t movableAllocCount = allocationPtrs.size();
|
|
||||||
|
|
||||||
VmaDefragmentationInfo defragInfo = {};
|
VmaDefragmentationInfo defragInfo = {};
|
||||||
VmaDefragmentationStats stats;
|
VmaDefragmentationStats stats;
|
||||||
Defragment(defragInfo, &stats);
|
Defragment(defragInfo, &stats);
|
||||||
|
PrintDefragmentationStats(stats);
|
||||||
for(size_t i = 0; i < movableAllocCount; ++i)
|
|
||||||
{
|
|
||||||
if(allocationChanged[i])
|
|
||||||
{
|
|
||||||
const size_t origAllocIndex = allocationOriginalIndex[i];
|
|
||||||
RecreateAllocationResource(allocations[origAllocIndex]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If corruption detection is enabled, GPU defragmentation may not work on
|
// If corruption detection is enabled, GPU defragmentation may not work on
|
||||||
// memory types that have this detection active, e.g. on Intel.
|
// memory types that have this detection active, e.g. on Intel.
|
||||||
|
@ -2749,6 +2731,8 @@ static void TestDefragmentationIncrementalBasic()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while ((res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &pass)) == VK_INCOMPLETE)
|
while ((res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
// Ignore data outside of test
|
// Ignore data outside of test
|
||||||
for (uint32_t i = 0; i < pass.moveCount; ++i)
|
for (uint32_t i = 0; i < pass.moveCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2890,11 +2874,9 @@ void TestDefragmentationIncrementalComplex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// Set our user data pointers. A real application should probably be more clever here
|
||||||
// Set our user data pointers. A real application should probably be more clever here
|
for (auto& alloc : allocations)
|
||||||
for (auto& alloc : allocations)
|
vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
|
||||||
vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill them with meaningful data.
|
// Fill them with meaningful data.
|
||||||
UploadGpuData(allocations.data(), allocations.size());
|
UploadGpuData(allocations.data(), allocations.size());
|
||||||
|
@ -2936,19 +2918,9 @@ void TestDefragmentationIncrementalComplex()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while((res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &pass)) == VK_INCOMPLETE)
|
while((res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
makeAdditionalAllocation();
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
// Ignore data outside of test
|
makeAdditionalAllocation();
|
||||||
for (uint32_t i = 0; i < pass.moveCount; ++i)
|
|
||||||
{
|
|
||||||
auto it = std::find_if(allocations.begin(), allocations.end(), [&](const AllocInfo& info) { return pass.pMoves[i].srcAllocation == info.m_Allocation; });
|
|
||||||
if (it == allocations.end())
|
|
||||||
{
|
|
||||||
auto it = std::find_if(additionalAllocations.begin(), additionalAllocations.end(), [&](const AllocInfo& info) { return pass.pMoves[i].srcAllocation == info.m_Allocation; });
|
|
||||||
if (it == additionalAllocations.end())
|
|
||||||
pass.pMoves[i].operation = VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginSingleTimeCommands();
|
BeginSingleTimeCommands();
|
||||||
ProcessDefragmentationPass(pass);
|
ProcessDefragmentationPass(pass);
|
||||||
|
@ -5373,6 +5345,8 @@ static void TestPool_SameSize()
|
||||||
VmaDefragmentationPassMoveInfo pass = {};
|
VmaDefragmentationPassMoveInfo pass = {};
|
||||||
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
while ((res = vmaBeginDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
|
wprintf(L" Pass: moveCount=%u\n", pass.moveCount);
|
||||||
|
|
||||||
if ((res = vmaEndDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_SUCCESS)
|
if ((res = vmaEndDefragmentationPass(g_hAllocator, defragCtx, &pass)) == VK_SUCCESS)
|
||||||
break;
|
break;
|
||||||
TEST(res == VK_INCOMPLETE);
|
TEST(res == VK_INCOMPLETE);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue