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