Some cleanups of VisualBench
BUG=skia:
Review URL: https://codereview.chromium.org/1240633005
diff --git a/tools/VisualBench/VisualBench.cpp b/tools/VisualBench/VisualBench.cpp
index d8713e7..895569c 100644
--- a/tools/VisualBench/VisualBench.cpp
+++ b/tools/VisualBench/VisualBench.cpp
@@ -170,15 +170,24 @@
canvas->clear(0xffffffff);
fBenchmark->preDraw();
- fBenchmark->perCanvasPreDraw(canvas);
fRecords.push_back();
return true;
}
+inline void VisualBench::nextState(State nextState) {
+ fState = nextState;
+}
+
+void VisualBench::perCanvasPreDraw(SkCanvas* canvas, State nextState) {
+ fBenchmark->perCanvasPreDraw(canvas);
+ fCurrentFrame = 0;
+ this->nextState(nextState);
+}
+
void VisualBench::preWarm(State nextState) {
if (fCurrentFrame >= FLAGS_gpuFrameLag) {
// we currently time across all frames to make sure we capture all GPU work
- fState = nextState;
+ this->nextState(nextState);
fCurrentFrame = 0;
fTimer.start();
} else {
@@ -193,33 +202,20 @@
}
this->renderFrame(canvas);
switch (fState) {
+ case kPreWarmLoopsPerCanvasPreDraw_State: {
+ this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
+ break;
+ }
case kPreWarmLoops_State: {
this->preWarm(kTuneLoops_State);
break;
}
case kTuneLoops_State: {
- if (1 << 30 == fLoops) {
- // We're about to wrap. Something's wrong with the bench.
- SkDebugf("InnerLoops wrapped\n");
- fLoops = 0;
- } else {
- fTimer.end();
- double elapsed = fTimer.fWall;
- if (elapsed > FLAGS_loopMs) {
- fState = kPreWarmTiming_State;
-
- // Scale back the number of loops
- fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsed);
- fFlushes = (int)ceil(FLAGS_flushMs / elapsed);
- } else {
- fState = kPreWarmLoops_State;
- fLoops *= 2;
- }
-
- fCurrentFrame = 0;
- fTimer = WallTimer();
- this->resetContext();
- }
+ this->tuneLoops();
+ break;
+ }
+ case kPreWarmTimingPerCanvasPreDraw_State: {
+ this->perCanvasPreDraw(canvas, kPreWarmTiming_State);
break;
}
case kPreWarmTiming_State: {
@@ -227,27 +223,7 @@
break;
}
case kTiming_State: {
- if (fCurrentFrame >= FLAGS_frames) {
- fTimer.end();
- fRecords.back().fMeasurements.push_back(
- fTimer.fWall / (FLAGS_frames * fLoops * fFlushes));
- if (fCurrentSample++ >= FLAGS_samples) {
- fState = kPreWarmLoops_State;
- this->printStats();
- fBenchmark->perCanvasPostDraw(canvas);
- fBenchmark.reset(NULL);
- fCurrentSample = 0;
- fFlushes = 1;
- fLoops = 1;
- } else {
- fState = kPreWarmTiming_State;
- }
- fTimer = WallTimer();
- this->resetContext();
- fCurrentFrame = 0;
- } else {
- fCurrentFrame++;
- }
+ this->timing(canvas);
break;
}
}
@@ -256,6 +232,70 @@
this->inval(NULL);
}
+inline double VisualBench::elapsed() {
+ fTimer.end();
+ return fTimer.fWall;
+}
+
+void VisualBench::resetTimingState() {
+ fCurrentFrame = 0;
+ fTimer = WallTimer();
+ this->resetContext();
+}
+
+void VisualBench::scaleLoops(double elapsedMs) {
+ // Scale back the number of loops
+ fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs);
+ fFlushes = (int)ceil(FLAGS_flushMs / elapsedMs);
+}
+
+inline void VisualBench::tuneLoops() {
+ if (1 << 30 == fLoops) {
+ // We're about to wrap. Something's wrong with the bench.
+ SkDebugf("InnerLoops wrapped\n");
+ fLoops = 0;
+ } else {
+ double elapsedMs = this->elapsed();
+ if (elapsedMs > FLAGS_loopMs) {
+ this->scaleLoops(elapsedMs);
+ this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
+ } else {
+ fLoops *= 2;
+ this->nextState(kPreWarmLoops_State);
+ }
+ this->resetTimingState();
+ }
+}
+
+void VisualBench::recordMeasurement() {
+ double measurement = this->elapsed() / (FLAGS_frames * fLoops * fFlushes);
+ fRecords.back().fMeasurements.push_back(measurement);
+}
+
+void VisualBench::postDraw(SkCanvas* canvas) {
+ fBenchmark->perCanvasPostDraw(canvas);
+ fBenchmark.reset(NULL);
+ fCurrentSample = 0;
+ fFlushes = 1;
+ fLoops = 1;
+}
+
+inline void VisualBench::timing(SkCanvas* canvas) {
+ if (fCurrentFrame >= FLAGS_frames) {
+ this->recordMeasurement();
+ if (fCurrentSample++ >= FLAGS_samples) {
+ this->printStats();
+ this->postDraw(canvas);
+ this->nextState(kPreWarmLoopsPerCanvasPreDraw_State);
+ } else {
+ this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
+ }
+ this->resetTimingState();
+ } else {
+ fCurrentFrame++;
+ }
+}
+
void VisualBench::onSizeChange() {
this->setupRenderTarget();
}
diff --git a/tools/VisualBench/VisualBench.h b/tools/VisualBench/VisualBench.h
index b8cd2bd..9843693 100644
--- a/tools/VisualBench/VisualBench.h
+++ b/tools/VisualBench/VisualBench.h
@@ -39,6 +39,34 @@
void onSizeChange() override;
private:
+ /*
+ * The heart of visual bench is an event driven timing loop.
+ * kPreWarmLoopsPerCanvasPreDraw_State: Before we begin timing, Benchmarks have a hook to
+ * access the canvas. Then we prewarm before the autotune
+ * loops step.
+ * kPreWarmLoops_State: We prewarm the gpu before auto tuning to enter a steady
+ * work state
+ * kTuneLoops_State: Then we tune the loops of the benchmark to ensure we
+ * are doing a measurable amount of work
+ * kPreWarmTimingPerCanvasPreDraw_State: Because reset the context after tuning loops to ensure
+ * coherent state, we need to give the benchmark
+ * another hook
+ * kPreWarmTiming_State: We prewarm the gpu again to enter a steady state
+ * kTiming_State: Finally we time the benchmark. When finished timing
+ * if we have enough samples then we'll start the next
+ * benchmark in the kPreWarmLoopsPerCanvasPreDraw_State.
+ * otherwise, we enter the
+ * kPreWarmTimingPerCanvasPreDraw_State for another sample
+ * In either case we reset the context.
+ */
+ enum State {
+ kPreWarmLoopsPerCanvasPreDraw_State,
+ kPreWarmLoops_State,
+ kTuneLoops_State,
+ kPreWarmTimingPerCanvasPreDraw_State,
+ kPreWarmTiming_State,
+ kTiming_State,
+ };
void setTitle();
bool setupBackend();
void resetContext();
@@ -47,19 +75,21 @@
void printStats();
bool advanceRecordIfNecessary(SkCanvas*);
inline void renderFrame(SkCanvas*);
+ inline void nextState(State);
+ void perCanvasPreDraw(SkCanvas*, State);
+ void preWarm(State nextState);
+ void scaleLoops(double elapsedMs);
+ inline void tuneLoops();
+ inline void timing(SkCanvas*);
+ inline double elapsed();
+ void resetTimingState();
+ void postDraw(SkCanvas*);
+ void recordMeasurement();
struct Record {
SkTArray<double> fMeasurements;
};
- enum State {
- kPreWarmLoops_State,
- kTuneLoops_State,
- kPreWarmTiming_State,
- kTiming_State,
- };
- void preWarm(State nextState);
-
int fCurrentSample;
int fCurrentFrame;
int fFlushes;