| // Copyright 2018 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // VulkanCommandBufferPerf: |
| // Performance benchmark for Vulkan Primary/Secondary Command Buffer implementations. |
| // Can run just these tests by adding "--gtest_filter=VulkanCommandBufferPerfTest*" |
| // option to angle_white_box_perftests. |
| // When running on Android with run_angle_white_box_perftests, use "-v" option. |
| |
| #include "ANGLEPerfTest.h" |
| #include "common/platform.h" |
| #include "test_utils/third_party/vulkan_command_buffer_utils.h" |
| |
| #if defined(ANDROID) |
| # define NUM_CMD_BUFFERS 1000 |
| // Android devices tend to be slower so only do 10 frames to avoid timeout |
| # define NUM_FRAMES 10 |
| #else |
| # define NUM_CMD_BUFFERS 1000 |
| # define NUM_FRAMES 100 |
| #endif |
| |
| // These are minimal shaders used to submit trivial draw commands to command |
| // buffers so that we can create large batches of cmd buffers with consistent |
| // draw patterns but size/type of cmd buffers can be varied to test cmd buffer |
| // differences across devices. |
| constexpr char kVertShaderText[] = R"( |
| #version 400 |
| #extension GL_ARB_separate_shader_objects : enable |
| #extension GL_ARB_shading_language_420pack : enable |
| layout (std140, binding = 0) uniform bufferVals { |
| mat4 mvp; |
| } myBufferVals; |
| layout (location = 0) in vec4 pos; |
| layout (location = 1) in vec4 inColor; |
| layout (location = 0) out vec4 outColor; |
| void main() { |
| outColor = inColor; |
| gl_Position = myBufferVals.mvp * pos; |
| })"; |
| |
| constexpr char kFragShaderText[] = R"( |
| #version 400 |
| #extension GL_ARB_separate_shader_objects : enable |
| #extension GL_ARB_shading_language_420pack : enable |
| layout (location = 0) in vec4 color; |
| layout (location = 0) out vec4 outColor; |
| void main() { |
| outColor = color; |
| })"; |
| |
| using CommandBufferImpl = void (*)(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers); |
| |
| struct CommandBufferTestParams |
| { |
| CommandBufferImpl CBImplementation; |
| std::string story; |
| int frames = NUM_FRAMES; |
| int buffers = NUM_CMD_BUFFERS; |
| }; |
| |
| class VulkanCommandBufferPerfTest : public ANGLEPerfTest, |
| public ::testing::WithParamInterface<CommandBufferTestParams> |
| { |
| public: |
| VulkanCommandBufferPerfTest(); |
| |
| void SetUp() override; |
| void TearDown() override; |
| void step() override; |
| |
| private: |
| VkClearValue mClearValues[2] = {}; |
| VkSemaphore mImageAcquiredSemaphore = VK_NULL_HANDLE; |
| VkFence mDrawFence = VK_NULL_HANDLE; |
| |
| VkResult res = VK_NOT_READY; |
| const bool mDepthPresent = true; |
| struct sample_info mInfo = {}; |
| std::string mSampleTitle; |
| CommandBufferImpl mCBImplementation = nullptr; |
| int mFrames = 0; |
| int mBuffers = 0; |
| }; |
| |
| VulkanCommandBufferPerfTest::VulkanCommandBufferPerfTest() |
| : ANGLEPerfTest("VulkanCommandBufferPerfTest", "", GetParam().story, GetParam().frames) |
| { |
| mInfo = {}; |
| mSampleTitle = "Draw Textured Cube"; |
| mCBImplementation = GetParam().CBImplementation; |
| mFrames = GetParam().frames; |
| mBuffers = GetParam().buffers; |
| |
| // This test appears to be flaky on multiple platforms. |
| #if !defined(ANGLE_PLATFORM_ANDROID) |
| // mSkipTest = true; |
| #endif // !defined(ANGLE_PLATFORM_ANDROID) |
| } |
| |
| void VulkanCommandBufferPerfTest::SetUp() |
| { |
| if (mSkipTest) |
| { |
| return; |
| } |
| |
| init_global_layer_properties(mInfo); |
| init_instance_extension_names(mInfo); |
| init_device_extension_names(mInfo); |
| init_instance(mInfo, mSampleTitle.c_str()); |
| init_enumerate_device(mInfo); |
| init_window_size(mInfo, 500, 500); |
| init_connection(mInfo); |
| init_window(mInfo); |
| init_swapchain_extension(mInfo); |
| init_device(mInfo); |
| |
| init_command_pool(mInfo, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); |
| init_command_buffer(mInfo); // Primary command buffer to hold secondaries |
| init_command_buffer_array(mInfo, mBuffers); // Array of primary command buffers |
| init_command_buffer2_array(mInfo, mBuffers); // Array containing all secondary buffers |
| init_device_queue(mInfo); |
| init_swap_chain(mInfo); |
| init_depth_buffer(mInfo); |
| init_uniform_buffer(mInfo); |
| init_descriptor_and_pipeline_layouts(mInfo, false); |
| init_renderpass(mInfo, mDepthPresent); |
| init_shaders(mInfo, kVertShaderText, kFragShaderText); |
| init_framebuffers(mInfo, mDepthPresent); |
| init_vertex_buffer(mInfo, g_vb_solid_face_colors_Data, sizeof(g_vb_solid_face_colors_Data), |
| sizeof(g_vb_solid_face_colors_Data[0]), false); |
| init_descriptor_pool(mInfo, false); |
| init_descriptor_set(mInfo); |
| init_pipeline_cache(mInfo); |
| init_pipeline(mInfo, mDepthPresent); |
| |
| mClearValues[0].color.float32[0] = 0.2f; |
| mClearValues[0].color.float32[1] = 0.2f; |
| mClearValues[0].color.float32[2] = 0.2f; |
| mClearValues[0].color.float32[3] = 0.2f; |
| mClearValues[1].depthStencil.depth = 1.0f; |
| mClearValues[1].depthStencil.stencil = 0; |
| |
| VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo; |
| imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; |
| imageAcquiredSemaphoreCreateInfo.pNext = NULL; |
| imageAcquiredSemaphoreCreateInfo.flags = 0; |
| res = vkCreateSemaphore(mInfo.device, &imageAcquiredSemaphoreCreateInfo, NULL, |
| &mImageAcquiredSemaphore); |
| ASSERT_EQ(VK_SUCCESS, res); |
| |
| VkFenceCreateInfo fenceInfo; |
| fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |
| fenceInfo.pNext = NULL; |
| fenceInfo.flags = 0; |
| res = vkCreateFence(mInfo.device, &fenceInfo, NULL, &mDrawFence); |
| ASSERT_EQ(VK_SUCCESS, res); |
| } |
| |
| void VulkanCommandBufferPerfTest::step() |
| { |
| for (int x = 0; x < mFrames; x++) |
| { |
| mInfo.current_buffer = x % mInfo.swapchainImageCount; |
| |
| // Get the index of the next available swapchain image: |
| res = vkAcquireNextImageKHR(mInfo.device, mInfo.swap_chain, UINT64_MAX, |
| mImageAcquiredSemaphore, VK_NULL_HANDLE, &mInfo.current_buffer); |
| // Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR |
| // return codes |
| ASSERT_EQ(VK_SUCCESS, res); |
| mCBImplementation(mInfo, mClearValues, mDrawFence, mImageAcquiredSemaphore, mBuffers); |
| } |
| } |
| |
| void VulkanCommandBufferPerfTest::TearDown() |
| { |
| if (mSkipTest) |
| { |
| return; |
| } |
| |
| vkDestroySemaphore(mInfo.device, mImageAcquiredSemaphore, NULL); |
| vkDestroyFence(mInfo.device, mDrawFence, NULL); |
| destroy_pipeline(mInfo); |
| destroy_pipeline_cache(mInfo); |
| destroy_descriptor_pool(mInfo); |
| destroy_vertex_buffer(mInfo); |
| destroy_framebuffers(mInfo); |
| destroy_shaders(mInfo); |
| destroy_renderpass(mInfo); |
| destroy_descriptor_and_pipeline_layouts(mInfo); |
| destroy_uniform_buffer(mInfo); |
| destroy_depth_buffer(mInfo); |
| destroy_swap_chain(mInfo); |
| destroy_command_buffer2_array(mInfo, mBuffers); |
| destroy_command_buffer_array(mInfo, mBuffers); |
| destroy_command_buffer(mInfo); |
| destroy_command_pool(mInfo); |
| destroy_device(mInfo); |
| destroy_window(mInfo); |
| destroy_instance(mInfo); |
| ANGLEPerfTest::TearDown(); |
| } |
| |
| // Common code to present image used by all tests |
| void Present(sample_info &info, VkFence drawFence) |
| { |
| // Now present the image in the window |
| |
| VkPresentInfoKHR present; |
| present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; |
| present.pNext = NULL; |
| present.swapchainCount = 1; |
| present.pSwapchains = &info.swap_chain; |
| present.pImageIndices = &info.current_buffer; |
| present.pWaitSemaphores = NULL; |
| present.waitSemaphoreCount = 0; |
| present.pResults = NULL; |
| |
| // Make sure command buffer is finished before presenting |
| VkResult res; |
| do |
| { |
| res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT); |
| } while (res == VK_TIMEOUT); |
| vkResetFences(info.device, 1, &drawFence); |
| |
| ASSERT_EQ(VK_SUCCESS, res); |
| res = vkQueuePresentKHR(info.present_queue, &present); |
| ASSERT_EQ(VK_SUCCESS, res); |
| } |
| |
| // 100 separate primary cmd buffers, each with 1 Draw |
| void PrimaryCommandBufferBenchmarkHundredIndividual(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| VkResult res; |
| |
| VkRenderPassBeginInfo rpBegin; |
| rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |
| rpBegin.pNext = NULL; |
| rpBegin.renderPass = info.render_pass; |
| rpBegin.framebuffer = info.framebuffers[info.current_buffer]; |
| rpBegin.renderArea.offset.x = 0; |
| rpBegin.renderArea.offset.y = 0; |
| rpBegin.renderArea.extent.width = info.width; |
| rpBegin.renderArea.extent.height = info.height; |
| rpBegin.clearValueCount = 2; |
| rpBegin.pClearValues = clear_values; |
| |
| VkCommandBufferBeginInfo cmdBufferInfo = {}; |
| cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
| cmdBufferInfo.pNext = NULL; |
| cmdBufferInfo.flags = 0; |
| cmdBufferInfo.pInheritanceInfo = NULL; |
| |
| for (int x = 0; x < numBuffers; x++) |
| { |
| vkBeginCommandBuffer(info.cmds[x], &cmdBufferInfo); |
| vkCmdBeginRenderPass(info.cmds[x], &rpBegin, VK_SUBPASS_CONTENTS_INLINE); |
| vkCmdBindPipeline(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline); |
| vkCmdBindDescriptorSets(info.cmds[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, |
| 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL); |
| |
| const VkDeviceSize offsets[1] = {0}; |
| vkCmdBindVertexBuffers(info.cmds[x], 0, 1, &info.vertex_buffer.buf, offsets); |
| |
| init_viewports_array(info, x); |
| init_scissors_array(info, x); |
| |
| vkCmdDraw(info.cmds[x], 0, 1, 0, 0); |
| vkCmdEndRenderPass(info.cmds[x]); |
| res = vkEndCommandBuffer(info.cmds[x]); |
| ASSERT_EQ(VK_SUCCESS, res); |
| } |
| |
| VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
| VkSubmitInfo submitInfo[1] = {}; |
| submitInfo[0].pNext = NULL; |
| submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |
| submitInfo[0].waitSemaphoreCount = 1; |
| submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore; |
| submitInfo[0].pWaitDstStageMask = &pipe_stage_flags; |
| submitInfo[0].commandBufferCount = numBuffers; |
| submitInfo[0].pCommandBuffers = info.cmds.data(); |
| submitInfo[0].signalSemaphoreCount = 0; |
| submitInfo[0].pSignalSemaphores = NULL; |
| |
| // Queue the command buffer for execution |
| res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence); |
| ASSERT_EQ(VK_SUCCESS, res); |
| |
| Present(info, drawFence); |
| } |
| |
| // 100 of the same Draw cmds in the same primary cmd buffer |
| void PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| VkResult res; |
| |
| VkRenderPassBeginInfo rpBegin; |
| rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |
| rpBegin.pNext = NULL; |
| rpBegin.renderPass = info.render_pass; |
| rpBegin.framebuffer = info.framebuffers[info.current_buffer]; |
| rpBegin.renderArea.offset.x = 0; |
| rpBegin.renderArea.offset.y = 0; |
| rpBegin.renderArea.extent.width = info.width; |
| rpBegin.renderArea.extent.height = info.height; |
| rpBegin.clearValueCount = 2; |
| rpBegin.pClearValues = clear_values; |
| |
| VkCommandBufferBeginInfo cmdBufferInfo = {}; |
| cmdBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
| cmdBufferInfo.pNext = NULL; |
| cmdBufferInfo.flags = 0; |
| cmdBufferInfo.pInheritanceInfo = NULL; |
| |
| vkBeginCommandBuffer(info.cmd, &cmdBufferInfo); |
| for (int x = 0; x < numBuffers; x++) |
| { |
| vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_INLINE); |
| vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline); |
| vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, |
| NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL); |
| |
| const VkDeviceSize offsets[1] = {0}; |
| vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets); |
| |
| init_viewports(info); |
| init_scissors(info); |
| |
| vkCmdDraw(info.cmd, 0, 1, 0, 0); |
| vkCmdEndRenderPass(info.cmd); |
| } |
| res = vkEndCommandBuffer(info.cmd); |
| ASSERT_EQ(VK_SUCCESS, res); |
| |
| const VkCommandBuffer cmd_bufs[] = {info.cmd}; |
| VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
| VkSubmitInfo submitInfo[1] = {}; |
| submitInfo[0].pNext = NULL; |
| submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |
| submitInfo[0].waitSemaphoreCount = 1; |
| submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore; |
| submitInfo[0].pWaitDstStageMask = &pipe_stage_flags; |
| submitInfo[0].commandBufferCount = 1; |
| submitInfo[0].pCommandBuffers = cmd_bufs; |
| submitInfo[0].signalSemaphoreCount = 0; |
| submitInfo[0].pSignalSemaphores = NULL; |
| |
| // Queue the command buffer for execution |
| res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence); |
| ASSERT_EQ(VK_SUCCESS, res); |
| |
| Present(info, drawFence); |
| } |
| |
| // 100 separate secondary cmd buffers, each with 1 Draw |
| void SecondaryCommandBufferBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| VkResult res; |
| |
| // Record Secondary Command Buffer |
| VkCommandBufferInheritanceInfo inheritInfo = {}; |
| inheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; |
| inheritInfo.pNext = NULL; |
| inheritInfo.renderPass = info.render_pass; |
| inheritInfo.subpass = 0; |
| inheritInfo.framebuffer = info.framebuffers[info.current_buffer]; |
| inheritInfo.occlusionQueryEnable = false; |
| inheritInfo.queryFlags = 0; |
| inheritInfo.pipelineStatistics = 0; |
| |
| VkCommandBufferBeginInfo secondaryCommandBufferInfo = {}; |
| secondaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
| secondaryCommandBufferInfo.pNext = NULL; |
| secondaryCommandBufferInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | |
| VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; |
| secondaryCommandBufferInfo.pInheritanceInfo = &inheritInfo; |
| |
| for (int x = 0; x < numBuffers; x++) |
| { |
| vkBeginCommandBuffer(info.cmd2s[x], &secondaryCommandBufferInfo); |
| vkCmdBindPipeline(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline); |
| vkCmdBindDescriptorSets(info.cmd2s[x], VK_PIPELINE_BIND_POINT_GRAPHICS, |
| info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(), |
| 0, NULL); |
| const VkDeviceSize offsets[1] = {0}; |
| vkCmdBindVertexBuffers(info.cmd2s[x], 0, 1, &info.vertex_buffer.buf, offsets); |
| init_viewports2_array(info, x); |
| init_scissors2_array(info, x); |
| vkCmdDraw(info.cmd2s[x], 0, 1, 0, 0); |
| vkEndCommandBuffer(info.cmd2s[x]); |
| } |
| // Record Secondary Command Buffer End |
| |
| // Record Primary Command Buffer Begin |
| VkRenderPassBeginInfo rpBegin; |
| rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |
| rpBegin.pNext = NULL; |
| rpBegin.renderPass = info.render_pass; |
| rpBegin.framebuffer = info.framebuffers[info.current_buffer]; |
| rpBegin.renderArea.offset.x = 0; |
| rpBegin.renderArea.offset.y = 0; |
| rpBegin.renderArea.extent.width = info.width; |
| rpBegin.renderArea.extent.height = info.height; |
| rpBegin.clearValueCount = 2; |
| rpBegin.pClearValues = clear_values; |
| |
| VkCommandBufferBeginInfo primaryCommandBufferInfo = {}; |
| primaryCommandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
| primaryCommandBufferInfo.pNext = NULL; |
| primaryCommandBufferInfo.flags = 0; |
| primaryCommandBufferInfo.pInheritanceInfo = NULL; |
| |
| vkBeginCommandBuffer(info.cmd, &primaryCommandBufferInfo); |
| for (int x = 0; x < numBuffers; x++) |
| { |
| vkCmdBeginRenderPass(info.cmd, &rpBegin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); |
| vkCmdExecuteCommands(info.cmd, 1, &info.cmd2s[x]); |
| vkCmdEndRenderPass(info.cmd); |
| } |
| vkEndCommandBuffer(info.cmd); |
| // Record Primary Command Buffer End |
| |
| const VkCommandBuffer cmd_bufs[] = {info.cmd}; |
| VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
| VkSubmitInfo submitInfo[1] = {}; |
| submitInfo[0].pNext = NULL; |
| submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |
| submitInfo[0].waitSemaphoreCount = 1; |
| submitInfo[0].pWaitSemaphores = &imageAcquiredSemaphore; |
| submitInfo[0].pWaitDstStageMask = &pipe_stage_flags; |
| submitInfo[0].commandBufferCount = 1; |
| submitInfo[0].pCommandBuffers = cmd_bufs; |
| submitInfo[0].signalSemaphoreCount = 0; |
| submitInfo[0].pSignalSemaphores = NULL; |
| |
| // Queue the command buffer for execution |
| res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence); |
| ASSERT_EQ(VK_SUCCESS, res); |
| |
| Present(info, drawFence); |
| } |
| |
| // Details on the following functions that stress various cmd buffer reset methods. |
| // All of these functions wrap the SecondaryCommandBufferBenchmark() test above, |
| // adding additional overhead with various reset methods. |
| // -CommandPoolDestroyBenchmark: Reset command buffers by destroying and re-creating |
| // command buffer pool. |
| // -CommandPoolHardResetBenchmark: Reset the command pool w/ the RELEASE_RESOURCES |
| // bit set. |
| // -CommandPoolSoftResetBenchmark: Reset to command pool w/o the RELEASE_RESOURCES |
| // bit set. |
| // -CommandBufferExplicitHardResetBenchmark: Reset each individual command buffer |
| // w/ the RELEASE_RESOURCES bit set. |
| // -CommandBufferExplicitSoftResetBenchmark: Reset each individual command buffer |
| // w/o the RELEASE_RESOURCES bit set. |
| // -CommandBufferImplicitResetBenchmark: Reset each individual command buffer |
| // implicitly by calling "Begin" on previously used cmd buffer. |
| |
| void CommandPoolDestroyBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| // Save setup cmd buffer data to be restored |
| auto saved_cmd_pool = info.cmd_pool; |
| auto saved_cb = info.cmd; |
| auto saved_cb2s = info.cmd2s; |
| // Now re-allocate & destroy cmd buffers to stress those calls |
| init_command_pool(info, 0); |
| init_command_buffer2_array(info, numBuffers); |
| |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| |
| destroy_command_pool(info); |
| |
| // Restore original cmd buffer data for cleanup |
| info.cmd_pool = saved_cmd_pool; |
| info.cmd = saved_cb; |
| info.cmd2s = saved_cb2s; |
| } |
| |
| void CommandPoolHardResetBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| reset_command_pool(info, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); |
| } |
| |
| void CommandPoolSoftResetBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| reset_command_pool(info, 0); |
| } |
| |
| void CommandBufferExplicitHardResetBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| // Explicitly resetting cmd buffers |
| reset_command_buffer2_array(info, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); |
| } |
| |
| void CommandBufferExplicitSoftResetBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| // Explicitly resetting cmd buffers w/ soft reset (don't release resources) |
| reset_command_buffer2_array(info, 0); |
| } |
| |
| void CommandBufferImplicitResetBenchmark(sample_info &info, |
| VkClearValue *clear_values, |
| VkFence drawFence, |
| VkSemaphore imageAcquiredSemaphore, |
| int numBuffers) |
| { |
| // Repeated call SCBBenchmark & BeginCmdBuffer calls will implicitly reset each cmd buffer |
| SecondaryCommandBufferBenchmark(info, clear_values, drawFence, imageAcquiredSemaphore, |
| numBuffers); |
| } |
| |
| CommandBufferTestParams PrimaryCBHundredIndividualParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = PrimaryCommandBufferBenchmarkHundredIndividual; |
| params.story = "_PrimaryCB_Submit_100_With_1_Draw"; |
| return params; |
| } |
| |
| CommandBufferTestParams PrimaryCBOneWithOneHundredParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = PrimaryCommandBufferBenchmarkOneWithOneHundred; |
| params.story = "_PrimaryCB_Submit_1_With_100_Draw"; |
| return params; |
| } |
| |
| CommandBufferTestParams SecondaryCBParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = SecondaryCommandBufferBenchmark; |
| params.story = "_SecondaryCB_Submit_1_With_100_Draw_In_Individual_Secondary"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandPoolDestroyParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandPoolDestroyBenchmark; |
| params.story = "_Reset_CBs_With_Destroy_Command_Pool"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandPoolHardResetParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandPoolHardResetBenchmark; |
| params.story = "_Reset_CBs_With_Hard_Reset_Command_Pool"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandPoolSoftResetParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandPoolSoftResetBenchmark; |
| params.story = "_Reset_CBs_With_Soft_Reset_Command_Pool"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandBufferExplicitHardResetParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandBufferExplicitHardResetBenchmark; |
| params.story = "_Reset_CBs_With_Explicit_Hard_Reset_Command_Buffers"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandBufferExplicitSoftResetParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandBufferExplicitSoftResetBenchmark; |
| params.story = "_Reset_CBs_With_Explicit_Soft_Reset_Command_Buffers"; |
| return params; |
| } |
| |
| CommandBufferTestParams CommandBufferImplicitResetParams() |
| { |
| CommandBufferTestParams params; |
| params.CBImplementation = CommandBufferImplicitResetBenchmark; |
| params.story = "_Reset_CBs_With_Implicit_Reset_Command_Buffers"; |
| return params; |
| } |
| |
| TEST_P(VulkanCommandBufferPerfTest, Run) |
| { |
| run(); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(, |
| VulkanCommandBufferPerfTest, |
| ::testing::Values(PrimaryCBHundredIndividualParams(), |
| PrimaryCBOneWithOneHundredParams(), |
| SecondaryCBParams(), |
| CommandPoolDestroyParams(), |
| CommandPoolHardResetParams(), |
| CommandPoolSoftResetParams(), |
| CommandBufferExplicitHardResetParams(), |
| CommandBufferExplicitSoftResetParams(), |
| CommandBufferImplicitResetParams())); |