aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/Benchmark.h5
-rw-r--r--gyp/visualbench.gyp20
-rw-r--r--tools/VisualBench/VisualBench.cpp81
-rw-r--r--tools/VisualBench/VisualBench.h9
-rw-r--r--tools/VisualBench/VisualBenchmarkStream.cpp103
-rw-r--r--tools/VisualBench/VisualBenchmarkStream.h37
-rw-r--r--tools/VisualBench/VisualSKPBench.cpp33
-rw-r--r--tools/VisualBench/VisualSKPBench.h37
8 files changed, 266 insertions, 59 deletions
diff --git a/bench/Benchmark.h b/bench/Benchmark.h
index 34ea92b4a2..751172685e 100644
--- a/bench/Benchmark.h
+++ b/bench/Benchmark.h
@@ -102,6 +102,11 @@ public:
fClearMask = clearMask;
}
+ /*
+ * Benches which support running in a visual mode can advertise this functionality
+ */
+ virtual bool isVisual() { return false; }
+
protected:
virtual void setupPaint(SkPaint* paint);
diff --git a/gyp/visualbench.gyp b/gyp/visualbench.gyp
index 874b0aafa0..4bf559ae98 100644
--- a/gyp/visualbench.gyp
+++ b/gyp/visualbench.gyp
@@ -11,19 +11,37 @@
{
'target_name': 'visualbench',
'type': 'executable',
+ 'includes' : [
+ 'gmslides.gypi',
+ ],
'include_dirs' : [
+ '../bench',
'../include/gpu',
'../src/core',
+ '../src/effects',
'../src/images',
],
'sources': [
+ '../gm/gm.cpp',
'../tools/VisualBench/VisualBench.h',
'../tools/VisualBench/VisualBench.cpp',
+ '../tools/VisualBench/VisualBenchmarkStream.h',
+ '../tools/VisualBench/VisualBenchmarkStream.cpp',
+ '../tools/VisualBench/VisualSKPBench.h',
+ '../tools/VisualBench/VisualSKPBench.cpp',
+ '<!@(python find.py ../bench "*.cpp")',
+ ],
+ 'sources!': [
+ '../bench/nanobench.cpp',
+ '../bench/nanobenchAndroid.cpp',
],
'dependencies': [
- 'flags.gyp:flags_common',
+ 'etc1.gyp:libetc1',
+ 'flags.gyp:flags',
+ 'gputest.gyp:skgputest',
'skia_lib.gyp:skia_lib',
'tools.gyp:proc_stats',
+ 'tools.gyp:sk_tool_utils',
'tools.gyp:timer',
'views.gyp:views',
],
diff --git a/tools/VisualBench/VisualBench.cpp b/tools/VisualBench/VisualBench.cpp
index ac53b43167..6501aa36b2 100644
--- a/tools/VisualBench/VisualBench.cpp
+++ b/tools/VisualBench/VisualBench.cpp
@@ -12,7 +12,6 @@
#include "SkApplication.h"
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
-#include "SkCommonFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkGr.h"
@@ -35,6 +34,7 @@ DEFINE_double(flushMs, 20, "Target flush time in millseconds.");
DEFINE_double(loopMs, 5, "Target loop time in millseconds.");
DEFINE_int32(msaa, 0, "Number of msaa samples.");
DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
+DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
static SkString humanize(double ms) {
if (FLAGS_verbose) {
@@ -47,34 +47,19 @@ static SkString humanize(double ms) {
VisualBench::VisualBench(void* hwnd, int argc, char** argv)
: INHERITED(hwnd)
- , fCurrentPictureIdx(-1)
, fCurrentSample(0)
, fCurrentFrame(0)
, fFlushes(1)
, fLoops(1)
- , fState(kPreWarmLoops_State) {
+ , fState(kPreWarmLoops_State)
+ , fBenchmark(NULL) {
SkCommandLineFlags::Parse(argc, argv);
- // read all the skp file names.
- for (int i = 0; i < FLAGS_skps.count(); i++) {
- if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
- fRecords.push_back().fFilename = FLAGS_skps[i];
- } else {
- SkOSFile::Iter it(FLAGS_skps[i], ".skp");
- SkString path;
- while (it.next(&path)) {
- fRecords.push_back().fFilename = SkOSPath::Join(FLAGS_skps[i], path.c_str());;
- }
- }
- }
-
- if (fRecords.empty()) {
- SkDebugf("no valid skps found\n");
- }
-
this->setTitle();
this->setupBackend();
+ fBenchmarkStream.reset(SkNEW(VisualBenchmarkStream));
+
// Print header
SkDebugf("curr/maxrss\tloops\tflushes\tmin\tmedian\tmean\tmax\tstddev\tbench\n");
}
@@ -134,22 +119,20 @@ void VisualBench::setupRenderTarget() {
inline void VisualBench::renderFrame(SkCanvas* canvas) {
for (int flush = 0; flush < fFlushes; flush++) {
- for (int loop = 0; loop < fLoops; loop++) {
- canvas->drawPicture(fPicture);
- }
+ fBenchmark->draw(fLoops, canvas);
canvas->flush();
}
INHERITED::present();
}
void VisualBench::printStats() {
- const SkTArray<double>& measurements = fRecords[fCurrentPictureIdx].fMeasurements;
- SkString shortName = SkOSPath::Basename(fRecords[fCurrentPictureIdx].fFilename.c_str());
+ const SkTArray<double>& measurements = fRecords.back().fMeasurements;
+ const char* shortName = fBenchmark->getUniqueName();
if (FLAGS_verbose) {
for (int i = 0; i < measurements.count(); i++) {
SkDebugf("%s ", HUMANIZE(measurements[i]));
}
- SkDebugf("%s\n", shortName.c_str());
+ SkDebugf("%s\n", shortName);
} else {
SkASSERT(measurements.count());
Stats stats(measurements);
@@ -164,37 +147,28 @@ void VisualBench::printStats() {
HUMANIZE(stats.mean),
HUMANIZE(stats.max),
stdDevPercent,
- shortName.c_str());
+ shortName);
}
}
-bool VisualBench::advanceRecordIfNecessary() {
- if (fPicture) {
+bool VisualBench::advanceRecordIfNecessary(SkCanvas* canvas) {
+ if (fBenchmark) {
return true;
}
- ++fCurrentPictureIdx;
- while (true) {
- if (fCurrentPictureIdx >= fRecords.count()) {
- return false;
- }
- if (this->loadPicture()) {
- return true;
- }
- fRecords.removeShuffle(fCurrentPictureIdx);
- }
-}
-bool VisualBench::loadPicture() {
- const char* fileName = fRecords[fCurrentPictureIdx].fFilename.c_str();
- SkFILEStream stream(fileName);
- if (stream.isValid()) {
- fPicture.reset(SkPicture::CreateFromStream(&stream));
- if (SkToBool(fPicture)) {
- return true;
- }
+ while ((fBenchmark = fBenchmarkStream->next()) &&
+ (SkCommandLineFlags::ShouldSkip(FLAGS_match, fBenchmark->getUniqueName()) ||
+ !fBenchmark->isSuitableFor(Benchmark::kGPU_Backend))) {}
+
+ if (!fBenchmark) {
+ return false;
}
- SkDebugf("couldn't load picture at \"%s\"\n", fileName);
- return false;
+
+ canvas->clear(0xffffffff);
+ fBenchmark->preDraw();
+ fBenchmark->perCanvasPreDraw(canvas);
+ fRecords.push_back();
+ return true;
}
void VisualBench::preWarm(State nextState) {
@@ -209,7 +183,7 @@ void VisualBench::preWarm(State nextState) {
}
void VisualBench::draw(SkCanvas* canvas) {
- if (!this->advanceRecordIfNecessary()) {
+ if (!this->advanceRecordIfNecessary(canvas)) {
this->closeWindow();
return;
}
@@ -251,12 +225,13 @@ void VisualBench::draw(SkCanvas* canvas) {
case kTiming_State: {
if (fCurrentFrame >= FLAGS_frames) {
fTimer.end();
- fRecords[fCurrentPictureIdx].fMeasurements.push_back(
+ fRecords.back().fMeasurements.push_back(
fTimer.fWall / (FLAGS_frames * fLoops * fFlushes));
if (fCurrentSample++ >= FLAGS_samples) {
fState = kPreWarmLoops_State;
this->printStats();
- fPicture.reset(NULL);
+ fBenchmark->perCanvasPostDraw(canvas);
+ fBenchmark = NULL;
fCurrentSample = 0;
fFlushes = 1;
fLoops = 1;
diff --git a/tools/VisualBench/VisualBench.h b/tools/VisualBench/VisualBench.h
index 332fe82eb4..683151f566 100644
--- a/tools/VisualBench/VisualBench.h
+++ b/tools/VisualBench/VisualBench.h
@@ -15,6 +15,7 @@
#include "SkString.h"
#include "SkSurface.h"
#include "Timer.h"
+#include "VisualBenchmarkStream.h"
#include "gl/SkGLContext.h"
class GrContext;
@@ -44,12 +45,10 @@ private:
void setupRenderTarget();
bool onHandleChar(SkUnichar unichar) override;
void printStats();
- bool loadPicture();
- bool advanceRecordIfNecessary();
+ bool advanceRecordIfNecessary(SkCanvas*);
inline void renderFrame(SkCanvas*);
struct Record {
- SkString fFilename;
SkTArray<double> fMeasurements;
};
@@ -61,8 +60,6 @@ private:
};
void preWarm(State nextState);
- int fCurrentPictureIdx;
- SkAutoTUnref<SkPicture> fPicture;
int fCurrentSample;
int fCurrentFrame;
int fFlushes;
@@ -70,6 +67,8 @@ private:
SkTArray<Record> fRecords;
WallTimer fTimer;
State fState;
+ SkAutoTDelete<VisualBenchmarkStream> fBenchmarkStream;
+ Benchmark* fBenchmark;
// support framework
SkAutoTUnref<SkSurface> fSurface;
diff --git a/tools/VisualBench/VisualBenchmarkStream.cpp b/tools/VisualBench/VisualBenchmarkStream.cpp
new file mode 100644
index 0000000000..841fb5d11b
--- /dev/null
+++ b/tools/VisualBench/VisualBenchmarkStream.cpp
@@ -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.
+ *
+ */
+
+#include <VisualBench/VisualBenchmarkStream.h>
+#include "GMBench.h"
+#include "SkOSFile.h"
+#include "SkPictureRecorder.h"
+#include "SkStream.h"
+#include "VisualSKPBench.h"
+
+DEFINE_string2(match, m, NULL,
+ "[~][^]substring[$] [...] of bench name to run.\n"
+ "Multiple matches may be separated by spaces.\n"
+ "~ causes a matching bench to always be skipped\n"
+ "^ requires the start of the bench to match\n"
+ "$ requires the end of the bench to match\n"
+ "^ and $ requires an exact match\n"
+ "If a bench does not match any list entry,\n"
+ "it is skipped unless some list entry starts with ~");
+DEFINE_string(skps, "skps", "Directory to read skps from.");
+
+VisualBenchmarkStream::VisualBenchmarkStream()
+ : fBenches(BenchRegistry::Head())
+ , fGMs(skiagm::GMRegistry::Head())
+ , fSourceType(NULL)
+ , fBenchType(NULL)
+ , fCurrentSKP(0) {
+ for (int i = 0; i < FLAGS_skps.count(); i++) {
+ if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
+ fSKPs.push_back() = FLAGS_skps[i];
+ } else {
+ SkOSFile::Iter it(FLAGS_skps[i], ".skp");
+ SkString path;
+ while (it.next(&path)) {
+ fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
+ }
+ }
+ }
+}
+
+bool VisualBenchmarkStream::ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
+ // Not strictly necessary, as it will be checked again later,
+ // but helps to avoid a lot of pointless work if we're going to skip it.
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
+ return false;
+ }
+
+ SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
+ if (stream.get() == NULL) {
+ SkDebugf("Could not read %s.\n", path);
+ return false;
+ }
+
+ pic->reset(SkPicture::CreateFromStream(stream.get()));
+ if (pic->get() == NULL) {
+ SkDebugf("Could not read %s as an SkPicture.\n", path);
+ return false;
+ }
+ return true;
+}
+
+Benchmark* VisualBenchmarkStream::next() {
+ while (fBenches) {
+ Benchmark* bench = fBenches->factory()(NULL);
+ fBenches = fBenches->next();
+ if (bench->isVisual()) {
+ fSourceType = "bench";
+ fBenchType = "micro";
+ return bench;
+ }
+ }
+
+ while (fGMs) {
+ SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
+ fGMs = fGMs->next();
+ if (gm->runAsBench()) {
+ fSourceType = "gm";
+ fBenchType = "micro";
+ return SkNEW_ARGS(GMBench, (gm.detach()));
+ }
+ }
+
+ // Render skps
+ while (fCurrentSKP < fSKPs.count()) {
+ const SkString& path = fSKPs[fCurrentSKP++];
+ SkAutoTUnref<SkPicture> pic;
+ if (!ReadPicture(path.c_str(), &pic)) {
+ continue;
+ }
+
+ SkString name = SkOSPath::Basename(path.c_str());
+ fSourceType = "skp";
+ fBenchType = "playback";
+ return SkNEW_ARGS(VisualSKPBench, (name.c_str(), pic.get()));
+ }
+
+ return NULL;
+}
diff --git a/tools/VisualBench/VisualBenchmarkStream.h b/tools/VisualBench/VisualBenchmarkStream.h
new file mode 100644
index 0000000000..4c6a1eb262
--- /dev/null
+++ b/tools/VisualBench/VisualBenchmarkStream.h
@@ -0,0 +1,37 @@
+/*
+ * 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 VisualBenchmarkStream_DEFINED
+#define VisualBenchmarkStream_DEFINED
+
+#include "Benchmark.h"
+#include "gm.h"
+#include "SkCommandLineFlags.h"
+#include "SkPicture.h"
+
+DECLARE_string(match);
+
+class VisualBenchmarkStream {
+public:
+ VisualBenchmarkStream();
+
+ static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic);
+
+ Benchmark* next();
+
+private:
+ const BenchRegistry* fBenches;
+ const skiagm::GMRegistry* fGMs;
+ SkTArray<SkString> fSKPs;
+
+ const char* fSourceType; // What we're benching: bench, GM, SKP, ...
+ const char* fBenchType; // How we bench it: micro, playback, ...
+ int fCurrentSKP;
+};
+
+#endif
diff --git a/tools/VisualBench/VisualSKPBench.cpp b/tools/VisualBench/VisualSKPBench.cpp
new file mode 100644
index 0000000000..9e03d71488
--- /dev/null
+++ b/tools/VisualBench/VisualSKPBench.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 "VisualSKPBench.h"
+
+VisualSKPBench::VisualSKPBench(const char* name, const SkPicture* pic)
+ : fPic(SkRef(pic))
+ , fName(name) {
+ fUniqueName.printf("%s", name);
+}
+
+const char* VisualSKPBench::onGetName() {
+ return fName.c_str();
+}
+
+const char* VisualSKPBench::onGetUniqueName() {
+ return fUniqueName.c_str();
+}
+
+bool VisualSKPBench::isSuitableFor(Backend backend) {
+ return backend != kNonRendering_Backend;
+}
+
+void VisualSKPBench::onDraw(const int loops, SkCanvas* canvas) {
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPicture(fPic);
+ }
+}
diff --git a/tools/VisualBench/VisualSKPBench.h b/tools/VisualBench/VisualSKPBench.h
new file mode 100644
index 0000000000..cc35deaac5
--- /dev/null
+++ b/tools/VisualBench/VisualSKPBench.h
@@ -0,0 +1,37 @@
+/*
+ * 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 VisualSKPBench_DEFINED
+#define VisualSKPBench_DEFINED
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+
+/**
+ * Runs an SkPicture as a benchmark by repeatedly drawing it
+ */
+class VisualSKPBench : public Benchmark {
+public:
+ VisualSKPBench(const char* name, const SkPicture*);
+
+protected:
+ const char* onGetName() override;
+ const char* onGetUniqueName() override;
+ bool isSuitableFor(Backend backend) override;
+ void onDraw(const int loops, SkCanvas* canvas) override;
+
+private:
+ SkAutoTUnref<const SkPicture> fPic;
+ SkString fName;
+ SkString fUniqueName;
+
+ typedef Benchmark INHERITED;
+};
+
+#endif