@@ -6153,6 +6153,264 @@ 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 () % 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
+
6156
6414
static uint32_t FindDeviceCoherentMemoryTypeBits ()
6157
6415
{
6158
6416
VkPhysicalDeviceMemoryProperties memProps;
@@ -8352,6 +8610,9 @@ void Test()
8352
8610
TestAllocationsInitialization ();
8353
8611
#endif
8354
8612
TestMemoryUsage ();
8613
+ TestDataUploadingWithStagingBuffer ();
8614
+ TestDataUploadingWithMappedMemory ();
8615
+ TestAdvancedDataUploading ();
8355
8616
TestDeviceCoherentMemory ();
8356
8617
TestStatistics ();
8357
8618
TestAliasing ();
0 commit comments