perf_tests: Replace WaitForGPU with maxStepsInFlight argument

The current BufferUpload perf test calls WaitForGPU at the end of
every step to time how long the batch of uploads took. Future tests
will want to have multiple Steps or Frames in flight to mimic real
applications that use double or triple buffering. This patch removes
WaitForGPU and adds a |maxStepsInFlight| argument which a test can
set to configure how many steps can be running on the GPU.
For the BufferUpload tests, this is still 1.

Bug: dawn:208
Change-Id: I95ae12b2358e0283088205bd2ffd20532ea62871
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12302
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng 2019-10-17 00:15:07 +00:00 committed by Commit Bot service account
parent 7f426898ef
commit 31bde95857
3 changed files with 38 additions and 35 deletions

View File

@ -87,7 +87,8 @@ namespace {
class BufferUploadPerf : public DawnPerfTestWithParams<BufferUploadParams> {
public:
BufferUploadPerf()
: DawnPerfTestWithParams(kNumIterations), data(static_cast<size_t>(GetParam().uploadSize)) {
: DawnPerfTestWithParams(kNumIterations, 1),
data(static_cast<size_t>(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) {

View File

@ -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<bool*>(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();
}

View File

@ -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 <typename Params = DawnTestParam>
class DawnPerfTestWithParams : public DawnTestWithParams<Params>, public DawnPerfTestBase {
protected:
DawnPerfTestWithParams(unsigned int iterationsPerStep)
: DawnTestWithParams<Params>(), DawnPerfTestBase(this, iterationsPerStep) {
DawnPerfTestWithParams(unsigned int iterationsPerStep, unsigned int maxStepsInFlight)
: DawnTestWithParams<Params>(),
DawnPerfTestBase(this, iterationsPerStep, maxStepsInFlight) {
}
~DawnPerfTestWithParams() override = default;
};