Index: tools/VisualBench/TimingStateMachine.cpp |
diff --git a/tools/VisualBench/TimingStateMachine.cpp b/tools/VisualBench/TimingStateMachine.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c7f2f134709ea9fda4a4c171b28951989e073c0d |
--- /dev/null |
+++ b/tools/VisualBench/TimingStateMachine.cpp |
@@ -0,0 +1,122 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "TimingStateMachine.h" |
+ |
+#include "SkCanvas.h" |
+#include "SkCommandLineFlags.h" |
+ |
+DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU is allowed to lag."); |
+DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample."); |
+DEFINE_double(loopMs, 5, "Each benchmark will be tuned until it takes loopsMs millseconds."); |
+ |
+TimingStateMachine::TimingStateMachine() |
+ : fCurrentFrame(0) |
+ , fLoops(1) |
+ , fLastMeasurement(0.) |
+ , fState(kPreWarmLoopsPerCanvasPreDraw_State) { |
+} |
+ |
+TimingStateMachine::ParentEvents TimingStateMachine::nextFrame(SkCanvas* canvas, |
+ Benchmark* benchmark) { |
+ switch (fState) { |
+ case kPreWarmLoopsPerCanvasPreDraw_State: |
+ return this->perCanvasPreDraw(canvas, benchmark, kPreWarmLoops_State); |
+ case kPreWarmLoops_State: |
+ return this->preWarm(kTuneLoops_State); |
+ case kTuneLoops_State: |
+ return this->tuneLoops(); |
+ case kPreWarmTimingPerCanvasPreDraw_State: |
+ return this->perCanvasPreDraw(canvas, benchmark, kPreWarmTiming_State); |
+ case kPreWarmTiming_State: |
+ return this->preWarm(kTiming_State); |
+ case kTiming_State: |
+ return this->timing(canvas, benchmark); |
+ } |
+ SkFAIL("Incomplete switch\n"); |
+ return kTiming_ParentEvents; |
+} |
+ |
+inline void TimingStateMachine::nextState(State nextState) { |
+ fState = nextState; |
+} |
+ |
+TimingStateMachine::ParentEvents TimingStateMachine::perCanvasPreDraw(SkCanvas* canvas, |
+ Benchmark* benchmark, |
+ State nextState) { |
+ benchmark->perCanvasPreDraw(canvas); |
+ benchmark->preDraw(canvas); |
+ fCurrentFrame = 0; |
+ this->nextState(nextState); |
+ return kTiming_ParentEvents; |
+} |
+ |
+TimingStateMachine::ParentEvents TimingStateMachine::preWarm(State nextState) { |
+ if (fCurrentFrame >= FLAGS_gpuFrameLag) { |
+ // we currently time across all frames to make sure we capture all GPU work |
+ this->nextState(nextState); |
+ fCurrentFrame = 0; |
+ fTimer.start(); |
+ } else { |
+ fCurrentFrame++; |
+ } |
+ return kTiming_ParentEvents; |
+} |
+ |
+inline double TimingStateMachine::elapsed() { |
+ fTimer.end(); |
+ return fTimer.fWall; |
+} |
+ |
+void TimingStateMachine::resetTimingState() { |
+ fCurrentFrame = 0; |
+ fTimer = WallTimer(); |
+} |
+ |
+inline TimingStateMachine::ParentEvents TimingStateMachine::tuneLoops() { |
+ if (1 << 30 == fLoops) { |
+ // We're about to wrap. Something's wrong with the bench. |
+ SkDebugf("InnerLoops wrapped\n"); |
+ fLoops = 1; |
+ return kTiming_ParentEvents; |
+ } else { |
+ double elapsedMs = this->elapsed(); |
+ if (elapsedMs > FLAGS_loopMs) { |
+ this->nextState(kPreWarmTimingPerCanvasPreDraw_State); |
+ } else { |
+ fLoops *= 2; |
+ this->nextState(kPreWarmLoops_State); |
+ } |
+ this->resetTimingState(); |
+ return kReset_ParentEvents; |
+ } |
+} |
+ |
+void TimingStateMachine::recordMeasurement() { |
+ fLastMeasurement = this->elapsed() / (FLAGS_frames * fLoops); |
+} |
+ |
+void TimingStateMachine::nextBenchmark(SkCanvas* canvas, Benchmark* benchmark) { |
+ benchmark->postDraw(canvas); |
+ benchmark->perCanvasPostDraw(canvas); |
+ fLoops = 1; |
+ this->nextState(kPreWarmLoopsPerCanvasPreDraw_State); |
+} |
+ |
+inline TimingStateMachine::ParentEvents TimingStateMachine::timing(SkCanvas* canvas, |
+ Benchmark* benchmark) { |
+ if (fCurrentFrame >= FLAGS_frames) { |
+ this->recordMeasurement(); |
+ this->resetTimingState(); |
+ this->nextState(kPreWarmTimingPerCanvasPreDraw_State); |
+ return kTimingFinished_ParentEvents; |
+ } else { |
+ fCurrentFrame++; |
+ return kTiming_ParentEvents; |
+ } |
+} |
+ |