Added TestDefragmentationGpu. Not passing - apparently there is some bug...
diff --git a/src/Common.h b/src/Common.h
index 0e32c78..714fa6a 100644
--- a/src/Common.h
+++ b/src/Common.h
@@ -57,6 +57,11 @@
{
return (x+y-1) / y;
}
+template <typename T>
+inline T round_div(T x, T y)
+{
+ return (x+y/(T)2) / y;
+}
template <typename T>
static inline T align_up(T val, T align)
diff --git a/src/Tests.cpp b/src/Tests.cpp
index a512b95..cbf15b6 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -649,17 +649,47 @@
struct AllocInfo
{
- VmaAllocation m_Allocation;
- VkBuffer m_Buffer;
- VkImage m_Image;
- uint32_t m_StartValue;
+ VmaAllocation m_Allocation = VK_NULL_HANDLE;
+ VkBuffer m_Buffer = VK_NULL_HANDLE;
+ VkImage m_Image = VK_NULL_HANDLE;
+ uint32_t m_StartValue = 0;
union
{
VkBufferCreateInfo m_BufferInfo;
VkImageCreateInfo m_ImageInfo;
};
+
+ void CreateBuffer(
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo);
+ void Destroy();
};
+void AllocInfo::CreateBuffer(
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo)
+{
+ m_BufferInfo = bufCreateInfo;
+ VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &m_Buffer, &m_Allocation, nullptr);
+ TEST(res == VK_SUCCESS);
+}
+
+void AllocInfo::Destroy()
+{
+ if(m_Image)
+ {
+ vkDestroyImage(g_hDevice, m_Image, nullptr);
+ }
+ if(m_Buffer)
+ {
+ vkDestroyBuffer(g_hDevice, m_Buffer, nullptr);
+ }
+ if(m_Allocation)
+ {
+ vmaFreeMemory(g_hAllocator, m_Allocation);
+ }
+}
+
class StagingBufferCollection
{
public:
@@ -997,7 +1027,7 @@
}
}
-static void CreateAllocation(AllocInfo& outAllocation, VmaAllocator allocator)
+static void CreateAllocation(AllocInfo& outAllocation)
{
outAllocation.m_Allocation = nullptr;
outAllocation.m_Buffer = nullptr;
@@ -1021,7 +1051,7 @@
bufferInfo.size = bufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- VkResult res = vmaCreateBuffer(allocator, &bufferInfo, &vmaMemReq, &outAllocation.m_Buffer, &outAllocation.m_Allocation, &allocInfo);
+ VkResult res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &vmaMemReq, &outAllocation.m_Buffer, &outAllocation.m_Allocation, &allocInfo);
outAllocation.m_BufferInfo = bufferInfo;
TEST(res == VK_SUCCESS);
}
@@ -1047,7 +1077,7 @@
imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
- VkResult res = vmaCreateImage(allocator, &imageInfo, &vmaMemReq, &outAllocation.m_Image, &outAllocation.m_Allocation, &allocInfo);
+ VkResult res = vmaCreateImage(g_hAllocator, &imageInfo, &vmaMemReq, &outAllocation.m_Image, &outAllocation.m_Allocation, &allocInfo);
outAllocation.m_ImageInfo = imageInfo;
TEST(res == VK_SUCCESS);
}
@@ -1055,7 +1085,7 @@
uint32_t* data = (uint32_t*)allocInfo.pMappedData;
if(allocInfo.pMappedData == nullptr)
{
- VkResult res = vmaMapMemory(allocator, outAllocation.m_Allocation, (void**)&data);
+ VkResult res = vmaMapMemory(g_hAllocator, outAllocation.m_Allocation, (void**)&data);
TEST(res == VK_SUCCESS);
}
@@ -1065,7 +1095,7 @@
data[i] = value++;
if(allocInfo.pMappedData == nullptr)
- vmaUnmapMemory(allocator, outAllocation.m_Allocation);
+ vmaUnmapMemory(g_hAllocator, outAllocation.m_Allocation);
}
static void DestroyAllocation(const AllocInfo& allocation)
@@ -1339,7 +1369,7 @@
for(size_t i = 0; i < 400; ++i)
{
AllocInfo allocation;
- CreateAllocation(allocation, g_hAllocator);
+ CreateAllocation(allocation);
allocations.push_back(allocation);
}
@@ -1415,6 +1445,106 @@
DestroyAllAllocations(allocations);
}
+static void TestDefragmentationGpu()
+{
+ wprintf(L"Test defragmentation GPU\n");
+
+ std::vector<AllocInfo> allocations;
+
+ // Create that many allocations to surely fill 3 new blocks of 256 MB.
+ const VkDeviceSize bufSize = 10ull * 1024 * 1024;
+ const VkDeviceSize totalSize = 3ull * 256 * 1024 * 1024;
+ const size_t bufCount = (size_t)(totalSize / bufSize);
+ const size_t percentToLeave = 20;
+ RandomNumberGenerator rand = { 234522 };
+
+ VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufCreateInfo.size = bufSize;
+ bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ VmaAllocationCreateInfo allocCreateInfo = {};
+ allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
+ allocCreateInfo.pUserData = "TestDefragmentationGpu";
+
+ // Create all intended buffers.
+ for(size_t i = 0; i < bufCount; ++i)
+ {
+ AllocInfo alloc;
+ alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
+ alloc.m_StartValue = rand.Generate();
+ allocations.push_back(alloc);
+ }
+
+ // Destroy some percentage of them.
+ {
+ const size_t buffersToDestroy = round_div<size_t>(bufCount * (100 - percentToLeave), 100);
+ for(size_t i = 0; i < buffersToDestroy; ++i)
+ {
+ const size_t index = rand.Generate() % allocations.size();
+ allocations[index].Destroy();
+ allocations.erase(allocations.begin() + index);
+ }
+ }
+
+ // Fill them with meaningful data.
+ UploadGpuData(allocations.data(), allocations.size());
+
+ SaveAllocatorStatsToFile(L"GPU_defragmentation_A_before.json");
+
+ // Defragment using GPU only.
+ {
+ const size_t allocCount = allocations.size();
+ std::vector<VmaAllocation> allocationPtrs(allocCount);
+ std::vector<VkBool32> allocationChanged(allocCount);
+ for(size_t i = 0; i < allocCount; ++i)
+ {
+ allocationPtrs[i] = allocations[i].m_Allocation;
+ allocationChanged[i] = VK_FALSE;
+ }
+
+ BeginSingleTimeCommands();
+
+ VmaDefragmentationInfo2 defragInfo = {};
+ defragInfo.allocationCount = (uint32_t)allocCount;
+ defragInfo.pAllocations = allocationPtrs.data();
+ defragInfo.maxGpuBytesToMove = 0;//VK_WHOLE_SIZE;
+ defragInfo.maxGpuAllocationsToMove = UINT32_MAX;
+ defragInfo.commandBuffer = g_hTemporaryCommandBuffer;
+
+ VmaDefragmentationStats stats = {};
+ VmaDefragmentationContext ctx = VK_NULL_HANDLE;
+ VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &stats, &ctx);
+ TEST(res >= VK_SUCCESS);
+
+ EndSingleTimeCommands();
+
+ vmaDefragmentationEnd(g_hAllocator, ctx);
+
+ for(size_t i = 0; i < allocCount; ++i)
+ {
+ if(allocationChanged[i])
+ {
+ RecreateAllocationResource(allocations[i]);
+ }
+ }
+
+ //TEST(stats.allocationsMoved > 0 && stats.bytesMoved > 0);
+ //TEST(stats.deviceMemoryBlocksFreed > 0 && stats.bytesFreed > 0);
+ //TEST(stats.allocationsLost == 0);
+ }
+
+ ValidateGpuData(allocations.data(), allocations.size());
+
+ SaveAllocatorStatsToFile(L"GPU_defragmentation_B_after.json");
+
+ // Destroy all remaining buffers.
+ for(size_t i = allocations.size(); i--; )
+ {
+ allocations[i].Destroy();
+ }
+}
+
static void TestUserData()
{
VkResult res;
@@ -4555,8 +4685,9 @@
// ########################################
// ########################################
- //TestDefragmentationSimple();
- //TestDefragmentationFull();
+ TestDefragmentationGpu();
+ TestDefragmentationSimple();
+ TestDefragmentationFull();
return;
}
@@ -4591,6 +4722,7 @@
TestDefragmentationSimple();
TestDefragmentationFull();
+ TestDefragmentationGpu();
// # Detailed tests
FILE* file;