1 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // VulkanCommandBufferPerf:
6 // Performance benchmark for Vulkan Primary/Secondary Command Buffer implementations.
7 // Can run just these tests by adding "--gtest_filter=VulkanCommandBufferPerfTest*"
8 // option to angle_white_box_perftests.
9 // When running on Android with run_angle_white_box_perftests, use "-v" option.
10
11 #include "ANGLEPerfTest.h"
12 #include "common/platform.h"
13 #include "test_utils/third_party/vulkan_command_buffer_utils.h"
14
15 #if defined(ANDROID)
16 # define NUM_CMD_BUFFERS 1000
17 // Android devices tend to be slower so only do 10 frames to avoid timeout
18 # define NUM_FRAMES 10
19 #else
20 # define NUM_CMD_BUFFERS 1000
21 # define NUM_FRAMES 100
22 #endif
23
24 // These are minimal shaders used to submit trivial draw commands to command
25 // buffers so that we can create large batches of cmd buffers with consistent
26 // draw patterns but size/type of cmd buffers can be varied to test cmd buffer
27 // differences across devices.
28 constexpr char kVertShaderText[] = R"(
29 #version 400
30 #extension GL_ARB_separate_shader_objects : enable
31 #extension GL_ARB_shading_language_420pack : enable
32 layout (std140, binding = 0) uniform bufferVals {
33 mat4 mvp;
34 } myBufferVals;
35 layout (location = 0) in vec4 pos;
36 layout (location = 1) in vec4 inColor;
37 layout (location = 0) out vec4 outColor;
38 void main() {
39 outColor = inColor;
40 gl_Position = myBufferVals.mvp * pos;
41 })";
42
43 constexpr char kFragShaderText[] = R"(
44 #version 400
45 #extension GL_ARB_separate_shader_objects : enable
46 #extension GL_ARB_shading_language_420pack : enable
47 layout (location = 0) in vec4 color;
48 layout (location = 0) out vec4 outColor;
49 void main() {
50 outColor = color;
51 })";
52
53 using CommandBufferImpl = void (*)(sample_info &info,
54 VkClearValue *clear_values,
55 VkFence drawFence,
56 VkSemaphore imageAcquiredSemaphore,
57 int numBuffers);
58
59 struct CommandBufferTestParams
60 {
61 CommandBufferImpl CBImplementation;
62 std::string story;
63 int frames = NUM_FRAMES;
64 int buffers = NUM_CMD_BUFFERS;
65 };
66
67 class VulkanCommandBufferPerfTest : public ANGLEPerfTest,
68 public ::testing::WithParamInterface<CommandBufferTestParams>
69 {
70 public:
71 VulkanCommandBufferPerfTest();
72
73 void SetUp() override;
74 void TearDown() override;
75 void step() override;
76
77 private:
78 VkClearValue mClearValues[2] = {};
79 VkSemaphore mImageAcquiredSemaphore = VK_NULL_HANDLE;
80 VkFence mDrawFence = VK_NULL_HANDLE;
81
82 VkResult res = VK_NOT_READY;
83 const bool mDepthPresent = true;
84 struct sample_info mInfo = {};
85 std::string mSampleTitle;
86 CommandBufferImpl mCBImplementation = nullptr;
87 int mFrames = 0;
88 int mBuffers = 0;
89 };
90
VulkanCommandBufferPerfTest()91 VulkanCommandBufferPerfTest::VulkanCommandBufferPerfTest()
92 : ANGLEPerfTest("VulkanCommandBufferPerfTest", "", GetParam().story, GetParam().frames)
93 {
94 mInfo = {};
95 mSampleTitle = "Draw Textured Cube";
96 mCBImplementation = GetParam().CBImplementation;
97 mFrames = GetParam().frames;
98 mBuffers = GetParam().buffers;
99 }
100
SetUp()101 void VulkanCommandBufferPerfTest::SetUp()
102 {
103 ANGLEPerfTest::SetUp();
104
105 init_global_layer_properties(mInfo);
106 init_instance_extension_names(mInfo);
107 init_device_extension_names(mInfo);
108 init_instance(mInfo, mSampleTitle.c_str());
109 init_enumerate_device(mInfo);
110 init_window_size(mInfo, 500, 500);
111 init_connection(mInfo);
112 init_window(mInfo);
113 init_swapchain_extension(mInfo);
114 init_device(mInfo);
115
116 init_command_pool(mInfo, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
117 init_command_buffer(mInfo); // Primary command buffer to hold secondaries
118 init_command_buffer_array(mInfo, mBuffers); // Array of primary command buffers
119 init_command_buffer2_array(mInfo, mBuffers); // Array containing all secondary buffers
120 init_device_queue(mInfo);
121 init_swap_chain(mInfo);
122 init_depth_buffer(mInfo);
123 init_uniform_buffer(mInfo);
124 init_descriptor_and_pipeline_layouts(mInfo, false);
125 init_renderpass(mInfo, mDepthPresent);
126 init_shaders(mInfo, kVertShaderText, kFragShaderText);
127 init_framebuffers(mInfo, mDepthPresent);
128 init_vertex_buffer(mInfo, g_vb_solid_face_colors_Data, sizeof(g_vb_solid_face_colors_Data),
129 sizeof(g_vb_solid_face_colors_Data[0]), false);
130 init_descriptor_pool(mInfo, false);
131 init_descriptor_set(mInfo);
132 init_pipeline_cache(mInfo);
133 init_pipeline(mInfo, mDepthPresent);
134
135 mClearValues[0].color.float32[0] = 0.2f;
136 mClearValues[0].color.float32[1] = 0.2f;
137 mClearValues[0].color.float32[2] = 0.2f;
138 mClearValues[0].color.float32[3] = 0.2f;
139 mClearValues[1].depthStencil.depth = 1.0f;
140 mClearValues[1].depthStencil.stencil = 0;
141
142 VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
143 imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
144 imageAcquiredSemaphoreCreateInfo.pNext = NULL;
145 imageAcquiredSemaphoreCreateInfo.flags = 0;
146 res = vkCreateSemaphore(mInfo.device, &imageAcquiredSemaphoreCreateInfo, NULL,
147 &mImageAcquiredSemaphore);
148 ASSERT_EQ(VK_SUCCESS, res);
149
150 VkFenceCreateInfo fenceInfo;
151 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
152 fenceInfo.pNext = NULL;
153 fenceInfo.flags = 0;
154 res = vkCreateFence(mInfo.device, &fenceInfo, NULL, &mDrawFence);
155 ASSERT_EQ(VK_SUCCESS, res);
156 }
157
step()158 void VulkanCommandBufferPerfTest::step()
159 {
160 for (int x = 0; x < mFrames; x++)
161 {
162 mInfo.current_buffer = x % mInfo.swapchainImageCount;
163
164 // Get the index of the next available swapchain image:
165 res = vkAcquireNextImageKHR(mInfo.device, mInfo.swap_chain, UINT64_MAX,
166 mImageAcquiredSemaphore, VK_NULL_HANDLE, &mInfo.current_buffer);
167 // Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
168 // return codes
169 ASSERT_EQ(VK_SUCCESS, res);
170 mCBImplementation(mInfo, mClearValues, mDrawFence, mImageAcquiredSemaphore, mBuffers);
171 }
172 }
173
TearDown()174 void VulkanCommandBufferPerfTest::TearDown()
175 {
176 vkDestroySemaphore(mInfo.device, mImageAcquiredSemaphore, NULL);
177 vkDestroyFence(mInfo.device, mDrawFence, NULL);
178 destroy_pipeline(mInfo);
179 destroy_pipeline_cache(mInfo);
180 destroy_descriptor_pool(mInfo);
181 destroy_vertex_buffer(mInfo);
182 destroy_framebuffers(mInfo);
183 destroy_shaders(mInfo);
184 destroy_renderpass(mInfo);
185 destroy_descriptor_and_pipeline_layouts(mInfo);
186 destroy_uniform_buffer(mInfo);
187 destroy_depth_buffer(mInfo);
188 destroy_swap_chain(mInfo);
189 destroy_command_buffer2_array(mInfo, mBuffers);
190 destroy_command_buffer_array(mInfo, mBuffers);
191 destroy_command_buffer(mInfo);
192 destroy_command_pool(mInfo);
193 destroy_device(mInfo);
194 destroy_window(mInfo);
195 destroy_instance(mInfo);
196 ANGLEPerfTest::TearDown();
197 }
198
199 // Common code to present image used by all tests
Present(sample_info & info,VkFence drawFence)200 void Present(sample_info &info, VkFence drawFence)
201 {
202 // Now present the image in the window
203
204 VkPresentInfoKHR present;
205 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
206 present.pNext = NULL;
207 present.swapchainCount = 1;
208 present.pSwapchains = &info.swap_chain;
209 present.pImageIndices = &info.current_buffer;
210 present.pWaitSemaphores = NULL;
211 present.waitSemaphoreCount = 0;
212 present.pResults = NULL;
213
214 // Make sure command buffer is finished before presenting
215 VkResult res;
216 do
217 {
218 res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
219 } while (res == VK_TIMEOUT);
220 vkResetFences(info.device, 1, &drawFence);
221
222 ASSERT_EQ(VK_SUCCESS, res);
223 res = vkQueuePresentKHR(info.present_queue, &present);
224 ASSERT_EQ(VK_SUCCESS, res);
225 }
226
227 // 100 separate primary cmd buffers, each with 1 Draw
PrimaryCommandBufferBenchmarkHundredIndividual(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)228 void PrimaryCommandBufferBenchmarkHundredIndividual(sample_info &info,
229 VkClearValue *clear_values,
230 VkFence drawFence,
231 VkSemaphore imageAcquiredSemaphore,
232 int numBuffers)
233 {
234 VkResult res;
235
236 VkRenderPassBeginInfo rpBegin;
237 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
238 rpBegin.pNext = NULL;
239 rpBegin.renderPass = info.render_pass;
240 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
241 rpBegin.renderArea.offset.x = 0;
242 rpBegin.renderArea.offset.y = 0;
243 rpBegin.renderArea.extent.width = info.width;
244 rpBegin.renderArea.extent.height = info.height;
245 rpBegin.clearValueCount = 2;
246 rpBegin.pClearValues = clear_values;
247
248 VkCommandBufferBeginInfo cmdBufferInfo = {};
249 cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
250 cmdBufferInfo.pNext = NULL;
251 cmdBufferInfo.flags = 0;
252 cmdBufferInfo.pInheritanceInfo = NULL;
253
254 for (int x = 0; x < numBuffers; x++)
255 {
256 vkBeginCommandBuffer(info.cmds[x], &cmdBufferInfo);
257 vkCmdBeginRenderPass(info.cmds[x], &rpBegin, VK_SUBPASS_CONTENTS_INLINE);
258 vkCmdBindPipeline(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
259 vkCmdBindDescriptorSets(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout,
260 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL);
261
262 const VkDeviceSize offsets[1] = {0};
263 vkCmdBindVertexBuffers(info.cmds[x], 0, 1, &info.vertex_buffer.buf, offsets);
264
265 init_viewports_array(info, x);
266 init_scissors_array(info, x);
267
268 vkCmdDraw(info.cmds[x], 0, 1, 0, 0);
269 vkCmdEndRenderPass(info.cmds[x]);
270 res = vkEndCommandBuffer(info.cmds[x]);
271 ASSERT_EQ(VK_SUCCESS, res);
272 }
273
274 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
275 VkSubmitInfo submitInfo[1] = {};
276 submitInfo[0].pNext = NULL;
277 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
278 submitInfo[0].waitSemaphoreCount = 1;
279 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
280 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
281 submitInfo[0].commandBufferCount = numBuffers;
282 submitInfo[0].pCommandBuffers = info.cmds.data();
283 submitInfo[0].signalSemaphoreCount = 0;
284 submitInfo[0].pSignalSemaphores = NULL;
285
286 // Queue the command buffer for execution
287 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
288 ASSERT_EQ(VK_SUCCESS, res);
289
290 Present(info, drawFence);
291 }
292
293 // 100 of the same Draw cmds in the same primary cmd buffer
PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)294 void PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info &info,
295 VkClearValue *clear_values,
296 VkFence drawFence,
297 VkSemaphore imageAcquiredSemaphore,
298 int numBuffers)
299 {
300 VkResult res;
301
302 VkRenderPassBeginInfo rpBegin;
303 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
304 rpBegin.pNext = NULL;
305 rpBegin.renderPass = info.render_pass;
306 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
307 rpBegin.renderArea.offset.x = 0;
308 rpBegin.renderArea.offset.y = 0;
309 rpBegin.renderArea.extent.width = info.width;
310 rpBegin.renderArea.extent.height = info.height;
311 rpBegin.clearValueCount = 2;
312 rpBegin.pClearValues = clear_values;
313
314 VkCommandBufferBeginInfo cmdBufferInfo = {};
315 cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
316 cmdBufferInfo.pNext = NULL;
317 cmdBufferInfo.flags = 0;
318 cmdBufferInfo.pInheritanceInfo = NULL;
319
320 vkBeginCommandBuffer(info.cmd, &cmdBufferInfo);
321 for (int x = 0; x < numBuffers; x++)
322 {
323 vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_INLINE);
324 vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
325 vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0,
326 NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL);
327
328 const VkDeviceSize offsets[1] = {0};
329 vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);
330
331 init_viewports(info);
332 init_scissors(info);
333
334 vkCmdDraw(info.cmd, 0, 1, 0, 0);
335 vkCmdEndRenderPass(info.cmd);
336 }
337 res = vkEndCommandBuffer(info.cmd);
338 ASSERT_EQ(VK_SUCCESS, res);
339
340 const VkCommandBuffer cmd_bufs[] = {info.cmd};
341 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
342 VkSubmitInfo submitInfo[1] = {};
343 submitInfo[0].pNext = NULL;
344 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
345 submitInfo[0].waitSemaphoreCount = 1;
346 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
347 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
348 submitInfo[0].commandBufferCount = 1;
349 submitInfo[0].pCommandBuffers = cmd_bufs;
350 submitInfo[0].signalSemaphoreCount = 0;
351 submitInfo[0].pSignalSemaphores = NULL;
352
353 // Queue the command buffer for execution
354 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
355 ASSERT_EQ(VK_SUCCESS, res);
356
357 Present(info, drawFence);
358 }
359
360 // 100 separate secondary cmd buffers, each with 1 Draw
SecondaryCommandBufferBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)361 void SecondaryCommandBufferBenchmark(sample_info &info,
362 VkClearValue *clear_values,
363 VkFence drawFence,
364 VkSemaphore imageAcquiredSemaphore,
365 int numBuffers)
366 {
367 VkResult res;
368
369 // Record Secondary Command Buffer
370 VkCommandBufferInheritanceInfo inheritInfo = {};
371 inheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
372 inheritInfo.pNext = NULL;
373 inheritInfo.renderPass = info.render_pass;
374 inheritInfo.subpass = 0;
375 inheritInfo.framebuffer = info.framebuffers[info.current_buffer];
376 inheritInfo.occlusionQueryEnable = false;
377 inheritInfo.queryFlags = 0;
378 inheritInfo.pipelineStatistics = 0;
379
380 VkCommandBufferBeginInfo secondaryCommandBufferInfo = {};
381 secondaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
382 secondaryCommandBufferInfo.pNext = NULL;
383 secondaryCommandBufferInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT |
384 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
385 secondaryCommandBufferInfo.pInheritanceInfo = &inheritInfo;
386
387 for (int x = 0; x < numBuffers; x++)
388 {
389 vkBeginCommandBuffer(info.cmd2s[x], &secondaryCommandBufferInfo);
390 vkCmdBindPipeline(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
391 vkCmdBindDescriptorSets(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS,
392 info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(),
393 0, NULL);
394 const VkDeviceSize offsets[1] = {0};
395 vkCmdBindVertexBuffers(info.cmd2s[x], 0, 1, &info.vertex_buffer.buf, offsets);
396 init_viewports2_array(info, x);
397 init_scissors2_array(info, x);
398 vkCmdDraw(info.cmd2s[x], 0, 1, 0, 0);
399 vkEndCommandBuffer(info.cmd2s[x]);
400 }
401 // Record Secondary Command Buffer End
402
403 // Record Primary Command Buffer Begin
404 VkRenderPassBeginInfo rpBegin;
405 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
406 rpBegin.pNext = NULL;
407 rpBegin.renderPass = info.render_pass;
408 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
409 rpBegin.renderArea.offset.x = 0;
410 rpBegin.renderArea.offset.y = 0;
411 rpBegin.renderArea.extent.width = info.width;
412 rpBegin.renderArea.extent.height = info.height;
413 rpBegin.clearValueCount = 2;
414 rpBegin.pClearValues = clear_values;
415
416 VkCommandBufferBeginInfo primaryCommandBufferInfo = {};
417 primaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
418 primaryCommandBufferInfo.pNext = NULL;
419 primaryCommandBufferInfo.flags = 0;
420 primaryCommandBufferInfo.pInheritanceInfo = NULL;
421
422 vkBeginCommandBuffer(info.cmd, &primaryCommandBufferInfo);
423 for (int x = 0; x < numBuffers; x++)
424 {
425 vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
426 vkCmdExecuteCommands(info.cmd, 1, &info.cmd2s[x]);
427 vkCmdEndRenderPass(info.cmd);
428 }
429 vkEndCommandBuffer(info.cmd);
430 // Record Primary Command Buffer End
431
432 const VkCommandBuffer cmd_bufs[] = {info.cmd};
433 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
434 VkSubmitInfo submitInfo[1] = {};
435 submitInfo[0].pNext = NULL;
436 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
437 submitInfo[0].waitSemaphoreCount = 1;
438 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
439 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
440 submitInfo[0].commandBufferCount = 1;
441 submitInfo[0].pCommandBuffers = cmd_bufs;
442 submitInfo[0].signalSemaphoreCount = 0;
443 submitInfo[0].pSignalSemaphores = NULL;
444
445 // Queue the command buffer for execution
446 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
447 ASSERT_EQ(VK_SUCCESS, res);
448
449 Present(info, drawFence);
450 }
451
452 // Details on the following functions that stress various cmd buffer reset methods.
453 // All of these functions wrap the SecondaryCommandBufferBenchmark() test above,
454 // adding additional overhead with various reset methods.
455 // -CommandPoolDestroyBenchmark: Reset command buffers by destroying and re-creating
456 // command buffer pool.
457 // -CommandPoolHardResetBenchmark: Reset the command pool w/ the RELEASE_RESOURCES
458 // bit set.
459 // -CommandPoolSoftResetBenchmark: Reset to command pool w/o the RELEASE_RESOURCES
460 // bit set.
461 // -CommandBufferExplicitHardResetBenchmark: Reset each individual command buffer
462 // w/ the RELEASE_RESOURCES bit set.
463 // -CommandBufferExplicitSoftResetBenchmark: Reset each individual command buffer
464 // w/o the RELEASE_RESOURCES bit set.
465 // -CommandBufferImplicitResetBenchmark: Reset each individual command buffer
466 // implicitly by calling "Begin" on previously used cmd buffer.
467
CommandPoolDestroyBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)468 void CommandPoolDestroyBenchmark(sample_info &info,
469 VkClearValue *clear_values,
470 VkFence drawFence,
471 VkSemaphore imageAcquiredSemaphore,
472 int numBuffers)
473 {
474 // Save setup cmd buffer data to be restored
475 auto saved_cmd_pool = info.cmd_pool;
476 auto saved_cb = info.cmd;
477 auto saved_cb2s = info.cmd2s;
478 // Now re-allocate & destroy cmd buffers to stress those calls
479 init_command_pool(info, 0);
480 init_command_buffer2_array(info, numBuffers);
481
482 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
483 numBuffers);
484
485 destroy_command_pool(info);
486
487 // Restore original cmd buffer data for cleanup
488 info.cmd_pool = saved_cmd_pool;
489 info.cmd = saved_cb;
490 info.cmd2s = saved_cb2s;
491 }
492
CommandPoolHardResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)493 void CommandPoolHardResetBenchmark(sample_info &info,
494 VkClearValue *clear_values,
495 VkFence drawFence,
496 VkSemaphore imageAcquiredSemaphore,
497 int numBuffers)
498 {
499 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
500 numBuffers);
501 reset_command_pool(info, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
502 }
503
CommandPoolSoftResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)504 void CommandPoolSoftResetBenchmark(sample_info &info,
505 VkClearValue *clear_values,
506 VkFence drawFence,
507 VkSemaphore imageAcquiredSemaphore,
508 int numBuffers)
509 {
510 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
511 numBuffers);
512 reset_command_pool(info, 0);
513 }
514
CommandBufferExplicitHardResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)515 void CommandBufferExplicitHardResetBenchmark(sample_info &info,
516 VkClearValue *clear_values,
517 VkFence drawFence,
518 VkSemaphore imageAcquiredSemaphore,
519 int numBuffers)
520 {
521 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
522 numBuffers);
523 // Explicitly resetting cmd buffers
524 reset_command_buffer2_array(info, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
525 }
526
CommandBufferExplicitSoftResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)527 void CommandBufferExplicitSoftResetBenchmark(sample_info &info,
528 VkClearValue *clear_values,
529 VkFence drawFence,
530 VkSemaphore imageAcquiredSemaphore,
531 int numBuffers)
532 {
533 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
534 numBuffers);
535 // Explicitly resetting cmd buffers w/ soft reset (don't release resources)
536 reset_command_buffer2_array(info, 0);
537 }
538
CommandBufferImplicitResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)539 void CommandBufferImplicitResetBenchmark(sample_info &info,
540 VkClearValue *clear_values,
541 VkFence drawFence,
542 VkSemaphore imageAcquiredSemaphore,
543 int numBuffers)
544 {
545 // Repeated call SCBBenchmark & BeginCmdBuffer calls will implicitly reset each cmd buffer
546 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
547 numBuffers);
548 }
549
PrimaryCBHundredIndividualParams()550 CommandBufferTestParams PrimaryCBHundredIndividualParams()
551 {
552 CommandBufferTestParams params;
553 params.CBImplementation = PrimaryCommandBufferBenchmarkHundredIndividual;
554 params.story = "_PrimaryCB_Submit_100_With_1_Draw";
555 return params;
556 }
557
PrimaryCBOneWithOneHundredParams()558 CommandBufferTestParams PrimaryCBOneWithOneHundredParams()
559 {
560 CommandBufferTestParams params;
561 params.CBImplementation = PrimaryCommandBufferBenchmarkOneWithOneHundred;
562 params.story = "_PrimaryCB_Submit_1_With_100_Draw";
563 return params;
564 }
565
SecondaryCBParams()566 CommandBufferTestParams SecondaryCBParams()
567 {
568 CommandBufferTestParams params;
569 params.CBImplementation = SecondaryCommandBufferBenchmark;
570 params.story = "_SecondaryCB_Submit_1_With_100_Draw_In_Individual_Secondary";
571 return params;
572 }
573
CommandPoolDestroyParams()574 CommandBufferTestParams CommandPoolDestroyParams()
575 {
576 CommandBufferTestParams params;
577 params.CBImplementation = CommandPoolDestroyBenchmark;
578 params.story = "_Reset_CBs_With_Destroy_Command_Pool";
579 return params;
580 }
581
CommandPoolHardResetParams()582 CommandBufferTestParams CommandPoolHardResetParams()
583 {
584 CommandBufferTestParams params;
585 params.CBImplementation = CommandPoolHardResetBenchmark;
586 params.story = "_Reset_CBs_With_Hard_Reset_Command_Pool";
587 return params;
588 }
589
CommandPoolSoftResetParams()590 CommandBufferTestParams CommandPoolSoftResetParams()
591 {
592 CommandBufferTestParams params;
593 params.CBImplementation = CommandPoolSoftResetBenchmark;
594 params.story = "_Reset_CBs_With_Soft_Reset_Command_Pool";
595 return params;
596 }
597
CommandBufferExplicitHardResetParams()598 CommandBufferTestParams CommandBufferExplicitHardResetParams()
599 {
600 CommandBufferTestParams params;
601 params.CBImplementation = CommandBufferExplicitHardResetBenchmark;
602 params.story = "_Reset_CBs_With_Explicit_Hard_Reset_Command_Buffers";
603 return params;
604 }
605
CommandBufferExplicitSoftResetParams()606 CommandBufferTestParams CommandBufferExplicitSoftResetParams()
607 {
608 CommandBufferTestParams params;
609 params.CBImplementation = CommandBufferExplicitSoftResetBenchmark;
610 params.story = "_Reset_CBs_With_Explicit_Soft_Reset_Command_Buffers";
611 return params;
612 }
613
CommandBufferImplicitResetParams()614 CommandBufferTestParams CommandBufferImplicitResetParams()
615 {
616 CommandBufferTestParams params;
617 params.CBImplementation = CommandBufferImplicitResetBenchmark;
618 params.story = "_Reset_CBs_With_Implicit_Reset_Command_Buffers";
619 return params;
620 }
621
TEST_P(VulkanCommandBufferPerfTest,Run)622 TEST_P(VulkanCommandBufferPerfTest, Run)
623 {
624 run();
625 }
626
627 INSTANTIATE_TEST_SUITE_P(,
628 VulkanCommandBufferPerfTest,
629 ::testing::Values(PrimaryCBHundredIndividualParams(),
630 PrimaryCBOneWithOneHundredParams(),
631 SecondaryCBParams(),
632 CommandPoolDestroyParams(),
633 CommandPoolHardResetParams(),
634 CommandPoolSoftResetParams(),
635 CommandBufferExplicitHardResetParams(),
636 CommandBufferExplicitSoftResetParams(),
637 CommandBufferImplicitResetParams()));
638