Skip to content

Commit 1c0c221

Browse files
committed
Add new tests for advanced data uploading
1 parent 811773f commit 1c0c221

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed

src/Tests.cpp

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6153,6 +6153,264 @@ static void TestMemoryUsage()
61536153
}
61546154
}
61556155

6156+
static void TestDataUploadingWithStagingBuffer()
6157+
{
6158+
wprintf(L"Testing data uploading with staging buffer...\n");
6159+
6160+
// Generate some random data to fill the uniform buffer with.
6161+
const VkDeviceSize bufferSize = 65536;
6162+
std::vector<std::uint8_t> bufferData(bufferSize);
6163+
for (auto& bufferByte : bufferData) {
6164+
bufferByte = static_cast<std::uint8_t>(rand() % 256);
6165+
}
6166+
6167+
VkBufferCreateInfo uniformBufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
6168+
uniformBufferCI.size = bufferSize;
6169+
uniformBufferCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change this if you want to create another type of buffer.
6170+
6171+
VmaAllocationCreateInfo uniformBufferAllocCI = {};
6172+
uniformBufferAllocCI.usage = VMA_MEMORY_USAGE_AUTO;
6173+
uniformBufferAllocCI.flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
6174+
6175+
VkBuffer uniformBuffer = VK_NULL_HANDLE;
6176+
VmaAllocation uniformBufferAlloc = {};
6177+
VmaAllocationInfo uniformBufferAllocInfo = {};
6178+
6179+
VkResult result = vmaCreateBuffer(g_hAllocator, &uniformBufferCI, &uniformBufferAllocCI, &uniformBuffer, &uniformBufferAlloc, &uniformBufferAllocInfo);
6180+
TEST(result == VK_SUCCESS);
6181+
6182+
// We need to check if the uniform buffer really ended NOT up in mappable memory.
6183+
VkMemoryPropertyFlags memPropFlags;
6184+
vmaGetAllocationMemoryProperties(g_hAllocator, uniformBufferAlloc, &memPropFlags);
6185+
TEST(!(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
6186+
6187+
VkBufferCreateInfo stagingBufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
6188+
stagingBufferCI.size = bufferSize;
6189+
stagingBufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
6190+
6191+
VmaAllocationCreateInfo stagingBufferAllocCI = {};
6192+
stagingBufferAllocCI.usage = VMA_MEMORY_USAGE_AUTO;
6193+
stagingBufferAllocCI.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
6194+
6195+
VkBuffer stagingBuffer = VK_NULL_HANDLE;
6196+
VmaAllocation stagingBufferAlloc = {};
6197+
VmaAllocationInfo stagingBufferAllocInfo = {};
6198+
6199+
result = vmaCreateBuffer(g_hAllocator, &stagingBufferCI, &stagingBufferAllocCI, &stagingBuffer, &stagingBufferAlloc, &stagingBufferAllocInfo);
6200+
TEST(result == VK_SUCCESS);
6201+
6202+
TEST(stagingBufferAllocInfo.pMappedData != nullptr);
6203+
std::memcpy(stagingBufferAllocInfo.pMappedData, bufferData.data(), bufferData.size());
6204+
6205+
result = vmaFlushAllocation(g_hAllocator, uniformBufferAlloc, 0, VK_WHOLE_SIZE);
6206+
TEST(result == VK_SUCCESS);
6207+
6208+
BeginSingleTimeCommands();
6209+
6210+
VkBufferMemoryBarrier bufferMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6211+
bufferMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
6212+
bufferMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
6213+
bufferMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6214+
bufferMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6215+
bufferMemBarrier.buffer = stagingBuffer;
6216+
bufferMemBarrier.offset = 0;
6217+
bufferMemBarrier.size = VK_WHOLE_SIZE;
6218+
6219+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier, 0, nullptr);
6220+
6221+
VkBufferCopy bufferCopy = {};
6222+
bufferCopy.srcOffset = 0;
6223+
bufferCopy.dstOffset = 0;
6224+
bufferCopy.size = bufferSize;
6225+
6226+
vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingBuffer, uniformBuffer, 1, &bufferCopy);
6227+
6228+
VkBufferMemoryBarrier bufferMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6229+
bufferMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
6230+
bufferMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // Change this if you want to create another type of buffer.
6231+
bufferMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6232+
bufferMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6233+
bufferMemBarrier2.buffer = uniformBuffer;
6234+
bufferMemBarrier2.offset = 0;
6235+
bufferMemBarrier2.size = VK_WHOLE_SIZE;
6236+
6237+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier2, 0, nullptr);
6238+
6239+
EndSingleTimeCommands();
6240+
6241+
vmaDestroyBuffer(g_hAllocator, stagingBuffer, stagingBufferAlloc);
6242+
vmaDestroyBuffer(g_hAllocator, uniformBuffer, uniformBufferAlloc);
6243+
}
6244+
6245+
static void TestDataUploadingWithMappedMemory() {
6246+
wprintf(L"Testing data uploading with mapped memory and memcpy...\n");
6247+
6248+
// Generate some random data to fill the uniform buffer with.
6249+
const VkDeviceSize bufferSize = 65536;
6250+
std::vector<std::uint8_t> bufferData(bufferSize);
6251+
for (auto& bufferByte : bufferData) {
6252+
bufferByte = static_cast<std::uint8_t>(rand() % 256);
6253+
}
6254+
6255+
VkBufferCreateInfo uniformBufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
6256+
uniformBufferCI.size = bufferSize;
6257+
uniformBufferCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; // Change this if you want to create another type of buffer.
6258+
6259+
VmaAllocationCreateInfo uniformBufferAllocCI = {};
6260+
uniformBufferAllocCI.usage = VMA_MEMORY_USAGE_AUTO;
6261+
uniformBufferAllocCI.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; // We want memory to be mapped so we can use memcpy to update it
6262+
6263+
VkBuffer uniformBuffer = VK_NULL_HANDLE;
6264+
VmaAllocation uniformBufferAlloc = {};
6265+
VmaAllocationInfo uniformBufferAllocInfo = {};
6266+
6267+
VkResult result = vmaCreateBuffer(g_hAllocator, &uniformBufferCI, &uniformBufferAllocCI, &uniformBuffer, &uniformBufferAlloc, &uniformBufferAllocInfo);
6268+
TEST(result == VK_SUCCESS);
6269+
6270+
// We need to check if the uniform buffer really ended up in mappable memory.
6271+
VkMemoryPropertyFlags memPropFlags;
6272+
vmaGetAllocationMemoryProperties(g_hAllocator, uniformBufferAlloc, &memPropFlags);
6273+
TEST(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
6274+
6275+
TEST(uniformBufferAllocInfo.pMappedData != nullptr);
6276+
std::memcpy(uniformBufferAllocInfo.pMappedData, bufferData.data(), bufferData.size());
6277+
6278+
// We don't need to check for VK_MEMORY_PROPERTY_HOST_COHERENT_BIT because both vmaFlushAllocation and vmaInvalidateAllocation check for this internally.
6279+
result = vmaFlushAllocation(g_hAllocator, uniformBufferAlloc, 0, VK_WHOLE_SIZE);
6280+
TEST(result == VK_SUCCESS);
6281+
6282+
BeginSingleTimeCommands();
6283+
6284+
VkBufferMemoryBarrier bufferMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6285+
bufferMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
6286+
bufferMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // Change this if you want to create another type of buffer.
6287+
bufferMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6288+
bufferMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6289+
bufferMemBarrier.buffer = uniformBuffer;
6290+
bufferMemBarrier.offset = 0;
6291+
bufferMemBarrier.size = VK_WHOLE_SIZE;
6292+
6293+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier, 0, nullptr);
6294+
6295+
EndSingleTimeCommands();
6296+
6297+
vmaDestroyBuffer(g_hAllocator, uniformBuffer, uniformBufferAlloc);
6298+
}
6299+
6300+
static void TestAdvancedDataUploading() {
6301+
wprintf(L"Testing advanced data uploading...\n");
6302+
6303+
// Generate some random data to fill the uniform buffer with.
6304+
const VkDeviceSize bufferSize = 65536;
6305+
std::vector<std::uint8_t> bufferData(bufferSize);
6306+
for (auto& bufferByte : bufferData) {
6307+
bufferByte = static_cast<std::uint8_t>(rand() % 256);
6308+
}
6309+
6310+
VkBufferCreateInfo uniformBufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
6311+
uniformBufferCI.size = bufferSize;
6312+
uniformBufferCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change this if you want to create another type of buffer.
6313+
6314+
VmaAllocationCreateInfo uniformBufferAllocCI = {};
6315+
uniformBufferAllocCI.usage = VMA_MEMORY_USAGE_AUTO;
6316+
uniformBufferAllocCI.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
6317+
6318+
VkBuffer uniformBuffer = VK_NULL_HANDLE;
6319+
VmaAllocation uniformBufferAlloc = {};
6320+
VmaAllocationInfo uniformBufferAllocInfo = {};
6321+
6322+
VkResult result = vmaCreateBuffer(g_hAllocator, &uniformBufferCI, &uniformBufferAllocCI, &uniformBuffer, &uniformBufferAlloc, &uniformBufferAllocInfo);
6323+
TEST(result == VK_SUCCESS);
6324+
6325+
VkMemoryPropertyFlags memPropFlags;
6326+
vmaGetAllocationMemoryProperties(g_hAllocator, uniformBufferAlloc, &memPropFlags);
6327+
6328+
if (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
6329+
// The allocation ended up as mapped memory, meaning we can update it simply by using std::memcpy.
6330+
TEST(uniformBufferAllocInfo.pMappedData != nullptr);
6331+
std::memcpy(uniformBufferAllocInfo.pMappedData, bufferData.data(), bufferData.size());
6332+
6333+
// We don't need to check for VK_MEMORY_PROPERTY_HOST_COHERENT_BIT because both vmaFlushAllocation and vmaInvalidateAllocation check for this internally.
6334+
result = vmaFlushAllocation(g_hAllocator, uniformBufferAlloc, 0, VK_WHOLE_SIZE);
6335+
TEST(result == VK_SUCCESS);
6336+
6337+
BeginSingleTimeCommands();
6338+
6339+
VkBufferMemoryBarrier bufferMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6340+
bufferMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
6341+
bufferMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // Change this if you want to create another type of buffer.
6342+
bufferMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6343+
bufferMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6344+
bufferMemBarrier.buffer = uniformBuffer;
6345+
bufferMemBarrier.offset = 0;
6346+
bufferMemBarrier.size = VK_WHOLE_SIZE;
6347+
6348+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier, 0, nullptr);
6349+
6350+
EndSingleTimeCommands();
6351+
}
6352+
else {
6353+
// The allocation did not end up in mapped memory, so we need a staging buffer and a copy operation to update it.
6354+
VkBufferCreateInfo stagingBufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
6355+
stagingBufferCI.size = bufferSize;
6356+
stagingBufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
6357+
6358+
VmaAllocationCreateInfo stagingBufferAllocCI = {};
6359+
stagingBufferAllocCI.usage = VMA_MEMORY_USAGE_AUTO;
6360+
stagingBufferAllocCI.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
6361+
6362+
VkBuffer stagingBuffer = VK_NULL_HANDLE;
6363+
VmaAllocation stagingBufferAlloc = {};
6364+
VmaAllocationInfo stagingBufferAllocInfo = {};
6365+
6366+
result = vmaCreateBuffer(g_hAllocator, &stagingBufferCI, &stagingBufferAllocCI, &stagingBuffer, &stagingBufferAlloc, &stagingBufferAllocInfo);
6367+
TEST(result == VK_SUCCESS);
6368+
6369+
TEST(stagingBufferAllocInfo.pMappedData != nullptr);
6370+
std::memcpy(stagingBufferAllocInfo.pMappedData, bufferData.data(), bufferData.size());
6371+
6372+
result = vmaFlushAllocation(g_hAllocator, uniformBufferAlloc, 0, VK_WHOLE_SIZE);
6373+
TEST(result == VK_SUCCESS);
6374+
6375+
BeginSingleTimeCommands();
6376+
6377+
VkBufferMemoryBarrier bufferMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6378+
bufferMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
6379+
bufferMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
6380+
bufferMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6381+
bufferMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6382+
bufferMemBarrier.buffer = stagingBuffer;
6383+
bufferMemBarrier.offset = 0;
6384+
bufferMemBarrier.size = VK_WHOLE_SIZE;
6385+
6386+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier, 0, nullptr);
6387+
6388+
VkBufferCopy bufferCopy = {};
6389+
bufferCopy.srcOffset = 0;
6390+
bufferCopy.dstOffset = 0;
6391+
bufferCopy.size = bufferSize;
6392+
6393+
vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingBuffer, uniformBuffer, 1, &bufferCopy);
6394+
6395+
VkBufferMemoryBarrier bufferMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
6396+
bufferMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
6397+
bufferMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // Change this if you want to create another type of buffer.
6398+
bufferMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6399+
bufferMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
6400+
bufferMemBarrier2.buffer = uniformBuffer;
6401+
bufferMemBarrier2.offset = 0;
6402+
bufferMemBarrier2.size = VK_WHOLE_SIZE;
6403+
6404+
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &bufferMemBarrier2, 0, nullptr);
6405+
6406+
EndSingleTimeCommands();
6407+
6408+
vmaDestroyBuffer(g_hAllocator, stagingBuffer, stagingBufferAlloc);
6409+
}
6410+
6411+
vmaDestroyBuffer(g_hAllocator, uniformBuffer, uniformBufferAlloc);
6412+
}
6413+
61566414
static uint32_t FindDeviceCoherentMemoryTypeBits()
61576415
{
61586416
VkPhysicalDeviceMemoryProperties memProps;
@@ -8352,6 +8610,9 @@ void Test()
83528610
TestAllocationsInitialization();
83538611
#endif
83548612
TestMemoryUsage();
8613+
TestDataUploadingWithStagingBuffer();
8614+
TestDataUploadingWithMappedMemory();
8615+
TestAdvancedDataUploading();
83558616
TestDeviceCoherentMemory();
83568617
TestStatistics();
83578618
TestAliasing();

0 commit comments

Comments
 (0)