diff --git a/src/tests/perf_tests/BufferUploadPerf.cpp b/src/tests/perf_tests/BufferUploadPerf.cpp index f0161c509c..8eeb1ca377 100644 --- a/src/tests/perf_tests/BufferUploadPerf.cpp +++ b/src/tests/perf_tests/BufferUploadPerf.cpp @@ -87,7 +87,8 @@ namespace { class BufferUploadPerf : public DawnPerfTestWithParams { public: BufferUploadPerf() - : DawnPerfTestWithParams(kNumIterations), data(static_cast(GetParam().uploadSize)) { + : DawnPerfTestWithParams(kNumIterations, 1), + data(static_cast(GetParam().uploadSize)) { } ~BufferUploadPerf() override = default; @@ -138,12 +139,6 @@ void BufferUploadPerf::Step() { queue.Submit(1, &commands); } break; } - - // Wait for the GPU in this batch of iterations. - // If we don't wait, we can't properly compute the number of steps to run during - // calibration. - // The wait time gets amortized over the kNumIterations. - WaitForGPU(); } TEST_P(BufferUploadPerf, Run) { diff --git a/src/tests/perf_tests/DawnPerfTest.cpp b/src/tests/perf_tests/DawnPerfTest.cpp index d916ff2074..ea2ed5b4cb 100644 --- a/src/tests/perf_tests/DawnPerfTest.cpp +++ b/src/tests/perf_tests/DawnPerfTest.cpp @@ -73,8 +73,13 @@ unsigned int DawnPerfTestEnvironment::OverrideStepsToRun() const { return mOverrideStepsToRun; } -DawnPerfTestBase::DawnPerfTestBase(DawnTestBase* test, unsigned int iterationsPerStep) - : mTest(test), mIterationsPerStep(iterationsPerStep), mTimer(utils::CreateTimer()) { +DawnPerfTestBase::DawnPerfTestBase(DawnTestBase* test, + unsigned int iterationsPerStep, + unsigned int maxStepsInFlight) + : mTest(test), + mIterationsPerStep(iterationsPerStep), + mMaxStepsInFlight(maxStepsInFlight), + mTimer(utils::CreateTimer()) { } DawnPerfTestBase::~DawnPerfTestBase() = default; @@ -83,26 +88,6 @@ void DawnPerfTestBase::AbortTest() { mRunning = false; } -void DawnPerfTestBase::WaitForGPU() { - dawn::FenceDescriptor desc = {}; - desc.initialValue = 0; - - dawn::Fence fence = mTest->queue.CreateFence(&desc); - mTest->queue.Signal(fence, 1); - - bool done = false; - fence.OnCompletion(1, - [](DawnFenceCompletionStatus status, void* userdata) { - ASSERT_EQ(status, DAWN_FENCE_COMPLETION_STATUS_SUCCESS); - *reinterpret_cast(userdata) = true; - }, - &done); - - while (!done) { - mTest->WaitABit(); - } -} - void DawnPerfTestBase::RunTest() { if (gTestEnv->OverrideStepsToRun() == 0) { // Run to compute the approximate number of steps to perform. @@ -137,11 +122,22 @@ void DawnPerfTestBase::RunTest() { void DawnPerfTestBase::DoRunLoop(double maxRunTime) { mNumStepsPerformed = 0; mRunning = true; + + dawn::FenceDescriptor desc = {}; + uint64_t signaledFenceValue = 0; + dawn::Fence fence = mTest->queue.CreateFence(&desc); + mTimer->Start(); // This loop can be canceled by calling AbortTest(). while (mRunning) { + // Wait if there are too many steps in flight on the GPU. + while (signaledFenceValue - fence.GetCompletedValue() >= mMaxStepsInFlight) { + mTest->WaitABit(); + } Step(); + mTest->queue.Signal(fence, ++signaledFenceValue); + if (mRunning) { ++mNumStepsPerformed; if (mTimer->GetElapsedTime() > maxRunTime) { @@ -152,6 +148,11 @@ void DawnPerfTestBase::DoRunLoop(double maxRunTime) { } } + // Wait for all GPU commands to complete. + while (signaledFenceValue != fence.GetCompletedValue()) { + mTest->WaitABit(); + } + mTimer->Stop(); } diff --git a/src/tests/perf_tests/DawnPerfTest.h b/src/tests/perf_tests/DawnPerfTest.h index b858a8781d..f5f12a4a8a 100644 --- a/src/tests/perf_tests/DawnPerfTest.h +++ b/src/tests/perf_tests/DawnPerfTest.h @@ -47,15 +47,20 @@ class DawnPerfTestBase { static constexpr unsigned int kNumTrials = 3; public: - DawnPerfTestBase(DawnTestBase* test, unsigned int iterationsPerStep); + // Perf test results are reported as the amortized time of |mStepsToRun| * |mIterationsPerStep|. + // A test deriving from |DawnPerfTestBase| must call the base contructor with + // |iterationsPerStep| appropriately to reflect the amount of work performed. + // |maxStepsInFlight| may be used to mimic having multiple frames or workloads in flight which + // is common with double or triple buffered applications. + DawnPerfTestBase(DawnTestBase* test, + unsigned int iterationsPerStep, + unsigned int maxStepsInFlight); virtual ~DawnPerfTestBase(); protected: // Call if the test step was aborted and the test should stop running. void AbortTest(); - void WaitForGPU(); - void RunTest(); void PrintResult(const std::string& trace, double value, @@ -74,7 +79,8 @@ class DawnPerfTestBase { DawnTestBase* mTest; bool mRunning = false; - unsigned int mIterationsPerStep; + const unsigned int mIterationsPerStep; + const unsigned int mMaxStepsInFlight; unsigned int mStepsToRun = 0; unsigned int mNumStepsPerformed = 0; uint64_t mGPUTimeNs = 0; // TODO(enga): Measure GPU time with timing queries. @@ -84,8 +90,9 @@ class DawnPerfTestBase { template class DawnPerfTestWithParams : public DawnTestWithParams, public DawnPerfTestBase { protected: - DawnPerfTestWithParams(unsigned int iterationsPerStep) - : DawnTestWithParams(), DawnPerfTestBase(this, iterationsPerStep) { + DawnPerfTestWithParams(unsigned int iterationsPerStep, unsigned int maxStepsInFlight) + : DawnTestWithParams(), + DawnPerfTestBase(this, iterationsPerStep, maxStepsInFlight) { } ~DawnPerfTestWithParams() override = default; };