aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2015-10-05 07:23:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-05 07:23:30 -0700
commit98d2e2f095d9a5b784a32cfc2c34b30735dedcc3 (patch)
tree7aeb07fb604ad1f7647226132da6ba32c4d4e746
parentd8982d7e923d8ab6c7a4ff9456c5ce631ae11423 (diff)
Factor out VisualBench timing code into a helper class
-rw-r--r--bench/BigPathBench.cpp8
-rw-r--r--tools/BigPathBench.inc (renamed from bench/BigPathBench.inc)1
-rw-r--r--tools/VisualBench/TimingStateMachine.cpp122
-rw-r--r--tools/VisualBench/TimingStateMachine.h103
-rw-r--r--tools/VisualBench/VisualBenchmarkStream.cpp39
-rw-r--r--tools/VisualBench/VisualBenchmarkStream.h1
-rw-r--r--tools/VisualBench/VisualLightweightBenchModule.cpp182
-rw-r--r--tools/VisualBench/VisualLightweightBenchModule.h48
-rw-r--r--tools/sk_tool_utils.cpp4
-rw-r--r--tools/sk_tool_utils.h2
10 files changed, 292 insertions, 218 deletions
diff --git a/bench/BigPathBench.cpp b/bench/BigPathBench.cpp
index 0ed8fc51e3..f39fd73693 100644
--- a/bench/BigPathBench.cpp
+++ b/bench/BigPathBench.cpp
@@ -8,11 +8,7 @@
#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkPath.h"
-#include "SkString.h"
-
-static void make_path(SkPath& path) {
- #include "BigPathBench.inc"
-}
+#include "sk_tool_utils.h"
enum Align {
kLeft_Align,
@@ -47,7 +43,7 @@ protected:
}
void onDelayedSetup() override {
- make_path(fPath);
+ sk_tool_utils::make_big_path(fPath);
}
void onDraw(int loops, SkCanvas* canvas) override {
diff --git a/bench/BigPathBench.inc b/tools/BigPathBench.inc
index d2d147ff40..c52bd32353 100644
--- a/bench/BigPathBench.inc
+++ b/tools/BigPathBench.inc
@@ -1,3 +1,4 @@
+// Inspired by crbug.com/455429
path.moveTo(-1113, 81);
path.lineTo(-1113, 83);
path.lineTo(-1113, 82);
diff --git a/tools/VisualBench/TimingStateMachine.cpp b/tools/VisualBench/TimingStateMachine.cpp
new file mode 100644
index 0000000000..c7f2f13470
--- /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;
+ }
+}
+
diff --git a/tools/VisualBench/TimingStateMachine.h b/tools/VisualBench/TimingStateMachine.h
new file mode 100644
index 0000000000..69ea24337f
--- /dev/null
+++ b/tools/VisualBench/TimingStateMachine.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#ifndef TimingStateMachine_DEFINED
+#define TimingStateMachine_DEFINED
+
+#include "Benchmark.h"
+#include "SkTArray.h"
+#include "Timer.h"
+
+class SkCanvas;
+
+/*
+ * Manages a timer via a state machine. Can be used by modules to time benchmarks
+ *
+ * Clients call nextFrame, and must handle any requests from the timing state machine, specifically
+ * to reset. When kTimingFinished_ParentEvents is returned, then lastMeasurement() will return the
+ * timing and loops() will return the number of loops used to time.
+ *
+ * A client may continue timing the same benchmark indefinitely. To advance to the next
+ * benchmark, the client should call nextBenchmark.
+ */
+class TimingStateMachine {
+public:
+ TimingStateMachine();
+
+ enum ParentEvents {
+ kReset_ParentEvents,
+ kTiming_ParentEvents,
+ kTimingFinished_ParentEvents,// This implies parent can read lastMeasurement() and must
+ // reset
+ };
+
+ ParentEvents nextFrame(SkCanvas* canvas, Benchmark* benchmark);
+
+ /*
+ * The caller should call this when they are ready to move to the next benchmark. The caller
+ * must call this with the *last* benchmark so post draw hooks can be invoked
+ */
+ void nextBenchmark(SkCanvas*, Benchmark*);
+
+
+ /*
+ * When TimingStateMachine returns kTimingFinished_ParentEvents, then the owner can call
+ * lastMeasurement() to get the time
+ */
+ double lastMeasurement() const { return fLastMeasurement; }
+
+ int loops() const { return fLoops; }
+
+private:
+ /*
+ * The heart of the timing state machine 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,
+ };
+
+ inline void nextState(State);
+ ParentEvents perCanvasPreDraw(SkCanvas*, Benchmark*, State);
+ ParentEvents preWarm(State nextState);
+ inline ParentEvents tuneLoops();
+ inline ParentEvents timing(SkCanvas*, Benchmark*);
+ inline double elapsed();
+ void resetTimingState();
+ void postDraw(SkCanvas*, Benchmark*);
+ void recordMeasurement();
+
+ int fCurrentFrame;
+ int fLoops;
+ double fLastMeasurement;
+ WallTimer fTimer;
+ State fState;
+};
+
+#endif
diff --git a/tools/VisualBench/VisualBenchmarkStream.cpp b/tools/VisualBench/VisualBenchmarkStream.cpp
index 9e1ce36fbc..c520eeed05 100644
--- a/tools/VisualBench/VisualBenchmarkStream.cpp
+++ b/tools/VisualBench/VisualBenchmarkStream.cpp
@@ -10,8 +10,10 @@
#include "CpuWrappedBenchmark.h"
#include "GMBench.h"
#include "SkOSFile.h"
+#include "SkPath.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
+#include "sk_tool_utils.h"
#include "VisualSKPBench.h"
DEFINE_bool(cpu, false, "Run in CPU mode?");
@@ -26,12 +28,41 @@ DEFINE_string2(match, m, nullptr,
"it is skipped unless some list entry starts with ~");
DEFINE_string(skps, "skps", "Directory to read skps from.");
+// We draw a big nonAA path to warmup the gpu / cpu
+#include "SkPerlinNoiseShader.h"
+class WarmupBench : public Benchmark {
+public:
+ WarmupBench() {
+ sk_tool_utils::make_big_path(fPath);
+ }
+private:
+ const char* onGetName() override { return "warmupbench"; }
+ void onDraw(int loops, SkCanvas* canvas) override {
+ // We draw a big path to warm up the cpu, and then use perlin noise shader to warm up the
+ // gpu
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(2);
+
+ SkPaint perlinPaint;
+ perlinPaint.setShader(SkPerlinNoiseShader::CreateTurbulence(0.1f, 0.1f, 1, 0,
+ nullptr))->unref();
+ SkRect rect = SkRect::MakeLTRB(0., 0., 400., 400.);
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPath(fPath, paint);
+ canvas->drawRect(rect, perlinPaint);
+ }
+ }
+ SkPath fPath;
+};
+
VisualBenchmarkStream::VisualBenchmarkStream()
: fBenches(BenchRegistry::Head())
, fGMs(skiagm::GMRegistry::Head())
, fSourceType(nullptr)
, fBenchType(nullptr)
- , fCurrentSKP(0) {
+ , fCurrentSKP(0)
+ , fIsWarmedUp(false) {
for (int i = 0; i < FLAGS_skps.count(); i++) {
if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
fSKPs.push_back() = FLAGS_skps[i];
@@ -67,7 +98,13 @@ bool VisualBenchmarkStream::ReadPicture(const char* path, SkAutoTUnref<SkPicture
}
Benchmark* VisualBenchmarkStream::next() {
+ if (!fIsWarmedUp) {
+ fIsWarmedUp = true;
+ return new WarmupBench;
+ }
+
Benchmark* bench;
+
// skips non matching benches
while ((bench = this->innerNext()) &&
(SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName()) ||
diff --git a/tools/VisualBench/VisualBenchmarkStream.h b/tools/VisualBench/VisualBenchmarkStream.h
index e8d2cbe524..9e5d4590cb 100644
--- a/tools/VisualBench/VisualBenchmarkStream.h
+++ b/tools/VisualBench/VisualBenchmarkStream.h
@@ -34,6 +34,7 @@ private:
const char* fSourceType; // What we're benching: bench, GM, SKP, ...
const char* fBenchType; // How we bench it: micro, playback, ...
int fCurrentSKP;
+ bool fIsWarmedUp;
};
#endif
diff --git a/tools/VisualBench/VisualLightweightBenchModule.cpp b/tools/VisualBench/VisualLightweightBenchModule.cpp
index cdb9318c4b..fa99caa1fb 100644
--- a/tools/VisualBench/VisualLightweightBenchModule.cpp
+++ b/tools/VisualBench/VisualLightweightBenchModule.cpp
@@ -25,18 +25,13 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
// Between samples we reset context
// Between frames we swap buffers
-
-DEFINE_int32(maxWarmupFrames, 100, "maxmium frames to try and tune for sane timings");
-DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
-DEFINE_int32(samples, 10, "Number of times to time each skp.");
-DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample.");
-DEFINE_double(loopMs, 5, "Target loop time in millseconds.");
DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
DEFINE_string(key, "",
"Space-separated key/value pairs to add to JSON identifying this builder.");
DEFINE_string(properties, "",
"Space-separated key/value pairs to add to JSON identifying this run.");
+DEFINE_int32(samples, 10, "Number of times to time each skp.");
static SkString humanize(double ms) {
if (FLAGS_verbose) {
@@ -47,34 +42,8 @@ static SkString humanize(double ms) {
#define HUMANIZE(time) humanize(time).c_str()
-// We draw a big nonAA path to warmup the gpu / cpu
-class WarmupBench : public Benchmark {
-public:
- WarmupBench() {
- make_path(fPath);
- }
-private:
- static void make_path(SkPath& path) {
- #include "BigPathBench.inc"
- }
- const char* onGetName() override { return "warmupbench"; }
- void onDraw(int loops, SkCanvas* canvas) override {
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(2);
- for (int i = 0; i < loops; i++) {
- canvas->drawPath(fPath, paint);
- }
- }
- SkPath fPath;
-};
-
VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner)
: fCurrentSample(0)
- , fCurrentFrame(0)
- , fLoops(1)
- , fState(kWarmup_State)
- , fBenchmark(nullptr)
, fOwner(SkRef(owner))
, fResults(new ResultsWriter) {
fBenchmarkStream.reset(new VisualBenchmarkStream);
@@ -106,7 +75,7 @@ VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner)
}
inline void VisualLightweightBenchModule::renderFrame(SkCanvas* canvas) {
- fBenchmark->draw(fLoops, canvas);
+ fBenchmark->draw(fTSM.loops(), canvas);
canvas->flush();
fOwner->present();
}
@@ -140,7 +109,7 @@ void VisualLightweightBenchModule::printStats() {
SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\n",
sk_tools::getCurrResidentSetSizeMB(),
sk_tools::getMaxResidentSetSizeMB(),
- fLoops,
+ fTSM.loops(),
HUMANIZE(stats.min),
HUMANIZE(stats.median),
HUMANIZE(stats.mean),
@@ -152,12 +121,6 @@ void VisualLightweightBenchModule::printStats() {
}
bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) {
- if (!fBenchmark && fState == kWarmup_State) {
- fOwner->clear(canvas, SK_ColorWHITE, 2);
- fBenchmark.reset(new WarmupBench);
- return true;
- }
-
if (fBenchmark) {
return true;
}
@@ -178,49 +141,6 @@ bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) {
return true;
}
-inline void VisualLightweightBenchModule::nextState(State nextState) {
- fState = nextState;
-}
-
-void VisualLightweightBenchModule::perCanvasPreDraw(SkCanvas* canvas, State nextState) {
- fBenchmark->perCanvasPreDraw(canvas);
- fBenchmark->preDraw(canvas);
- fCurrentFrame = 0;
- this->nextState(nextState);
-}
-
-void VisualLightweightBenchModule::warmup(SkCanvas* canvas) {
- if (fCurrentFrame >= FLAGS_maxWarmupFrames) {
- this->nextState(kPreWarmLoopsPerCanvasPreDraw_State);
- fBenchmark.reset(nullptr);
- this->resetTimingState();
- fLoops = 1;
- } else {
- bool isEven = (fCurrentFrame++ % 2) == 0;
- if (isEven) {
- fTimer.start();
- } else {
- double elapsedMs = this->elapsed();
- if (elapsedMs < FLAGS_loopMs) {
- fLoops *= 2;
- }
- fTimer = WallTimer();
- fOwner->reset();
- }
- }
-}
-
-void VisualLightweightBenchModule::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++;
- }
-}
-
void VisualLightweightBenchModule::draw(SkCanvas* canvas) {
if (!this->advanceRecordIfNecessary(canvas)) {
SkDebugf("Exiting VisualBench successfully\n");
@@ -228,93 +148,25 @@ void VisualLightweightBenchModule::draw(SkCanvas* canvas) {
return;
}
this->renderFrame(canvas);
- switch (fState) {
- case kWarmup_State: {
- this->warmup(canvas);
- break;
- }
- case kPreWarmLoopsPerCanvasPreDraw_State: {
- this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
- break;
- }
- case kPreWarmLoops_State: {
- this->preWarm(kTuneLoops_State);
- break;
- }
- case kTuneLoops_State: {
- this->tuneLoops();
- break;
- }
- case kPreWarmTimingPerCanvasPreDraw_State: {
- this->perCanvasPreDraw(canvas, kPreWarmTiming_State);
+ TimingStateMachine::ParentEvents event = fTSM.nextFrame(canvas, fBenchmark);
+ switch (event) {
+ case TimingStateMachine::kReset_ParentEvents:
+ fOwner->reset();
break;
- }
- case kPreWarmTiming_State: {
- this->preWarm(kTiming_State);
+ case TimingStateMachine::kTiming_ParentEvents:
break;
- }
- case kTiming_State: {
- this->timing(canvas);
+ case TimingStateMachine::kTimingFinished_ParentEvents:
+ fOwner->reset();
+ fRecords.back().fMeasurements.push_back(fTSM.lastMeasurement());
+ if (++fCurrentSample > FLAGS_samples) {
+ this->printStats();
+ fTSM.nextBenchmark(canvas, fBenchmark);
+ fCurrentSample = 0;
+ fBenchmark.reset(nullptr);
+ }
break;
- }
- }
-}
-
-inline double VisualLightweightBenchModule::elapsed() {
- fTimer.end();
- return fTimer.fWall;
-}
-
-void VisualLightweightBenchModule::resetTimingState() {
- fCurrentFrame = 0;
- fTimer = WallTimer();
- fOwner->reset();
-}
-
-inline void VisualLightweightBenchModule::tuneLoops() {
- if (1 << 30 == fLoops) {
- // We're about to wrap. Something's wrong with the bench.
- SkDebugf("InnerLoops wrapped\n");
- fLoops = 1;
- } else {
- double elapsedMs = this->elapsed();
- if (elapsedMs > FLAGS_loopMs) {
- this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
- } else {
- fLoops *= 2;
- this->nextState(kPreWarmLoops_State);
- }
- this->resetTimingState();
}
-}
-void VisualLightweightBenchModule::recordMeasurement() {
- double measurement = this->elapsed() / (FLAGS_frames * fLoops);
- fRecords.back().fMeasurements.push_back(measurement);
-}
-
-void VisualLightweightBenchModule::postDraw(SkCanvas* canvas) {
- fBenchmark->postDraw(canvas);
- fBenchmark->perCanvasPostDraw(canvas);
- fBenchmark.reset(nullptr);
- fCurrentSample = 0;
- fLoops = 1;
-}
-
-inline void VisualLightweightBenchModule::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++;
- }
}
bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) {
diff --git a/tools/VisualBench/VisualLightweightBenchModule.h b/tools/VisualBench/VisualLightweightBenchModule.h
index 1a30875c61..ffa109dc49 100644
--- a/tools/VisualBench/VisualLightweightBenchModule.h
+++ b/tools/VisualBench/VisualLightweightBenchModule.h
@@ -13,7 +13,7 @@
#include "ResultsWriter.h"
#include "SkPicture.h"
-#include "Timer.h"
+#include "TimingStateMachine.h"
#include "VisualBench.h"
#include "VisualBenchmarkStream.h"
@@ -32,65 +32,21 @@ public:
bool onHandleChar(SkUnichar c) override;
private:
- /*
- * The heart of visual bench is an event driven timing loop.
- * kWarmup_State: We run a dummy bench to let things settle on startup
- * 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 {
- kWarmup_State,
- kPreWarmLoopsPerCanvasPreDraw_State,
- kPreWarmLoops_State,
- kTuneLoops_State,
- kPreWarmTimingPerCanvasPreDraw_State,
- kPreWarmTiming_State,
- kTiming_State,
- };
void setTitle();
bool setupBackend();
void setupRenderTarget();
void printStats();
bool advanceRecordIfNecessary(SkCanvas*);
inline void renderFrame(SkCanvas*);
- inline void nextState(State);
- void perCanvasPreDraw(SkCanvas*, State);
- void preWarm(State nextState);
- inline void tuneLoops();
- inline void timing(SkCanvas*);
- inline double elapsed();
- void resetTimingState();
- void postDraw(SkCanvas*);
- void recordMeasurement();
- void warmup(SkCanvas* canvas);
struct Record {
SkTArray<double> fMeasurements;
};
-
int fCurrentSample;
- int fCurrentFrame;
- int fLoops;
SkTArray<Record> fRecords;
- WallTimer fTimer;
- State fState;
SkAutoTDelete<VisualBenchmarkStream> fBenchmarkStream;
SkAutoTUnref<Benchmark> fBenchmark;
+ TimingStateMachine fTSM;
// support framework
SkAutoTUnref<VisualBench> fOwner;
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index aab068cbd7..710c204271 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -345,4 +345,8 @@ void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
}
}
+void make_big_path(SkPath& path) {
+ #include "BigPathBench.inc"
+}
+
} // namespace sk_tool_utils
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index b20c60ba76..e0ad1df3ec 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -17,6 +17,7 @@
class SkBitmap;
class SkCanvas;
class SkPaint;
+class SkPath;
class SkShader;
class SkTestFont;
class SkTextBlobBuilder;
@@ -133,6 +134,7 @@ namespace sk_tool_utils {
void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);
+ void make_big_path(SkPath& path);
} // namespace sk_tool_utils
#endif // sk_tool_utils_DEFINED