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 // This test appears to be flaky on multiple platforms.
101 #if !defined(ANGLE_PLATFORM_ANDROID)
102 // mSkipTest = true;
103 #endif // !defined(ANGLE_PLATFORM_ANDROID)
104 }
105
SetUp()106 void VulkanCommandBufferPerfTest::SetUp()
107 {
108 if (mSkipTest)
109 {
110 return;
111 }
112
113 init_global_layer_properties(mInfo);
114 init_instance_extension_names(mInfo);
115 init_device_extension_names(mInfo);
116 init_instance(mInfo, mSampleTitle.c_str());
117 init_enumerate_device(mInfo);
118 init_window_size(mInfo, 500, 500);
119 init_connection(mInfo);
120 init_window(mInfo);
121 init_swapchain_extension(mInfo);
122 init_device(mInfo);
123
124 init_command_pool(mInfo, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
125 init_command_buffer(mInfo); // Primary command buffer to hold secondaries
126 init_command_buffer_array(mInfo, mBuffers); // Array of primary command buffers
127 init_command_buffer2_array(mInfo, mBuffers); // Array containing all secondary buffers
128 init_device_queue(mInfo);
129 init_swap_chain(mInfo);
130 init_depth_buffer(mInfo);
131 init_uniform_buffer(mInfo);
132 init_descriptor_and_pipeline_layouts(mInfo, false);
133 init_renderpass(mInfo, mDepthPresent);
134 init_shaders(mInfo, kVertShaderText, kFragShaderText);
135 init_framebuffers(mInfo, mDepthPresent);
136 init_vertex_buffer(mInfo, g_vb_solid_face_colors_Data, sizeof(g_vb_solid_face_colors_Data),
137 sizeof(g_vb_solid_face_colors_Data[0]), false);
138 init_descriptor_pool(mInfo, false);
139 init_descriptor_set(mInfo);
140 init_pipeline_cache(mInfo);
141 init_pipeline(mInfo, mDepthPresent);
142
143 mClearValues[0].color.float32[0] = 0.2f;
144 mClearValues[0].color.float32[1] = 0.2f;
145 mClearValues[0].color.float32[2] = 0.2f;
146 mClearValues[0].color.float32[3] = 0.2f;
147 mClearValues[1].depthStencil.depth = 1.0f;
148 mClearValues[1].depthStencil.stencil = 0;
149
150 VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
151 imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
152 imageAcquiredSemaphoreCreateInfo.pNext = NULL;
153 imageAcquiredSemaphoreCreateInfo.flags = 0;
154 res = vkCreateSemaphore(mInfo.device, &imageAcquiredSemaphoreCreateInfo, NULL,
155 &mImageAcquiredSemaphore);
156 ASSERT_EQ(VK_SUCCESS, res);
157
158 VkFenceCreateInfo fenceInfo;
159 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
160 fenceInfo.pNext = NULL;
161 fenceInfo.flags = 0;
162 res = vkCreateFence(mInfo.device, &fenceInfo, NULL, &mDrawFence);
163 ASSERT_EQ(VK_SUCCESS, res);
164 }
165
step()166 void VulkanCommandBufferPerfTest::step()
167 {
168 for (int x = 0; x < mFrames; x++)
169 {
170 mInfo.current_buffer = x % mInfo.swapchainImageCount;
171
172 // Get the index of the next available swapchain image:
173 res = vkAcquireNextImageKHR(mInfo.device, mInfo.swap_chain, UINT64_MAX,
174 mImageAcquiredSemaphore, VK_NULL_HANDLE, &mInfo.current_buffer);
175 // Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
176 // return codes
177 ASSERT_EQ(VK_SUCCESS, res);
178 mCBImplementation(mInfo, mClearValues, mDrawFence, mImageAcquiredSemaphore, mBuffers);
179 }
180 }
181
TearDown()182 void VulkanCommandBufferPerfTest::TearDown()
183 {
184 if (mSkipTest)
185 {
186 return;
187 }
188
189 vkDestroySemaphore(mInfo.device, mImageAcquiredSemaphore, NULL);
190 vkDestroyFence(mInfo.device, mDrawFence, NULL);
191 destroy_pipeline(mInfo);
192 destroy_pipeline_cache(mInfo);
193 destroy_descriptor_pool(mInfo);
194 destroy_vertex_buffer(mInfo);
195 destroy_framebuffers(mInfo);
196 destroy_shaders(mInfo);
197 destroy_renderpass(mInfo);
198 destroy_descriptor_and_pipeline_layouts(mInfo);
199 destroy_uniform_buffer(mInfo);
200 destroy_depth_buffer(mInfo);
201 destroy_swap_chain(mInfo);
202 destroy_command_buffer2_array(mInfo, mBuffers);
203 destroy_command_buffer_array(mInfo, mBuffers);
204 destroy_command_buffer(mInfo);
205 destroy_command_pool(mInfo);
206 destroy_device(mInfo);
207 destroy_window(mInfo);
208 destroy_instance(mInfo);
209 ANGLEPerfTest::TearDown();
210 }
211
212 // Common code to present image used by all tests
Present(sample_info & info,VkFence drawFence)213 void Present(sample_info &info, VkFence drawFence)
214 {
215 // Now present the image in the window
216
217 VkPresentInfoKHR present;
218 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
219 present.pNext = NULL;
220 present.swapchainCount = 1;
221 present.pSwapchains = &info.swap_chain;
222 present.pImageIndices = &info.current_buffer;
223 present.pWaitSemaphores = NULL;
224 present.waitSemaphoreCount = 0;
225 present.pResults = NULL;
226
227 // Make sure command buffer is finished before presenting
228 VkResult res;
229 do
230 {
231 res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
232 } while (res == VK_TIMEOUT);
233 vkResetFences(info.device, 1, &drawFence);
234
235 ASSERT_EQ(VK_SUCCESS, res);
236 res = vkQueuePresentKHR(info.present_queue, &present);
237 ASSERT_EQ(VK_SUCCESS, res);
238 }
239
240 // 100 separate primary cmd buffers, each with 1 Draw
PrimaryCommandBufferBenchmarkHundredIndividual(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)241 void PrimaryCommandBufferBenchmarkHundredIndividual(sample_info &info,
242 VkClearValue *clear_values,
243 VkFence drawFence,
244 VkSemaphore imageAcquiredSemaphore,
245 int numBuffers)
246 {
247 VkResult res;
248
249 VkRenderPassBeginInfo rpBegin;
250 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
251 rpBegin.pNext = NULL;
252 rpBegin.renderPass = info.render_pass;
253 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
254 rpBegin.renderArea.offset.x = 0;
255 rpBegin.renderArea.offset.y = 0;
256 rpBegin.renderArea.extent.width = info.width;
257 rpBegin.renderArea.extent.height = info.height;
258 rpBegin.clearValueCount = 2;
259 rpBegin.pClearValues = clear_values;
260
261 VkCommandBufferBeginInfo cmdBufferInfo = {};
262 cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
263 cmdBufferInfo.pNext = NULL;
264 cmdBufferInfo.flags = 0;
265 cmdBufferInfo.pInheritanceInfo = NULL;
266
267 for (int x = 0; x < numBuffers; x++)
268 {
269 vkBeginCommandBuffer(info.cmds[x], &cmdBufferInfo);
270 vkCmdBeginRenderPass(info.cmds[x], &rpBegin, VK_SUBPASS_CONTENTS_INLINE);
271 vkCmdBindPipeline(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
272 vkCmdBindDescriptorSets(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout,
273 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL);
274
275 const VkDeviceSize offsets[1] = {0};
276 vkCmdBindVertexBuffers(info.cmds[x], 0, 1, &info.vertex_buffer.buf, offsets);
277
278 init_viewports_array(info, x);
279 init_scissors_array(info, x);
280
281 vkCmdDraw(info.cmds[x], 0, 1, 0, 0);
282 vkCmdEndRenderPass(info.cmds[x]);
283 res = vkEndCommandBuffer(info.cmds[x]);
284 ASSERT_EQ(VK_SUCCESS, res);
285 }
286
287 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
288 VkSubmitInfo submitInfo[1] = {};
289 submitInfo[0].pNext = NULL;
290 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
291 submitInfo[0].waitSemaphoreCount = 1;
292 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
293 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
294 submitInfo[0].commandBufferCount = numBuffers;
295 submitInfo[0].pCommandBuffers = info.cmds.data();
296 submitInfo[0].signalSemaphoreCount = 0;
297 submitInfo[0].pSignalSemaphores = NULL;
298
299 // Queue the command buffer for execution
300 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
301 ASSERT_EQ(VK_SUCCESS, res);
302
303 Present(info, drawFence);
304 }
305
306 // 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)307 void PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info &info,
308 VkClearValue *clear_values,
309 VkFence drawFence,
310 VkSemaphore imageAcquiredSemaphore,
311 int numBuffers)
312 {
313 VkResult res;
314
315 VkRenderPassBeginInfo rpBegin;
316 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
317 rpBegin.pNext = NULL;
318 rpBegin.renderPass = info.render_pass;
319 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
320 rpBegin.renderArea.offset.x = 0;
321 rpBegin.renderArea.offset.y = 0;
322 rpBegin.renderArea.extent.width = info.width;
323 rpBegin.renderArea.extent.height = info.height;
324 rpBegin.clearValueCount = 2;
325 rpBegin.pClearValues = clear_values;
326
327 VkCommandBufferBeginInfo cmdBufferInfo = {};
328 cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
329 cmdBufferInfo.pNext = NULL;
330 cmdBufferInfo.flags = 0;
331 cmdBufferInfo.pInheritanceInfo = NULL;
332
333 vkBeginCommandBuffer(info.cmd, &cmdBufferInfo);
334 for (int x = 0; x < numBuffers; x++)
335 {
336 vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_INLINE);
337 vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
338 vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0,
339 NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL);
340
341 const VkDeviceSize offsets[1] = {0};
342 vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);
343
344 init_viewports(info);
345 init_scissors(info);
346
347 vkCmdDraw(info.cmd, 0, 1, 0, 0);
348 vkCmdEndRenderPass(info.cmd);
349 }
350 res = vkEndCommandBuffer(info.cmd);
351 ASSERT_EQ(VK_SUCCESS, res);
352
353 const VkCommandBuffer cmd_bufs[] = {info.cmd};
354 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
355 VkSubmitInfo submitInfo[1] = {};
356 submitInfo[0].pNext = NULL;
357 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
358 submitInfo[0].waitSemaphoreCount = 1;
359 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
360 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
361 submitInfo[0].commandBufferCount = 1;
362 submitInfo[0].pCommandBuffers = cmd_bufs;
363 submitInfo[0].signalSemaphoreCount = 0;
364 submitInfo[0].pSignalSemaphores = NULL;
365
366 // Queue the command buffer for execution
367 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
368 ASSERT_EQ(VK_SUCCESS, res);
369
370 Present(info, drawFence);
371 }
372
373 // 100 separate secondary cmd buffers, each with 1 Draw
SecondaryCommandBufferBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)374 void SecondaryCommandBufferBenchmark(sample_info &info,
375 VkClearValue *clear_values,
376 VkFence drawFence,
377 VkSemaphore imageAcquiredSemaphore,
378 int numBuffers)
379 {
380 VkResult res;
381
382 // Record Secondary Command Buffer
383 VkCommandBufferInheritanceInfo inheritInfo = {};
384 inheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
385 inheritInfo.pNext = NULL;
386 inheritInfo.renderPass = info.render_pass;
387 inheritInfo.subpass = 0;
388 inheritInfo.framebuffer = info.framebuffers[info.current_buffer];
389 inheritInfo.occlusionQueryEnable = false;
390 inheritInfo.queryFlags = 0;
391 inheritInfo.pipelineStatistics = 0;
392
393 VkCommandBufferBeginInfo secondaryCommandBufferInfo = {};
394 secondaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
395 secondaryCommandBufferInfo.pNext = NULL;
396 secondaryCommandBufferInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT |
397 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
398 secondaryCommandBufferInfo.pInheritanceInfo = &inheritInfo;
399
400 for (int x = 0; x < numBuffers; x++)
401 {
402 vkBeginCommandBuffer(info.cmd2s[x], &secondaryCommandBufferInfo);
403 vkCmdBindPipeline(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
404 vkCmdBindDescriptorSets(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS,
405 info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(),
406 0, NULL);
407 const VkDeviceSize offsets[1] = {0};
408 vkCmdBindVertexBuffers(info.cmd2s[x], 0, 1, &info.vertex_buffer.buf, offsets);
409 init_viewports2_array(info, x);
410 init_scissors2_array(info, x);
411 vkCmdDraw(info.cmd2s[x], 0, 1, 0, 0);
412 vkEndCommandBuffer(info.cmd2s[x]);
413 }
414 // Record Secondary Command Buffer End
415
416 // Record Primary Command Buffer Begin
417 VkRenderPassBeginInfo rpBegin;
418 rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
419 rpBegin.pNext = NULL;
420 rpBegin.renderPass = info.render_pass;
421 rpBegin.framebuffer = info.framebuffers[info.current_buffer];
422 rpBegin.renderArea.offset.x = 0;
423 rpBegin.renderArea.offset.y = 0;
424 rpBegin.renderArea.extent.width = info.width;
425 rpBegin.renderArea.extent.height = info.height;
426 rpBegin.clearValueCount = 2;
427 rpBegin.pClearValues = clear_values;
428
429 VkCommandBufferBeginInfo primaryCommandBufferInfo = {};
430 primaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
431 primaryCommandBufferInfo.pNext = NULL;
432 primaryCommandBufferInfo.flags = 0;
433 primaryCommandBufferInfo.pInheritanceInfo = NULL;
434
435 vkBeginCommandBuffer(info.cmd, &primaryCommandBufferInfo);
436 for (int x = 0; x < numBuffers; x++)
437 {
438 vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
439 vkCmdExecuteCommands(info.cmd, 1, &info.cmd2s[x]);
440 vkCmdEndRenderPass(info.cmd);
441 }
442 vkEndCommandBuffer(info.cmd);
443 // Record Primary Command Buffer End
444
445 const VkCommandBuffer cmd_bufs[] = {info.cmd};
446 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
447 VkSubmitInfo submitInfo[1] = {};
448 submitInfo[0].pNext = NULL;
449 submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
450 submitInfo[0].waitSemaphoreCount = 1;
451 submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore;
452 submitInfo[0].pWaitDstStageMask = &pipe_stage_flags;
453 submitInfo[0].commandBufferCount = 1;
454 submitInfo[0].pCommandBuffers = cmd_bufs;
455 submitInfo[0].signalSemaphoreCount = 0;
456 submitInfo[0].pSignalSemaphores = NULL;
457
458 // Queue the command buffer for execution
459 res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
460 ASSERT_EQ(VK_SUCCESS, res);
461
462 Present(info, drawFence);
463 }
464
465 // Details on the following functions that stress various cmd buffer reset methods.
466 // All of these functions wrap the SecondaryCommandBufferBenchmark() test above,
467 // adding additional overhead with various reset methods.
468 // -CommandPoolDestroyBenchmark: Reset command buffers by destroying and re-creating
469 // command buffer pool.
470 // -CommandPoolHardResetBenchmark: Reset the command pool w/ the RELEASE_RESOURCES
471 // bit set.
472 // -CommandPoolSoftResetBenchmark: Reset to command pool w/o the RELEASE_RESOURCES
473 // bit set.
474 // -CommandBufferExplicitHardResetBenchmark: Reset each individual command buffer
475 // w/ the RELEASE_RESOURCES bit set.
476 // -CommandBufferExplicitSoftResetBenchmark: Reset each individual command buffer
477 // w/o the RELEASE_RESOURCES bit set.
478 // -CommandBufferImplicitResetBenchmark: Reset each individual command buffer
479 // implicitly by calling "Begin" on previously used cmd buffer.
480
CommandPoolDestroyBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)481 void CommandPoolDestroyBenchmark(sample_info &info,
482 VkClearValue *clear_values,
483 VkFence drawFence,
484 VkSemaphore imageAcquiredSemaphore,
485 int numBuffers)
486 {
487 // Save setup cmd buffer data to be restored
488 auto saved_cmd_pool = info.cmd_pool;
489 auto saved_cb = info.cmd;
490 auto saved_cb2s = info.cmd2s;
491 // Now re-allocate & destroy cmd buffers to stress those calls
492 init_command_pool(info, 0);
493 init_command_buffer2_array(info, numBuffers);
494
495 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
496 numBuffers);
497
498 destroy_command_pool(info);
499
500 // Restore original cmd buffer data for cleanup
501 info.cmd_pool = saved_cmd_pool;
502 info.cmd = saved_cb;
503 info.cmd2s = saved_cb2s;
504 }
505
CommandPoolHardResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)506 void CommandPoolHardResetBenchmark(sample_info &info,
507 VkClearValue *clear_values,
508 VkFence drawFence,
509 VkSemaphore imageAcquiredSemaphore,
510 int numBuffers)
511 {
512 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
513 numBuffers);
514 reset_command_pool(info, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
515 }
516
CommandPoolSoftResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)517 void CommandPoolSoftResetBenchmark(sample_info &info,
518 VkClearValue *clear_values,
519 VkFence drawFence,
520 VkSemaphore imageAcquiredSemaphore,
521 int numBuffers)
522 {
523 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
524 numBuffers);
525 reset_command_pool(info, 0);
526 }
527
CommandBufferExplicitHardResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)528 void CommandBufferExplicitHardResetBenchmark(sample_info &info,
529 VkClearValue *clear_values,
530 VkFence drawFence,
531 VkSemaphore imageAcquiredSemaphore,
532 int numBuffers)
533 {
534 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
535 numBuffers);
536 // Explicitly resetting cmd buffers
537 reset_command_buffer2_array(info, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
538 }
539
CommandBufferExplicitSoftResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)540 void CommandBufferExplicitSoftResetBenchmark(sample_info &info,
541 VkClearValue *clear_values,
542 VkFence drawFence,
543 VkSemaphore imageAcquiredSemaphore,
544 int numBuffers)
545 {
546 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
547 numBuffers);
548 // Explicitly resetting cmd buffers w/ soft reset (don't release resources)
549 reset_command_buffer2_array(info, 0);
550 }
551
CommandBufferImplicitResetBenchmark(sample_info & info,VkClearValue * clear_values,VkFence drawFence,VkSemaphore imageAcquiredSemaphore,int numBuffers)552 void CommandBufferImplicitResetBenchmark(sample_info &info,
553 VkClearValue *clear_values,
554 VkFence drawFence,
555 VkSemaphore imageAcquiredSemaphore,
556 int numBuffers)
557 {
558 // Repeated call SCBBenchmark & BeginCmdBuffer calls will implicitly reset each cmd buffer
559 SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore,
560 numBuffers);
561 }
562
PrimaryCBHundredIndividualParams()563 CommandBufferTestParams PrimaryCBHundredIndividualParams()
564 {
565 CommandBufferTestParams params;
566 params.CBImplementation = PrimaryCommandBufferBenchmarkHundredIndividual;
567 params.story = "_PrimaryCB_Submit_100_With_1_Draw";
568 return params;
569 }
570
PrimaryCBOneWithOneHundredParams()571 CommandBufferTestParams PrimaryCBOneWithOneHundredParams()
572 {
573 CommandBufferTestParams params;
574 params.CBImplementation = PrimaryCommandBufferBenchmarkOneWithOneHundred;
575 params.story = "_PrimaryCB_Submit_1_With_100_Draw";
576 return params;
577 }
578
SecondaryCBParams()579 CommandBufferTestParams SecondaryCBParams()
580 {
581 CommandBufferTestParams params;
582 params.CBImplementation = SecondaryCommandBufferBenchmark;
583 params.story = "_SecondaryCB_Submit_1_With_100_Draw_In_Individual_Secondary";
584 return params;
585 }
586
CommandPoolDestroyParams()587 CommandBufferTestParams CommandPoolDestroyParams()
588 {
589 CommandBufferTestParams params;
590 params.CBImplementation = CommandPoolDestroyBenchmark;
591 params.story = "_Reset_CBs_With_Destroy_Command_Pool";
592 return params;
593 }
594
CommandPoolHardResetParams()595 CommandBufferTestParams CommandPoolHardResetParams()
596 {
597 CommandBufferTestParams params;
598 params.CBImplementation = CommandPoolHardResetBenchmark;
599 params.story = "_Reset_CBs_With_Hard_Reset_Command_Pool";
600 return params;
601 }
602
CommandPoolSoftResetParams()603 CommandBufferTestParams CommandPoolSoftResetParams()
604 {
605 CommandBufferTestParams params;
606 params.CBImplementation = CommandPoolSoftResetBenchmark;
607 params.story = "_Reset_CBs_With_Soft_Reset_Command_Pool";
608 return params;
609 }
610
CommandBufferExplicitHardResetParams()611 CommandBufferTestParams CommandBufferExplicitHardResetParams()
612 {
613 CommandBufferTestParams params;
614 params.CBImplementation = CommandBufferExplicitHardResetBenchmark;
615 params.story = "_Reset_CBs_With_Explicit_Hard_Reset_Command_Buffers";
616 return params;
617 }
618
CommandBufferExplicitSoftResetParams()619 CommandBufferTestParams CommandBufferExplicitSoftResetParams()
620 {
621 CommandBufferTestParams params;
622 params.CBImplementation = CommandBufferExplicitSoftResetBenchmark;
623 params.story = "_Reset_CBs_With_Explicit_Soft_Reset_Command_Buffers";
624 return params;
625 }
626
CommandBufferImplicitResetParams()627 CommandBufferTestParams CommandBufferImplicitResetParams()
628 {
629 CommandBufferTestParams params;
630 params.CBImplementation = CommandBufferImplicitResetBenchmark;
631 params.story = "_Reset_CBs_With_Implicit_Reset_Command_Buffers";
632 return params;
633 }
634
TEST_P(VulkanCommandBufferPerfTest,Run)635 TEST_P(VulkanCommandBufferPerfTest, Run)
636 {
637 run();
638 }
639
640 INSTANTIATE_TEST_SUITE_P(,
641 VulkanCommandBufferPerfTest,
642 ::testing::Values(PrimaryCBHundredIndividualParams(),
643 PrimaryCBOneWithOneHundredParams(),
644 SecondaryCBParams(),
645 CommandPoolDestroyParams(),
646 CommandPoolHardResetParams(),
647 CommandPoolSoftResetParams(),
648 CommandBufferExplicitHardResetParams(),
649 CommandBufferExplicitSoftResetParams(),
650 CommandBufferImplicitResetParams()));
651