• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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