@@ -6153,6 +6153,248 @@ static void TestMemoryUsage()
6153
6153
}
6154
6154
}
6155
6155
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
+
6156
6398
static uint32_t FindDeviceCoherentMemoryTypeBits ()
6157
6399
{
6158
6400
VkPhysicalDeviceMemoryProperties memProps;
@@ -8352,6 +8594,9 @@ void Test()
8352
8594
TestAllocationsInitialization ();
8353
8595
#endif
8354
8596
TestMemoryUsage ();
8597
+ TestDataUploadingWithStagingBuffer ();
8598
+ TestDataUploadingWithMappedMemory ();
8599
+ TestAdvancedDataUploading ();
8355
8600
TestDeviceCoherentMemory ();
8356
8601
TestStatistics ();
8357
8602
TestAliasing ();
0 commit comments