Add benchmarkstream to visualbench
BUG=skia: Review URL: https://codereview.chromium.org/1215033002
This commit is contained in:
parent
2757e3f09d
commit
962cc98eb4
@ -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);
|
||||
|
||||
|
@ -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',
|
||||
],
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
103
tools/VisualBench/VisualBenchmarkStream.cpp
Normal file
103
tools/VisualBench/VisualBenchmarkStream.cpp
Normal file
@ -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;
|
||||
}
|
37
tools/VisualBench/VisualBenchmarkStream.h
Normal file
37
tools/VisualBench/VisualBenchmarkStream.h
Normal file
@ -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
|
33
tools/VisualBench/VisualSKPBench.cpp
Normal file
33
tools/VisualBench/VisualSKPBench.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
37
tools/VisualBench/VisualSKPBench.h
Normal file
37
tools/VisualBench/VisualSKPBench.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user