Commit 3571ad49 by Tobin Ehlis Committed by Commit Bot

Vulkan:Adding Cmd Buffer Reset tests

Resetting cmd buffers in various ways to understand VK driver perf on various devices. Also includes some changes to get the chromium APK wrapper for angle_white_box_perftests compiling. Bug: angleproject:3137 Change-Id: I56bd163cdd6605ce09effe509a9c7ac5e0008e7a Reviewed-on: https://chromium-review.googlesource.com/c/1456482 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 0a87f08d
......@@ -214,11 +214,16 @@ void ANGLEPerfTest::run()
// Do another warmup run. Seems to consistently improve results.
doRunLoop(kMaximumRunTimeSeconds);
double totalTime = 0.0;
for (unsigned int trial = 0; trial < kNumTrials; ++trial)
{
doRunLoop(kMaximumRunTimeSeconds);
printResults();
totalTime += printResults();
}
double average = totalTime / kNumTrials;
std::ostringstream averageString;
averageString << "for " << kNumTrials << " runs";
printResult("average", average, averageString.str(), false);
}
void ANGLEPerfTest::doRunLoop(double maxRunTime)
......@@ -268,7 +273,7 @@ void ANGLEPerfTest::SetUp() {}
void ANGLEPerfTest::TearDown() {}
void ANGLEPerfTest::printResults()
double ANGLEPerfTest::printResults()
{
double elapsedTimeSeconds[2] = {
mTimer->getElapsedTime(),
......@@ -283,6 +288,7 @@ void ANGLEPerfTest::printResults()
// If measured gpu time is non-zero, print that too.
size_t clocksToOutput = mGPUTimeNs > 0 ? 2 : 1;
double retValue = 0.0;
for (size_t i = 0; i < clocksToOutput; ++i)
{
double secondsPerStep = elapsedTimeSeconds[i] / static_cast<double>(mNumStepsPerformed);
......@@ -292,14 +298,17 @@ void ANGLEPerfTest::printResults()
if (secondsPerIteration > 1e-3)
{
double microSecondsPerIteration = secondsPerIteration * kMicroSecondsPerSecond;
retValue = microSecondsPerIteration;
printResult(clockNames[i], microSecondsPerIteration, "us", true);
}
else
{
double nanoSecPerIteration = secondsPerIteration * kNanoSecondsPerSecond;
retValue = nanoSecPerIteration;
printResult(clockNames[i], nanoSecPerIteration, "ns", true);
}
}
return retValue;
}
double ANGLEPerfTest::normalizedTime(size_t value) const
......
......@@ -97,7 +97,7 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
bool mSkipTest;
private:
void printResults();
double printResults();
unsigned int mStepsToRun;
unsigned int mNumStepsPerformed;
......
......@@ -9,6 +9,14 @@
#include "common/platform.h"
#include "test_utils/third_party/vulkan_command_buffer_utils.h"
#if defined(ANDROID)
# define NUM_CMD_BUFFERS 1000
# define NUM_FRAMES 10
#else
# define NUM_CMD_BUFFERS 1000
# define NUM_FRAMES 100
#endif
constexpr char kVertShaderText[] = R"(
#version 400
#extension GL_ARB_separate_shader_objects : enable
......@@ -44,8 +52,8 @@ struct CommandBufferTestParams
{
CommandBufferImpl CBImplementation;
std::string suffix;
int frames = 1;
int buffers = 10;
int frames = NUM_FRAMES;
int buffers = NUM_CMD_BUFFERS;
};
class VulkanCommandBufferPerfTest : public ANGLEPerfTest,
......@@ -83,7 +91,7 @@ VulkanCommandBufferPerfTest::VulkanCommandBufferPerfTest()
// This test appears to be flaky on multiple platforms.
#if !defined(ANGLE_PLATFORM_ANDROID)
mSkipTest = true;
// mSkipTest = true;
#endif // !defined(ANGLE_PLATFORM_ANDROID)
}
......@@ -105,7 +113,7 @@ void VulkanCommandBufferPerfTest::SetUp()
init_swapchain_extension(mInfo);
init_device(mInfo);
init_command_pool(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
......@@ -193,6 +201,34 @@ void VulkanCommandBufferPerfTest::TearDown()
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);
}
void PrimaryCommandBufferBenchmarkHundredIndividual(sample_info &info,
VkClearValue *clear_values,
VkFence drawFence,
......@@ -255,28 +291,7 @@ void PrimaryCommandBufferBenchmarkHundredIndividual(sample_info &info,
res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
ASSERT_EQ(VK_SUCCESS, res);
// 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
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);
Present(info, drawFence);
}
void PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info &info,
......@@ -342,28 +357,7 @@ void PrimaryCommandBufferBenchmarkOneWithOneHundred(sample_info &info,
res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
ASSERT_EQ(VK_SUCCESS, res);
// 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
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);
Present(info, drawFence);
}
void SecondaryCommandBufferBenchmark(sample_info &info,
......@@ -454,28 +448,89 @@ void SecondaryCommandBufferBenchmark(sample_info &info,
res = vkQueueSubmit(info.graphics_queue, 1, submitInfo, drawFence);
ASSERT_EQ(VK_SUCCESS, res);
// Now present the image in the window
Present(info, drawFence);
}
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;
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;
}
// Make sure command buffer is finished before presenting
do
{
res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
} while (res == VK_TIMEOUT);
vkResetFences(info.device, 1, &drawFence);
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);
}
ASSERT_EQ(VK_SUCCESS, res);
res = vkQueuePresentKHR(info.present_queue, &present);
ASSERT_EQ(VK_SUCCESS, res);
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()
......@@ -502,6 +557,54 @@ CommandBufferTestParams SecondaryCBParams()
return params;
}
CommandBufferTestParams CommandPoolDestroyParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandPoolDestroyBenchmark;
params.suffix = "_Reset_CBs_With_Destroy_Command_Pool";
return params;
}
CommandBufferTestParams CommandPoolHardResetParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandPoolHardResetBenchmark;
params.suffix = "_Reset_CBs_With_Hard_Reset_Command_Pool";
return params;
}
CommandBufferTestParams CommandPoolSoftResetParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandPoolSoftResetBenchmark;
params.suffix = "_Reset_CBs_With_Soft_Reset_Command_Pool";
return params;
}
CommandBufferTestParams CommandBufferExplicitHardResetParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandBufferExplicitHardResetBenchmark;
params.suffix = "_Reset_CBs_With_Explicit_Hard_Reset_Command_Buffers";
return params;
}
CommandBufferTestParams CommandBufferExplicitSoftResetParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandBufferExplicitSoftResetBenchmark;
params.suffix = "_Reset_CBs_With_Explicit_Soft_Reset_Command_Buffers";
return params;
}
CommandBufferTestParams CommandBufferImplicitResetParams()
{
CommandBufferTestParams params;
params.CBImplementation = CommandBufferImplicitResetBenchmark;
params.suffix = "_Reset_CBs_With_Implicit_Reset_Command_Buffers";
return params;
}
TEST_P(VulkanCommandBufferPerfTest, Run)
{
run();
......@@ -511,4 +614,10 @@ INSTANTIATE_TEST_CASE_P(,
VulkanCommandBufferPerfTest,
::testing::Values(PrimaryCBHundredIndividualParams(),
PrimaryCBOneWithOneHundredParams(),
SecondaryCBParams()));
SecondaryCBParams(),
CommandPoolDestroyParams(),
CommandPoolHardResetParams(),
CommandPoolSoftResetParams(),
CommandBufferExplicitHardResetParams(),
CommandBufferExplicitSoftResetParams(),
CommandBufferImplicitResetParams()));
......@@ -4,10 +4,14 @@
#include "perf_test.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdio.h>
#include <vector>
#if defined(ANDROID)
# include <android/log.h>
#endif
namespace {
namespace base {
......@@ -73,8 +77,15 @@ void PrintResultsImpl(const std::string& measurement,
const std::string& units,
bool important) {
fflush(stdout);
#if defined(ANDROID)
__android_log_print(
ANDROID_LOG_INFO, "ANGLE", "%s",
ResultsToString(measurement, modifier, trace, values, prefix, suffix, units, important)
.c_str());
#else
printf("%s", ResultsToString(measurement, modifier, trace, values,
prefix, suffix, units, important).c_str());
#endif // defined(ANDROID)
fflush(stdout);
}
......
......@@ -705,7 +705,7 @@ VkResult init_device(struct sample_info &info)
return res;
}
void init_command_pool(struct sample_info &info)
void init_command_pool(struct sample_info &info, VkCommandPoolCreateFlags cmd_pool_create_flags)
{
/* DEPENDS on init_swapchain_extension() */
VkResult res;
......@@ -714,7 +714,7 @@ void init_command_pool(struct sample_info &info)
cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmd_pool_info.pNext = NULL;
cmd_pool_info.queueFamilyIndex = info.graphics_queue_family_index;
cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
cmd_pool_info.flags = cmd_pool_create_flags;
res = vkCreateCommandPool(info.device, &cmd_pool_info, NULL, &info.cmd_pool);
assert(res == VK_SUCCESS);
......@@ -1736,22 +1736,6 @@ void init_viewports_array(struct sample_info &info, int index)
#endif
}
void init_viewports2(struct sample_info &info)
{
#ifdef __ANDROID__
// Disable dynamic viewport on Android. Some drive has an issue with the dynamic viewport
// feature.
#else
info.viewport.height = (float)info.height;
info.viewport.width = (float)info.width;
info.viewport.minDepth = (float)0.0f;
info.viewport.maxDepth = (float)1.0f;
info.viewport.x = 0;
info.viewport.y = 0;
vkCmdSetViewport(info.cmd2, 0, NUM_VIEWPORTS, &info.viewport);
#endif
}
void init_viewports2_array(struct sample_info &info, int index)
{
#ifdef __ANDROID__
......@@ -1855,11 +1839,25 @@ void destroy_command_buffer_array(struct sample_info &info, int numBuffers)
vkFreeCommandBuffers(info.device, info.cmd_pool, numBuffers, info.cmds.data());
}
void reset_command_buffer2_array(struct sample_info &info,
VkCommandBufferResetFlags cmd_buffer_reset_flags)
{
for (auto cb : info.cmd2s)
{
vkResetCommandBuffer(cb, cmd_buffer_reset_flags);
}
}
void destroy_command_buffer2_array(struct sample_info &info, int numBuffers)
{
vkFreeCommandBuffers(info.device, info.cmd_pool, numBuffers, info.cmd2s.data());
}
void reset_command_pool(struct sample_info &info, VkCommandPoolResetFlags cmd_pool_reset_flags)
{
vkResetCommandPool(info.device, info.cmd_pool, cmd_pool_reset_flags);
}
void destroy_command_pool(struct sample_info &info)
{
vkDestroyCommandPool(info.device, info.cmd_pool, NULL);
......
......@@ -61,8 +61,8 @@ ANGLE_REENABLE_EXTRA_SEMI_WARNING
# define VK_USE_PLATFORM_ANDROID_KHR
# include <android/log.h>
# include <unistd.h>
# include "OSWindow.h"
# include "android/third_party/android_native_app_glue.h"
# include "util/OSWindow.h"
# include "util/android/third_party/android_native_app_glue.h"
#else
# include <unistd.h>
# include "vulkan/vk_sdk_platform.h"
......@@ -214,7 +214,6 @@ struct sample_info
std::vector<float> MVP;
VkCommandBuffer cmd; // Buffer for initialization commands
VkCommandBuffer cmd2; // Place to hold secondary command buffer
std::vector<VkCommandBuffer> cmds; // Place to hold a lot of buffers
std::vector<VkCommandBuffer> cmd2s; // Place to hold a lot of 2nd buffers
VkPipelineLayout pipeline_layout;
......@@ -510,7 +509,7 @@ VkBool32 demo_check_layers(const std::vector<layer_properties> &layer_props,
void init_connection(struct sample_info &info);
void init_window(struct sample_info &info);
void init_swapchain_extension(struct sample_info &info);
void init_command_pool(struct sample_info &info);
void init_command_pool(struct sample_info &info, VkCommandPoolCreateFlags cmd_pool_create_flags);
void init_command_buffer(struct sample_info &info);
void init_command_buffer_array(struct sample_info &info, int numBuffers);
void init_command_buffer2_array(struct sample_info &info, int numBuffers);
......@@ -562,6 +561,9 @@ void destroy_swap_chain(struct sample_info &info);
void destroy_command_buffer(struct sample_info &info);
void destroy_command_buffer_array(struct sample_info &info, int numBuffers);
void destroy_command_buffer2_array(struct sample_info &info, int numBuffers);
void reset_command_buffer2_array(struct sample_info &info,
VkCommandBufferResetFlags cmd_buffer_reset_flags);
void reset_command_pool(struct sample_info &info, VkCommandPoolResetFlags cmd_pool_reset_flags);
void destroy_command_pool(struct sample_info &info);
void destroy_device(struct sample_info &info);
void destroy_instance(struct sample_info &info);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment