Report data from bench_pictures in the same fashion as bench.
Move SkBenchLogger into separate files and make bench_pictures use it. Remove sk_tools::print_msg, since SkBenchLogger is now used instead. Combine picture_benchmark with bench_pictures, since that is the only project that uses it. Refactor the aggregator for bench timer data into its own class and make bench_pictures use it. Consolidate the various virtual PictureBenchmark::run functions into one for reuse. BUG=https://code.google.com/p/skia/issues/detail?id=822 Review URL: https://codereview.appspot.com/6488086 git-svn-id: http://skia.googlecode.com/svn/trunk@5432 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
2d8edaf175
commit
9a4125283a
30
bench/SkBenchLogger.cpp
Normal file
30
bench/SkBenchLogger.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkBenchLogger.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
SkBenchLogger::SkBenchLogger()
|
||||
: fFileStream(NULL) {}
|
||||
|
||||
SkBenchLogger::~SkBenchLogger() {
|
||||
if (fFileStream) {
|
||||
SkDELETE(fFileStream);
|
||||
}
|
||||
}
|
||||
|
||||
bool SkBenchLogger::SetLogFile(const char *file) {
|
||||
fFileStream = SkNEW_ARGS(SkFILEWStream, (file));
|
||||
return fFileStream->isValid();
|
||||
}
|
||||
|
||||
void SkBenchLogger::fileWrite(const char msg[], size_t size) {
|
||||
if (fFileStream && fFileStream->isValid()) {
|
||||
fFileStream->write(msg, size);
|
||||
}
|
||||
}
|
77
bench/SkBenchLogger.h
Normal file
77
bench/SkBenchLogger.h
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkBenchLogger_DEFINED
|
||||
#define SkBenchLogger_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
#include "SkString.h"
|
||||
|
||||
class SkFILEWStream;
|
||||
|
||||
/**
|
||||
* Class that allows logging to a file while simultaneously logging to stdout/stderr.
|
||||
*/
|
||||
class SkBenchLogger {
|
||||
public:
|
||||
SkBenchLogger();
|
||||
|
||||
/**
|
||||
* Not virtual, since this class is not intended to be subclassed.
|
||||
*/
|
||||
~SkBenchLogger();
|
||||
|
||||
/**
|
||||
* Specify a file to write progress logs to. Unless this is called with a valid file path,
|
||||
* SkBenchLogger will only write to stdout/stderr.
|
||||
*/
|
||||
bool SetLogFile(const char file[]);
|
||||
|
||||
/**
|
||||
* Log an error to stderr, taking a C style string as input.
|
||||
*/
|
||||
void logError(const char msg[]) { this->nativeLogError(msg); }
|
||||
|
||||
/**
|
||||
* Log an error to stderr, taking an SkString as input.
|
||||
*/
|
||||
void logError(const SkString& str) { this->nativeLogError(str.c_str()); }
|
||||
|
||||
/**
|
||||
* Log the progress of the bench tool to both stdout and the log file specified by SetLogFile,
|
||||
* if any, taking a C style string as input.
|
||||
*/
|
||||
void logProgress(const char msg[]) {
|
||||
this->nativeLogProgress(msg);
|
||||
this->fileWrite(msg, strlen(msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the progress of the bench tool to both stdout and the log file specified by SetLogFile,
|
||||
* if any, taking an SkString as input.
|
||||
*/
|
||||
void logProgress(const SkString& str) {
|
||||
this->nativeLogProgress(str.c_str());
|
||||
this->fileWrite(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
void nativeLogError(const char msg[]) { SkDebugf("%s", msg); }
|
||||
void nativeLogProgress(const char msg[]) { SkDebugf("%s", msg); }
|
||||
#else
|
||||
void nativeLogError(const char msg[]) { fprintf(stderr, "%s", msg); }
|
||||
void nativeLogProgress(const char msg[]) { printf("%s", msg); }
|
||||
#endif
|
||||
|
||||
void fileWrite(const char msg[], size_t size);
|
||||
|
||||
SkFILEWStream* fFileStream;
|
||||
};
|
||||
|
||||
#endif // SkBenchLogger_DEFINED
|
108
bench/TimerData.cpp
Normal file
108
bench/TimerData.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "TimerData.h"
|
||||
|
||||
#include "BenchTimer.h"
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
TimerData::TimerData(const SkString& perIterTimeFormat, const SkString& normalTimeFormat)
|
||||
: fWallStr(" msecs = ")
|
||||
, fTruncatedWallStr(" Wmsecs = ")
|
||||
, fCpuStr(" cmsecs = ")
|
||||
, fTruncatedCpuStr(" Cmsecs = ")
|
||||
, fGpuStr(" gmsecs = ")
|
||||
, fWallSum(0.0)
|
||||
, fWallMin(numeric_limits<double>::max())
|
||||
, fTruncatedWallSum(0.0)
|
||||
, fTruncatedWallMin(numeric_limits<double>::max())
|
||||
, fCpuSum(0.0)
|
||||
, fCpuMin(numeric_limits<double>::max())
|
||||
, fTruncatedCpuSum(0.0)
|
||||
, fTruncatedCpuMin(numeric_limits<double>::max())
|
||||
, fGpuSum(0.0)
|
||||
, fGpuMin(numeric_limits<double>::max())
|
||||
, fPerIterTimeFormat(perIterTimeFormat)
|
||||
, fNormalTimeFormat(normalTimeFormat)
|
||||
{}
|
||||
|
||||
static double Min(double a, double b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
void TimerData::appendTimes(BenchTimer* timer, bool last) {
|
||||
SkASSERT(timer != NULL);
|
||||
SkString formatString(fPerIterTimeFormat);
|
||||
if (!last) {
|
||||
formatString.append(",");
|
||||
}
|
||||
const char* format = formatString.c_str();
|
||||
fWallStr.appendf(format, timer->fWall);
|
||||
fCpuStr.appendf(format, timer->fCpu);
|
||||
fTruncatedWallStr.appendf(format, timer->fTruncatedWall);
|
||||
fTruncatedCpuStr.appendf(format, timer->fTruncatedCpu);
|
||||
fGpuStr.appendf(format, timer->fGpu);
|
||||
|
||||
// Store the minimum values. We do not need to special case the first time since we initialized
|
||||
// to max double.
|
||||
fWallMin = Min(fWallMin, timer->fWall);
|
||||
fCpuMin = Min(fCpuMin, timer->fCpu);
|
||||
fTruncatedWallMin = Min(fTruncatedWallMin, timer->fTruncatedWall);
|
||||
fTruncatedCpuMin = Min(fTruncatedCpuMin, timer->fTruncatedCpu);
|
||||
fGpuMin = Min(fGpuMin, timer->fGpu);
|
||||
|
||||
// Tally the sum of each timer type.
|
||||
fWallSum += timer->fWall;
|
||||
fCpuSum += timer->fCpu;
|
||||
fTruncatedWallSum += timer->fTruncatedWall;
|
||||
fTruncatedCpuSum += timer->fTruncatedCpu;
|
||||
fGpuSum += timer->fGpu;
|
||||
|
||||
}
|
||||
|
||||
SkString TimerData::getResult(bool logPerIter, bool printMin, int repeatDraw,
|
||||
const char *configName, bool showWallTime, bool showTruncatedWallTime,
|
||||
bool showCpuTime, bool showTruncatedCpuTime, bool showGpuTime) {
|
||||
// output each repeat (no average) if logPerIter is set,
|
||||
// otherwise output only the average
|
||||
if (!logPerIter) {
|
||||
const char* format = fNormalTimeFormat.c_str();
|
||||
fWallStr.set(" msecs = ");
|
||||
fWallStr.appendf(format, printMin ? fWallMin : fWallSum / repeatDraw);
|
||||
fCpuStr.set(" cmsecs = ");
|
||||
fCpuStr.appendf(format, printMin ? fCpuMin : fCpuSum / repeatDraw);
|
||||
fTruncatedWallStr.set(" Wmsecs = ");
|
||||
fTruncatedWallStr.appendf(format,
|
||||
printMin ? fTruncatedWallMin : fTruncatedWallSum / repeatDraw);
|
||||
fTruncatedCpuStr.set(" Cmsecs = ");
|
||||
fTruncatedCpuStr.appendf(format,
|
||||
printMin ? fTruncatedCpuMin : fTruncatedCpuSum / repeatDraw);
|
||||
fGpuStr.set(" gmsecs = ");
|
||||
fGpuStr.appendf(format, printMin ? fGpuMin : fGpuSum / repeatDraw);
|
||||
}
|
||||
SkString str;
|
||||
str.printf(" %4s:", configName);
|
||||
if (showWallTime) {
|
||||
str += fWallStr;
|
||||
}
|
||||
if (showTruncatedWallTime) {
|
||||
str += fTruncatedWallStr;
|
||||
}
|
||||
if (showCpuTime) {
|
||||
str += fCpuStr;
|
||||
}
|
||||
if (showTruncatedCpuTime) {
|
||||
str += fTruncatedCpuStr;
|
||||
}
|
||||
if (showGpuTime && fGpuSum > 0) {
|
||||
str += fGpuStr;
|
||||
}
|
||||
return str;
|
||||
}
|
46
bench/TimerData.h
Normal file
46
bench/TimerData.h
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef TimerData_DEFINED
|
||||
#define TimerData_DEFINED
|
||||
|
||||
#include "SkString.h"
|
||||
|
||||
class BenchTimer;
|
||||
|
||||
class TimerData {
|
||||
public:
|
||||
TimerData(const SkString& perIterTimeFormat, const SkString& normalTimeFormat);
|
||||
|
||||
/**
|
||||
* Append the value from each timer in BenchTimer to our various strings, and update the
|
||||
* minimum and sum times.
|
||||
* @param BenchTimer Must not be null.
|
||||
* @param last True if this is the last set of times to add.
|
||||
*/
|
||||
void appendTimes(BenchTimer*, bool last);
|
||||
SkString getResult(bool logPerIter, bool printMin, int repeatDraw, const char* configName,
|
||||
bool showWallTime, bool showTruncatedWallTime, bool showCpuTime,
|
||||
bool showTruncatedCpuTime, bool showGpuTime);
|
||||
private:
|
||||
SkString fWallStr;
|
||||
SkString fTruncatedWallStr;
|
||||
SkString fCpuStr;
|
||||
SkString fTruncatedCpuStr;
|
||||
SkString fGpuStr;
|
||||
double fWallSum, fWallMin;
|
||||
double fTruncatedWallSum, fTruncatedWallMin;
|
||||
double fCpuSum, fCpuMin;
|
||||
double fTruncatedCpuSum, fTruncatedCpuMin;
|
||||
double fGpuSum, fGpuMin;
|
||||
|
||||
SkString fPerIterTimeFormat;
|
||||
SkString fNormalTimeFormat;
|
||||
};
|
||||
|
||||
#endif // TimerData_DEFINED
|
@ -21,6 +21,7 @@
|
||||
#include "SkGpuDevice.h"
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
#include "SkBenchLogger.h"
|
||||
#include "SkBenchmark.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDeferredCanvas.h"
|
||||
@ -30,56 +31,8 @@
|
||||
#include "SkImageEncoder.h"
|
||||
#include "SkNWayCanvas.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
|
||||
template <typename T> const T& Min(const T& a, const T& b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
class SkBenchLogger {
|
||||
public:
|
||||
SkBenchLogger() : fFileStream(NULL) {}
|
||||
~SkBenchLogger() {
|
||||
if (fFileStream)
|
||||
SkDELETE(fFileStream);
|
||||
}
|
||||
|
||||
bool SetLogFile(const char file[]) {
|
||||
fFileStream = SkNEW_ARGS(SkFILEWStream, (file));
|
||||
return fFileStream->isValid();
|
||||
}
|
||||
|
||||
void logError(const char msg[]) { nativeLogError(msg); }
|
||||
void logError(const SkString& str) { nativeLogError(str.c_str()); }
|
||||
|
||||
void logProgress(const char msg[]) {
|
||||
nativeLogProgress(msg);
|
||||
fileWrite(msg, strlen(msg));
|
||||
}
|
||||
void logProgress(const SkString& str) {
|
||||
nativeLogProgress(str.c_str());
|
||||
fileWrite(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
void nativeLogError(const char msg[]) { SkDebugf("%s", msg); }
|
||||
void nativeLogProgress(const char msg[]) { SkDebugf("%s", msg); }
|
||||
#else
|
||||
void nativeLogError(const char msg[]) { fprintf(stderr, "%s", msg); }
|
||||
void nativeLogProgress(const char msg[]) { printf("%s", msg); }
|
||||
#endif
|
||||
|
||||
void fileWrite(const char msg[], size_t size) {
|
||||
if (fFileStream && fFileStream->isValid())
|
||||
fFileStream->write(msg, size);
|
||||
}
|
||||
SkFILEWStream* fFileStream;
|
||||
|
||||
} logger;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "TimerData.h"
|
||||
|
||||
enum benchModes {
|
||||
kNormal_benchModes,
|
||||
@ -400,7 +353,7 @@ static void help() {
|
||||
" [-scale] [-clip] [-min] [-forceAA 1|0] [-forceFilter 1|0]\n"
|
||||
" [-forceDither 1|0] [-forceBlend 1|0] [-strokeWidth width]\n"
|
||||
" [-match name] [-mode normal|deferred|record|picturerecord]\n"
|
||||
" [-config 8888|565|GPU|ANGLE|NULLGPU] [-Dfoo bar]\n"
|
||||
" [-config 8888|565|GPU|ANGLE|NULLGPU] [-Dfoo bar] [-logFile filename]\n"
|
||||
" [-h|--help]");
|
||||
SkDebugf("\n\n");
|
||||
SkDebugf(" -o outDir : Image of each bench will be put in outDir.\n");
|
||||
@ -429,7 +382,7 @@ static void help() {
|
||||
" record, Benchmark the time to record to an SkPicture;\n"
|
||||
" picturerecord, Benchmark the time to do record from a \n"
|
||||
" SkPicture to a SkPicture.\n");
|
||||
SkDebugf(" -logFile : destination for writing log output, in addition to stdout.\n");
|
||||
SkDebugf(" -logFile filename : destination for writing log output, in addition to stdout.\n");
|
||||
#if SK_SUPPORT_GPU
|
||||
SkDebugf(" -config 8888|565|GPU|ANGLE|NULLGPU : "
|
||||
"Run bench in corresponding config mode.\n");
|
||||
@ -478,6 +431,8 @@ int main (int argc, char * const argv[]) {
|
||||
SkTDArray<int> configs;
|
||||
bool userConfig = false;
|
||||
|
||||
SkBenchLogger logger;
|
||||
|
||||
char* const* stop = argv + argc;
|
||||
for (++argv; argv < stop; ++argv) {
|
||||
if (strcmp(*argv, "-o") == 0) {
|
||||
@ -634,6 +589,7 @@ int main (int argc, char * const argv[]) {
|
||||
if (!logger.SetLogFile(*argv)) {
|
||||
SkString str;
|
||||
str.printf("Could not open %s for writing.", *argv);
|
||||
logger.logError(str);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@ -864,16 +820,7 @@ int main (int argc, char * const argv[]) {
|
||||
}
|
||||
|
||||
// record timer values for each repeat, and their sum
|
||||
SkString fWallStr(" msecs = ");
|
||||
SkString fTruncatedWallStr(" Wmsecs = ");
|
||||
SkString fCpuStr(" cmsecs = ");
|
||||
SkString fTruncatedCpuStr(" Cmsecs = ");
|
||||
SkString fGpuStr(" gmsecs = ");
|
||||
double fWallSum = 0.0, fWallMin;
|
||||
double fTruncatedWallSum = 0.0, fTruncatedWallMin;
|
||||
double fCpuSum = 0.0, fCpuMin;
|
||||
double fTruncatedCpuSum = 0.0, fTruncatedCpuMin;
|
||||
double fGpuSum = 0.0, fGpuMin;
|
||||
TimerData timerData(perIterTimeformat, normalTimeFormat);
|
||||
for (int i = 0; i < repeatDraw; i++) {
|
||||
if ((benchMode == kRecord_benchModes
|
||||
|| benchMode == kPictureRecord_benchModes)) {
|
||||
@ -904,84 +851,14 @@ int main (int argc, char * const argv[]) {
|
||||
// have completed
|
||||
timer.end();
|
||||
|
||||
if (i == repeatDraw - 1) {
|
||||
// no comma after the last value
|
||||
fWallStr.appendf(perIterTimeformat.c_str(), timer.fWall);
|
||||
fCpuStr.appendf(perIterTimeformat.c_str(), timer.fCpu);
|
||||
fTruncatedWallStr.appendf(perIterTimeformat.c_str(), timer.fTruncatedWall);
|
||||
fTruncatedCpuStr.appendf(perIterTimeformat.c_str(), timer.fTruncatedCpu);
|
||||
fGpuStr.appendf(perIterTimeformat.c_str(), timer.fGpu);
|
||||
} else {
|
||||
fWallStr.appendf(perIterTimeformat.c_str(), timer.fWall);
|
||||
fWallStr.appendf(",");
|
||||
fCpuStr.appendf(perIterTimeformat.c_str(), timer.fCpu);
|
||||
fCpuStr.appendf(",");
|
||||
fTruncatedWallStr.appendf(perIterTimeformat.c_str(), timer.fTruncatedWall);
|
||||
fTruncatedWallStr.appendf(",");
|
||||
fTruncatedCpuStr.appendf(perIterTimeformat.c_str(), timer.fTruncatedCpu);
|
||||
fTruncatedCpuStr.appendf(",");
|
||||
fGpuStr.appendf(perIterTimeformat.c_str(), timer.fGpu);
|
||||
fGpuStr.appendf(",");
|
||||
}
|
||||
timerData.appendTimes(&timer, repeatDraw - 1 == i);
|
||||
|
||||
if (0 == i) {
|
||||
fWallMin = timer.fWall;
|
||||
fCpuMin = timer.fCpu;
|
||||
fTruncatedWallMin = timer.fTruncatedWall;
|
||||
fTruncatedCpuMin = timer.fTruncatedCpu;
|
||||
fGpuMin = timer.fGpu;
|
||||
} else {
|
||||
fWallMin = Min(fWallMin, timer.fWall);
|
||||
fCpuMin = Min(fCpuMin, timer.fCpu);
|
||||
fTruncatedWallMin = Min(fTruncatedWallMin, timer.fTruncatedWall);
|
||||
fTruncatedCpuMin = Min(fTruncatedCpuMin, timer.fTruncatedCpu);
|
||||
fGpuMin = Min(fGpuMin, timer.fGpu);
|
||||
}
|
||||
|
||||
fWallSum += timer.fWall;
|
||||
fCpuSum += timer.fCpu;
|
||||
fTruncatedWallSum += timer.fTruncatedWall;
|
||||
fTruncatedCpuSum += timer.fTruncatedCpu;
|
||||
fGpuSum += timer.fGpu;
|
||||
}
|
||||
if (repeatDraw > 1) {
|
||||
// output each repeat (no average) if logPerIter is set,
|
||||
// otherwise output only the average
|
||||
if (!logPerIter) {
|
||||
fWallStr.set(" msecs = ");
|
||||
fWallStr.appendf(normalTimeFormat.c_str(),
|
||||
printMin ? fWallMin : fWallSum / repeatDraw);
|
||||
fCpuStr.set(" cmsecs = ");
|
||||
fCpuStr.appendf(normalTimeFormat.c_str(),
|
||||
printMin ? fCpuMin : fCpuSum / repeatDraw);
|
||||
fTruncatedWallStr.set(" Wmsecs = ");
|
||||
fTruncatedWallStr.appendf(normalTimeFormat.c_str(),
|
||||
printMin ? fTruncatedWallMin : fTruncatedWallSum / repeatDraw);
|
||||
fTruncatedCpuStr.set(" Cmsecs = ");
|
||||
fTruncatedCpuStr.appendf(normalTimeFormat.c_str(),
|
||||
printMin ? fTruncatedCpuMin : fTruncatedCpuSum / repeatDraw);
|
||||
fGpuStr.set(" gmsecs = ");
|
||||
fGpuStr.appendf(normalTimeFormat.c_str(),
|
||||
printMin ? fGpuMin : fGpuSum / repeatDraw);
|
||||
}
|
||||
SkString str;
|
||||
str.printf(" %4s:", configName);
|
||||
if (timerWall) {
|
||||
str += fWallStr;
|
||||
}
|
||||
if (truncatedTimerWall) {
|
||||
str += fTruncatedWallStr;
|
||||
}
|
||||
if (timerCpu) {
|
||||
str += fCpuStr;
|
||||
}
|
||||
if (truncatedTimerCpu) {
|
||||
str += fTruncatedCpuStr;
|
||||
}
|
||||
if (timerGpu && glHelper && fGpuSum > 0) {
|
||||
str += fGpuStr;
|
||||
}
|
||||
logger.logProgress(str);
|
||||
SkString result = timerData.getResult(logPerIter, printMin, repeatDraw, configName,
|
||||
timerWall, truncatedTimerWall, timerCpu,
|
||||
truncatedTimerCpu, timerGpu && glHelper);
|
||||
logger.logProgress(result);
|
||||
}
|
||||
if (outDir.size() > 0) {
|
||||
saveFile(bench->getName(), configName, outDir.c_str(),
|
||||
|
@ -38,6 +38,11 @@
|
||||
'../bench/TextBench.cpp',
|
||||
'../bench/VertBench.cpp',
|
||||
'../bench/WriterBench.cpp',
|
||||
|
||||
'../bench/SkBenchLogger.h',
|
||||
'../bench/SkBenchLogger.cpp',
|
||||
'../bench/TimerData.h',
|
||||
'../bench/TimerData.cpp',
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,12 @@
|
||||
'target_name': 'bench_pictures',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'../bench/SkBenchLogger.h',
|
||||
'../bench/SkBenchLogger.cpp',
|
||||
'../bench/TimerData.h',
|
||||
'../bench/TimerData.cpp',
|
||||
'../tools/bench_pictures_main.cpp',
|
||||
'../tools/PictureBenchmark.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../bench',
|
||||
@ -95,27 +100,9 @@
|
||||
'effects.gyp:effects',
|
||||
'ports.gyp:ports',
|
||||
'tools.gyp:picture_utils',
|
||||
'tools.gyp:picture_benchmark',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'picture_benchmark',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'../tools/PictureBenchmark.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../bench',
|
||||
],
|
||||
'dependencies': [
|
||||
'core.gyp:core',
|
||||
'tools.gyp:picture_utils',
|
||||
'tools.gyp:picture_renderer',
|
||||
'bench.gyp:bench_timer',
|
||||
],
|
||||
'export_dependent_settings': [
|
||||
'tools.gyp:picture_renderer',
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'picture_renderer',
|
||||
|
@ -6,12 +6,14 @@
|
||||
*/
|
||||
|
||||
#include "SkTypes.h"
|
||||
#include "SkBenchLogger.h"
|
||||
#include "BenchTimer.h"
|
||||
#include "PictureBenchmark.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkString.h"
|
||||
#include "picture_utils.h"
|
||||
#include "TimerData.h"
|
||||
|
||||
namespace sk_tools {
|
||||
|
||||
@ -29,224 +31,67 @@ BenchTimer* PictureBenchmark::setupTimer() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void PipePictureBenchmark::run(SkPicture* pict) {
|
||||
void PictureBenchmark::logProgress(const char msg[]) {
|
||||
if (fLogger != NULL) {
|
||||
fLogger->logProgress(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void PictureBenchmark::run(SkPicture* pict) {
|
||||
SkASSERT(pict);
|
||||
if (NULL == pict) {
|
||||
return;
|
||||
}
|
||||
|
||||
fRenderer.init(pict);
|
||||
PictureRenderer* renderer = this->getRenderer();
|
||||
SkASSERT(renderer != NULL);
|
||||
if (NULL == renderer) {
|
||||
return;
|
||||
}
|
||||
renderer->init(pict);
|
||||
|
||||
// We throw this away to remove first time effects (such as paging in this
|
||||
// program)
|
||||
fRenderer.render();
|
||||
fRenderer.resetState();
|
||||
renderer->setup();
|
||||
renderer->render(false);
|
||||
renderer->resetState();
|
||||
|
||||
BenchTimer* timer = this->setupTimer();
|
||||
double wall_time = 0, truncated_wall_time = 0;
|
||||
bool usingGpu = false;
|
||||
#if SK_SUPPORT_GPU
|
||||
double gpu_time = 0;
|
||||
usingGpu = renderer->isUsingGpuDevice();
|
||||
#endif
|
||||
|
||||
TimerData timerData(renderer->getPerIterTimeFormat(), renderer->getNormalTimeFormat());
|
||||
for (int i = 0; i < fRepeats; ++i) {
|
||||
timer->start();
|
||||
fRenderer.render();
|
||||
timer->end();
|
||||
fRenderer.resetState();
|
||||
|
||||
wall_time += timer->fWall;
|
||||
truncated_wall_time += timer->fTruncatedWall;
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
gpu_time += timer->fGpu;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SkString result;
|
||||
result.printf("pipe: msecs = %6.2f", wall_time / fRepeats);
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
|
||||
}
|
||||
#endif
|
||||
result.appendf("\n");
|
||||
sk_tools::print_msg(result.c_str());
|
||||
|
||||
fRenderer.end();
|
||||
SkDELETE(timer);
|
||||
}
|
||||
|
||||
void RecordPictureBenchmark::run(SkPicture* pict) {
|
||||
SkASSERT(pict);
|
||||
if (NULL == pict) {
|
||||
return;
|
||||
}
|
||||
|
||||
BenchTimer* timer = setupTimer();
|
||||
double wall_time = 0, truncated_wall_time = 0;
|
||||
|
||||
for (int i = 0; i < fRepeats + 1; ++i) {
|
||||
SkPicture replayer;
|
||||
renderer->setup();
|
||||
|
||||
timer->start();
|
||||
SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());
|
||||
pict->draw(recorder);
|
||||
replayer.endRecording();
|
||||
renderer->render(false);
|
||||
timer->truncatedEnd();
|
||||
|
||||
// Finishes gl context
|
||||
renderer->resetState();
|
||||
timer->end();
|
||||
|
||||
// We want to ignore first time effects
|
||||
if (i > 0) {
|
||||
wall_time += timer->fWall;
|
||||
truncated_wall_time += timer->fTruncatedWall;
|
||||
}
|
||||
timerData.appendTimes(timer, fRepeats - 1 == i);
|
||||
}
|
||||
|
||||
SkString result;
|
||||
result.printf("record: msecs = %6.5f\n", wall_time / fRepeats);
|
||||
sk_tools::print_msg(result.c_str());
|
||||
|
||||
SkDELETE(timer);
|
||||
}
|
||||
|
||||
void SimplePictureBenchmark::run(SkPicture* pict) {
|
||||
SkASSERT(pict);
|
||||
if (NULL == pict) {
|
||||
return;
|
||||
}
|
||||
|
||||
fRenderer.init(pict);
|
||||
|
||||
// We throw this away to remove first time effects (such as paging in this
|
||||
// program)
|
||||
fRenderer.render();
|
||||
fRenderer.resetState();
|
||||
|
||||
|
||||
BenchTimer* timer = this->setupTimer();
|
||||
double wall_time = 0, truncated_wall_time = 0;
|
||||
#if SK_SUPPORT_GPU
|
||||
double gpu_time = 0;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < fRepeats; ++i) {
|
||||
timer->start();
|
||||
fRenderer.render();
|
||||
timer->end();
|
||||
fRenderer.resetState();
|
||||
|
||||
wall_time += timer->fWall;
|
||||
truncated_wall_time += timer->fTruncatedWall;
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
gpu_time += timer->fGpu;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SkString result;
|
||||
result.printf("simple: msecs = %6.2f", wall_time / fRepeats);
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
|
||||
}
|
||||
#endif
|
||||
result.appendf("\n");
|
||||
sk_tools::print_msg(result.c_str());
|
||||
|
||||
fRenderer.end();
|
||||
SkDELETE(timer);
|
||||
}
|
||||
|
||||
void TiledPictureBenchmark::run(SkPicture* pict) {
|
||||
SkASSERT(pict);
|
||||
if (NULL == pict) {
|
||||
return;
|
||||
}
|
||||
|
||||
fRenderer.init(pict);
|
||||
|
||||
// We throw this away to remove first time effects (such as paging in this
|
||||
// program)
|
||||
fRenderer.drawTiles();
|
||||
fRenderer.resetState();
|
||||
|
||||
BenchTimer* timer = setupTimer();
|
||||
double wall_time = 0, truncated_wall_time = 0;
|
||||
#if SK_SUPPORT_GPU
|
||||
double gpu_time = 0;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < fRepeats; ++i) {
|
||||
timer->start();
|
||||
fRenderer.drawTiles();
|
||||
timer->end();
|
||||
fRenderer.resetState();
|
||||
|
||||
wall_time += timer->fWall;
|
||||
truncated_wall_time += timer->fTruncatedWall;
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
gpu_time += timer->fGpu;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SkString result;
|
||||
if (fRenderer.isMultiThreaded()) {
|
||||
result.printf("multithreaded using %s ", (fRenderer.isUsePipe() ? "pipe" : "picture"));
|
||||
}
|
||||
if (fRenderer.getTileMinPowerOf2Width() > 0) {
|
||||
result.appendf("%i_pow2tiles_%iminx%i: msecs = %6.2f", fRenderer.numTiles(),
|
||||
fRenderer.getTileMinPowerOf2Width(), fRenderer.getTileHeight(),
|
||||
wall_time / fRepeats);
|
||||
} else {
|
||||
result.appendf("%i_tiles_%ix%i: msecs = %6.2f", fRenderer.numTiles(),
|
||||
fRenderer.getTileWidth(), fRenderer.getTileHeight(), wall_time / fRepeats);
|
||||
}
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fRenderer.isUsingGpuDevice()) {
|
||||
result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
|
||||
}
|
||||
#endif
|
||||
result.appendf("\n");
|
||||
sk_tools::print_msg(result.c_str());
|
||||
|
||||
fRenderer.end();
|
||||
SkDELETE(timer);
|
||||
}
|
||||
|
||||
void UnflattenPictureBenchmark::run(SkPicture* pict) {
|
||||
SkASSERT(pict);
|
||||
if (NULL == pict) {
|
||||
return;
|
||||
}
|
||||
|
||||
BenchTimer* timer = setupTimer();
|
||||
double wall_time = 0, truncated_wall_time = 0;
|
||||
|
||||
for (int i = 0; i < fRepeats + 1; ++i) {
|
||||
SkPicture replayer;
|
||||
SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());
|
||||
|
||||
recorder->drawPicture(*pict);
|
||||
|
||||
timer->start();
|
||||
replayer.endRecording();
|
||||
timer->end();
|
||||
|
||||
// We want to ignore first time effects
|
||||
if (i > 0) {
|
||||
wall_time += timer->fWall;
|
||||
truncated_wall_time += timer->fTruncatedWall;
|
||||
}
|
||||
}
|
||||
|
||||
SkString result;
|
||||
result.printf("unflatten: msecs = %6.4f\n", wall_time / fRepeats);
|
||||
sk_tools::print_msg(result.c_str());
|
||||
// FIXME: Pass these options on the command line.
|
||||
bool logPerIter = false;
|
||||
bool printMin = false;
|
||||
const char* configName = usingGpu ? "gpu" : "raster";
|
||||
bool showWallTime = true;
|
||||
bool showTruncatedWallTime = false;
|
||||
bool showCpuTime = false;
|
||||
bool showTruncatedCpuTime = false;
|
||||
SkString result = timerData.getResult(logPerIter, printMin, fRepeats,
|
||||
configName, showWallTime, showTruncatedWallTime,
|
||||
showCpuTime, showTruncatedCpuTime, usingGpu);
|
||||
result.append("\n");
|
||||
this->logProgress(result.c_str());
|
||||
|
||||
renderer->end();
|
||||
SkDELETE(timer);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "PictureRenderer.h"
|
||||
|
||||
class BenchTimer;
|
||||
class SkBenchLogger;
|
||||
class SkPicture;
|
||||
class SkString;
|
||||
|
||||
@ -19,16 +20,16 @@ namespace sk_tools {
|
||||
|
||||
class PictureBenchmark : public SkRefCnt {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) = 0;
|
||||
PictureBenchmark()
|
||||
: fRepeats(1)
|
||||
, fLogger(NULL) {}
|
||||
|
||||
void run(SkPicture* pict);
|
||||
|
||||
void setRepeats(int repeats) {
|
||||
fRepeats = repeats;
|
||||
}
|
||||
|
||||
int getRepeats() const {
|
||||
return fRepeats;
|
||||
}
|
||||
|
||||
void setDeviceType(PictureRenderer::SkDeviceTypes deviceType) {
|
||||
sk_tools::PictureRenderer* renderer = getRenderer();
|
||||
|
||||
@ -37,54 +38,58 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setLogger(SkBenchLogger* logger) { fLogger = logger; }
|
||||
|
||||
private:
|
||||
int fRepeats;
|
||||
SkBenchLogger* fLogger;
|
||||
|
||||
void logProgress(const char msg[]);
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() = 0;
|
||||
|
||||
BenchTimer* setupTimer();
|
||||
|
||||
protected:
|
||||
int fRepeats;
|
||||
|
||||
private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() {
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Use just one PictureBenchmark with different renderers.
|
||||
|
||||
class PipePictureBenchmark : public PictureBenchmark {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) SK_OVERRIDE;
|
||||
private:
|
||||
PipePictureRenderer fRenderer;
|
||||
typedef PictureBenchmark INHERITED;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() SK_OVERRIDE {
|
||||
return &fRenderer;
|
||||
}
|
||||
|
||||
typedef PictureBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class RecordPictureBenchmark : public PictureBenchmark {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) SK_OVERRIDE;
|
||||
private:
|
||||
RecordPictureRenderer fRenderer;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() SK_OVERRIDE {
|
||||
return &fRenderer;
|
||||
}
|
||||
|
||||
typedef PictureBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class SimplePictureBenchmark : public PictureBenchmark {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) SK_OVERRIDE;
|
||||
private:
|
||||
SimplePictureRenderer fRenderer;
|
||||
typedef PictureBenchmark INHERITED;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() SK_OVERRIDE {
|
||||
return &fRenderer;
|
||||
}
|
||||
|
||||
typedef PictureBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class TiledPictureBenchmark : public PictureBenchmark {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) SK_OVERRIDE;
|
||||
|
||||
void setTileWidth(int width) {
|
||||
fRenderer.setTileWidth(width);
|
||||
}
|
||||
@ -135,17 +140,22 @@ public:
|
||||
|
||||
private:
|
||||
TiledPictureRenderer fRenderer;
|
||||
typedef PictureBenchmark INHERITED;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() SK_OVERRIDE{
|
||||
return &fRenderer;
|
||||
}
|
||||
|
||||
typedef PictureBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class UnflattenPictureBenchmark : public PictureBenchmark {
|
||||
public:
|
||||
virtual void run(SkPicture* pict) SK_OVERRIDE;
|
||||
class PlaybackCreationBenchmark : public PictureBenchmark {
|
||||
private:
|
||||
PlaybackCreationRenderer fRenderer;
|
||||
|
||||
virtual sk_tools::PictureRenderer* getRenderer() SK_OVERRIDE{
|
||||
return &fRenderer;
|
||||
}
|
||||
|
||||
typedef PictureBenchmark INHERITED;
|
||||
};
|
||||
|
||||
|
@ -83,23 +83,6 @@ void PictureRenderer::end() {
|
||||
}
|
||||
|
||||
void PictureRenderer::resetState() {
|
||||
#if SK_SUPPORT_GPU
|
||||
if (this->isUsingGpuDevice()) {
|
||||
SkGLContext* glContext = fGrContextFactory.getGLContext(
|
||||
GrContextFactory::kNative_GLContextType);
|
||||
SK_GL(*glContext, Finish());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PictureRenderer::finishDraw() {
|
||||
SkASSERT(fCanvas.get() != NULL);
|
||||
if (NULL == fCanvas.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fCanvas->flush();
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
if (this->isUsingGpuDevice()) {
|
||||
SkGLContext* glContext = fGrContextFactory.getGLContext(
|
||||
@ -110,6 +93,7 @@ void PictureRenderer::finishDraw() {
|
||||
return;
|
||||
}
|
||||
|
||||
fGrContext->flush();
|
||||
SK_GL(*glContext, Finish());
|
||||
}
|
||||
#endif
|
||||
@ -131,7 +115,14 @@ bool PictureRenderer::write(const SkString& path) const {
|
||||
return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
||||
}
|
||||
|
||||
void PipePictureRenderer::render() {
|
||||
void RecordPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||
SkPicture replayer;
|
||||
SkCanvas* recorder = replayer.beginRecording(fPicture->width(), fPicture->height());
|
||||
fPicture->draw(recorder);
|
||||
replayer.endRecording();
|
||||
}
|
||||
|
||||
void PipePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||
SkASSERT(fCanvas.get() != NULL);
|
||||
SkASSERT(fPicture != NULL);
|
||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
||||
@ -143,10 +134,10 @@ void PipePictureRenderer::render() {
|
||||
SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
|
||||
pipeCanvas->drawPicture(*fPicture);
|
||||
writer.endRecording();
|
||||
this->finishDraw();
|
||||
fCanvas->flush();
|
||||
}
|
||||
|
||||
void SimplePictureRenderer::render() {
|
||||
void SimplePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||
SkASSERT(fCanvas.get() != NULL);
|
||||
SkASSERT(fPicture != NULL);
|
||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
||||
@ -154,7 +145,7 @@ void SimplePictureRenderer::render() {
|
||||
}
|
||||
|
||||
fCanvas->drawPicture(*fPicture);
|
||||
this->finishDraw();
|
||||
fCanvas->flush();
|
||||
}
|
||||
|
||||
TiledPictureRenderer::TiledPictureRenderer()
|
||||
@ -189,7 +180,7 @@ void TiledPictureRenderer::init(SkPicture* pict) {
|
||||
}
|
||||
}
|
||||
|
||||
void TiledPictureRenderer::render() {
|
||||
void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||
SkASSERT(fCanvas.get() != NULL);
|
||||
SkASSERT(fPicture != NULL);
|
||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
||||
@ -197,8 +188,9 @@ void TiledPictureRenderer::render() {
|
||||
}
|
||||
|
||||
this->drawTiles();
|
||||
this->copyTilesToCanvas();
|
||||
this->finishDraw();
|
||||
if (doExtraWorkToDrawToBaseCanvas) {
|
||||
this->copyTilesToCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
void TiledPictureRenderer::end() {
|
||||
@ -293,6 +285,7 @@ static void DrawTile(void* data) {
|
||||
SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
|
||||
TileData* tileData = static_cast<TileData*>(data);
|
||||
tileData->fController->playback(tileData->fCanvas);
|
||||
tileData->fCanvas->flush();
|
||||
}
|
||||
|
||||
TileData::TileData(SkCanvas* canvas, ThreadSafePipeController* controller)
|
||||
@ -314,6 +307,7 @@ static void DrawClonedTile(void* data) {
|
||||
SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
|
||||
CloneData* cloneData = static_cast<CloneData*>(data);
|
||||
cloneData->fCanvas->drawPicture(*cloneData->fClone);
|
||||
cloneData->fCanvas->flush();
|
||||
}
|
||||
|
||||
CloneData::CloneData(SkCanvas* target, SkPicture* clone)
|
||||
@ -367,30 +361,11 @@ void TiledPictureRenderer::drawTiles() {
|
||||
} else {
|
||||
for (int i = 0; i < fTiles.count(); ++i) {
|
||||
fTiles[i]->drawPicture(*(fPicture));
|
||||
fTiles[i]->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TiledPictureRenderer::finishDraw() {
|
||||
for (int i = 0; i < fTiles.count(); ++i) {
|
||||
fTiles[i]->flush();
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
if (this->isUsingGpuDevice()) {
|
||||
SkGLContext* glContext = fGrContextFactory.getGLContext(
|
||||
GrContextFactory::kNative_GLContextType);
|
||||
|
||||
SkASSERT(glContext != NULL);
|
||||
if (NULL == glContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
SK_GL(*glContext, Finish());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TiledPictureRenderer::copyTilesToCanvas() {
|
||||
for (int i = 0; i < fTiles.count(); ++i) {
|
||||
// Since SkPicture performs a save and restore when being drawn to a
|
||||
@ -404,6 +379,16 @@ void TiledPictureRenderer::copyTilesToCanvas() {
|
||||
|
||||
fCanvas->drawBitmap(source, -tile_x_start, -tile_y_start);
|
||||
}
|
||||
fCanvas->flush();
|
||||
}
|
||||
|
||||
void PlaybackCreationRenderer::setup() {
|
||||
SkCanvas* recorder = fReplayer.beginRecording(fPicture->width(), fPicture->height());
|
||||
fPicture->draw(recorder);
|
||||
}
|
||||
|
||||
void PlaybackCreationRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||
fReplayer.endRecording();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,9 +8,11 @@
|
||||
#ifndef PictureRenderer_DEFINED
|
||||
#define PictureRenderer_DEFINED
|
||||
#include "SkMath.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkTypes.h"
|
||||
#include "SkTDArray.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkString.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContextFactory.h"
|
||||
@ -20,8 +22,6 @@
|
||||
class SkBitmap;
|
||||
class SkCanvas;
|
||||
class SkGLContext;
|
||||
class SkPicture;
|
||||
class SkString;
|
||||
|
||||
namespace sk_tools {
|
||||
|
||||
@ -35,7 +35,23 @@ public:
|
||||
};
|
||||
|
||||
virtual void init(SkPicture* pict);
|
||||
virtual void render() = 0;
|
||||
|
||||
/**
|
||||
* Perform any setup that should done prior to each iteration of render() which should not be
|
||||
* timed.
|
||||
*/
|
||||
virtual void setup() {}
|
||||
|
||||
/**
|
||||
* Perform work that is to be timed. Typically this is rendering, but is also used for recording
|
||||
* and preparing picture for playback by the subclasses which do those.
|
||||
* @param doExtraWorkToDrawToBaseCanvas Perform extra work to draw to fCanvas. Some subclasses
|
||||
* will automatically draw to fCanvas, but in the tiled
|
||||
* case, for example, true needs to be passed so that
|
||||
* the tiles will be stitched together on fCanvas.
|
||||
*/
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) = 0;
|
||||
|
||||
virtual void end();
|
||||
void resetState();
|
||||
|
||||
@ -47,6 +63,10 @@ public:
|
||||
return kBitmap_DeviceType == fDeviceType;
|
||||
}
|
||||
|
||||
virtual SkString getPerIterTimeFormat() { return SkString("%.2f"); }
|
||||
|
||||
virtual SkString getNormalTimeFormat() { return SkString("%6.2f"); }
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool isUsingGpuDevice() {
|
||||
return kGPU_DeviceType == fDeviceType;
|
||||
@ -72,7 +92,6 @@ public:
|
||||
bool write(const SkString& path) const;
|
||||
|
||||
protected:
|
||||
virtual void finishDraw();
|
||||
SkCanvas* setupCanvas();
|
||||
SkCanvas* setupCanvas(int width, int height);
|
||||
|
||||
@ -89,9 +108,21 @@ private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class does not do any rendering, but its render function executes recording, which we want
|
||||
* to time.
|
||||
*/
|
||||
class RecordPictureRenderer : public PictureRenderer {
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
||||
|
||||
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
||||
|
||||
virtual SkString getNormalTimeFormat() SK_OVERRIDE { return SkString("%6.4f"); }
|
||||
};
|
||||
|
||||
class PipePictureRenderer : public PictureRenderer {
|
||||
public:
|
||||
virtual void render() SK_OVERRIDE;
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
typedef PictureRenderer INHERITED;
|
||||
@ -99,7 +130,7 @@ private:
|
||||
|
||||
class SimplePictureRenderer : public PictureRenderer {
|
||||
public:
|
||||
virtual void render () SK_OVERRIDE;
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
typedef PictureRenderer INHERITED;
|
||||
@ -110,7 +141,7 @@ public:
|
||||
TiledPictureRenderer();
|
||||
|
||||
virtual void init(SkPicture* pict) SK_OVERRIDE;
|
||||
virtual void render() SK_OVERRIDE;
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
||||
virtual void end() SK_OVERRIDE;
|
||||
void drawTiles();
|
||||
|
||||
@ -181,9 +212,6 @@ public:
|
||||
|
||||
~TiledPictureRenderer();
|
||||
|
||||
protected:
|
||||
virtual void finishDraw();
|
||||
|
||||
private:
|
||||
bool fMultiThreaded;
|
||||
bool fUsePipe;
|
||||
@ -209,6 +237,25 @@ private:
|
||||
typedef PictureRenderer INHERITED;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class does not do any rendering, but its render function executes turning an SkPictureRecord
|
||||
* into an SkPicturePlayback, which we want to time.
|
||||
*/
|
||||
class PlaybackCreationRenderer : public PictureRenderer {
|
||||
public:
|
||||
virtual void setup() SK_OVERRIDE;
|
||||
|
||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
||||
|
||||
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
||||
|
||||
virtual SkString getNormalTimeFormat() SK_OVERRIDE { return SkString("%6.4f"); }
|
||||
|
||||
private:
|
||||
SkPicture fReplayer;
|
||||
typedef PictureRenderer INHERITED;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PictureRenderer_DEFINED
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "BenchTimer.h"
|
||||
#include "PictureBenchmark.h"
|
||||
#include "SkBenchLogger.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkMath.h"
|
||||
#include "SkOSFile.h"
|
||||
@ -22,9 +23,10 @@ static void usage(const char* argv0) {
|
||||
SkDebugf("\n"
|
||||
"Usage: \n"
|
||||
" %s <inputDir>...\n"
|
||||
" [--logFile filename]\n"
|
||||
" [--repeat] \n"
|
||||
" [--mode pow2tile minWidth height[] (multi) | record | simple\n"
|
||||
" | tile width[] height[] (multi) | unflatten]\n"
|
||||
" | tile width[] height[] (multi) | playbackCreation]\n"
|
||||
" [--pipe]\n"
|
||||
" [--device bitmap"
|
||||
#if SK_SUPPORT_GPU
|
||||
@ -35,10 +37,11 @@ static void usage(const char* argv0) {
|
||||
SkDebugf("\n\n");
|
||||
SkDebugf(
|
||||
" inputDir: A list of directories and files to use as input. Files are\n"
|
||||
" expected to have the .skp extension.\n\n");
|
||||
" expected to have the .skp extension.\n\n"
|
||||
" --logFile filename : destination for writing log output, in addition to stdout.\n");
|
||||
SkDebugf(
|
||||
" --mode pow2tile minWidht height[] (multi) | record | simple\n"
|
||||
" | tile width[] height[] (multi) | unflatten:\n"
|
||||
" | tile width[] height[] (multi) | playbackCreation:\n"
|
||||
" Run in the corresponding mode.\n"
|
||||
" Default is simple.\n");
|
||||
SkDebugf(
|
||||
@ -63,7 +66,7 @@ static void usage(const char* argv0) {
|
||||
" Append \"multi\" for multithreaded\n"
|
||||
" drawing.\n");
|
||||
SkDebugf(
|
||||
" unflatten, Benchmark picture unflattening.\n");
|
||||
" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
|
||||
SkDebugf("\n");
|
||||
SkDebugf(
|
||||
" --pipe: Benchmark SkGPipe rendering. Compatible with tiled, multithreaded rendering.\n");
|
||||
@ -86,13 +89,17 @@ static void usage(const char* argv0) {
|
||||
" Default is %i.\n", DEFAULT_REPEATS);
|
||||
}
|
||||
|
||||
SkBenchLogger gLogger;
|
||||
|
||||
static void run_single_benchmark(const SkString& inputPath,
|
||||
sk_tools::PictureBenchmark& benchmark) {
|
||||
SkFILEStream inputStream;
|
||||
|
||||
inputStream.setPath(inputPath.c_str());
|
||||
if (!inputStream.isValid()) {
|
||||
SkDebugf("Could not open file %s\n", inputPath.c_str());
|
||||
SkString err;
|
||||
err.printf("Could not open file %s\n", inputPath.c_str());
|
||||
gLogger.logError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -104,7 +111,7 @@ static void run_single_benchmark(const SkString& inputPath,
|
||||
SkString result;
|
||||
result.printf("running bench [%i %i] %s ", picture.width(), picture.height(),
|
||||
filename.c_str());
|
||||
sk_tools::print_msg(result.c_str());
|
||||
gLogger.logProgress(result);
|
||||
|
||||
benchmark.run(&picture);
|
||||
}
|
||||
@ -118,6 +125,14 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
sk_tools::PictureRenderer::SkDeviceTypes deviceType =
|
||||
sk_tools::PictureRenderer::kBitmap_DeviceType;
|
||||
|
||||
// Create a string to show our current settings.
|
||||
// TODO: Make it prettier. Currently it just repeats the command line.
|
||||
SkString commandLine("bench_pictures:");
|
||||
for (int i = 1; i < argc; i++) {
|
||||
commandLine.appendf(" %s", *(argv+i));
|
||||
}
|
||||
commandLine.append("\n");
|
||||
|
||||
bool usePipe = false;
|
||||
bool multiThreaded = false;
|
||||
bool useTiles = false;
|
||||
@ -132,23 +147,38 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
repeats = atoi(*argv);
|
||||
if (repeats < 1) {
|
||||
SkDELETE(benchmark);
|
||||
SkDebugf("--repeat must be given a value > 0\n");
|
||||
gLogger.logError("--repeat must be given a value > 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
SkDELETE(benchmark);
|
||||
SkDebugf("Missing arg for --repeat\n");
|
||||
gLogger.logError("Missing arg for --repeat\n");
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (0 == strcmp(*argv, "--pipe")) {
|
||||
usePipe = true;
|
||||
} else if (0 == strcmp(*argv, "--logFile")) {
|
||||
argv++;
|
||||
if (argv < stop) {
|
||||
if (!gLogger.SetLogFile(*argv)) {
|
||||
SkString str;
|
||||
str.printf("Could not open %s for writing.", *argv);
|
||||
gLogger.logError(str);
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
gLogger.logError("Missing arg for --logFile\n");
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (0 == strcmp(*argv, "--mode")) {
|
||||
SkDELETE(benchmark);
|
||||
|
||||
++argv;
|
||||
if (argv >= stop) {
|
||||
SkDebugf("Missing mode for --mode\n");
|
||||
gLogger.logError("Missing mode for --mode\n");
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
@ -167,7 +197,9 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
|
||||
++argv;
|
||||
if (argv >= stop) {
|
||||
SkDebugf("Missing width for --mode %s\n", mode);
|
||||
SkString err;
|
||||
err.printf("Missing width for --mode %s\n", mode);
|
||||
gLogger.logError(err);
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
@ -175,7 +207,7 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
widthString = *argv;
|
||||
++argv;
|
||||
if (argv >= stop) {
|
||||
SkDebugf("Missing height for --mode tile\n");
|
||||
gLogger.logError("Missing height for --mode tile\n");
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
@ -187,17 +219,19 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
} else {
|
||||
--argv;
|
||||
}
|
||||
} else if (0 == strcmp(*argv, "unflatten")) {
|
||||
benchmark = SkNEW(sk_tools::UnflattenPictureBenchmark);
|
||||
} else if (0 == strcmp(*argv, "playbackCreation")) {
|
||||
benchmark = SkNEW(sk_tools::PlaybackCreationBenchmark);
|
||||
} else {
|
||||
SkDebugf("%s is not a valid mode for --mode\n", *argv);
|
||||
SkString err;
|
||||
err.printf("%s is not a valid mode for --mode\n", *argv);
|
||||
gLogger.logError(err);
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (0 == strcmp(*argv, "--device")) {
|
||||
++argv;
|
||||
if (argv >= stop) {
|
||||
SkDebugf("Missing mode for --deivce\n");
|
||||
gLogger.logError("Missing mode for --deivce\n");
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
@ -211,7 +245,9 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
SkDebugf("%s is not a valid mode for --device\n", *argv);
|
||||
SkString err;
|
||||
err.printf("%s is not a valid mode for --device\n", *argv);
|
||||
gLogger.logError(err);
|
||||
usage(argv0);
|
||||
exit(-1);
|
||||
}
|
||||
@ -231,8 +267,10 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
int minWidth = atoi(widthString);
|
||||
if (!SkIsPow2(minWidth) || minWidth < 0) {
|
||||
SkDELETE(tileBenchmark);
|
||||
SkDebugf("--mode %s must be given a width"
|
||||
SkString err;
|
||||
err.printf("--mode %s must be given a width"
|
||||
" value that is a power of two\n", mode);
|
||||
gLogger.logError(err);
|
||||
exit(-1);
|
||||
}
|
||||
tileBenchmark->setTileMinPowerOf2Width(minWidth);
|
||||
@ -240,14 +278,14 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
tileBenchmark->setTileWidthPercentage(atof(widthString));
|
||||
if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
|
||||
SkDELETE(tileBenchmark);
|
||||
SkDebugf("--mode tile must be given a width percentage > 0\n");
|
||||
gLogger.logError("--mode tile must be given a width percentage > 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
tileBenchmark->setTileWidth(atoi(widthString));
|
||||
if (!(tileBenchmark->getTileWidth() > 0)) {
|
||||
SkDELETE(tileBenchmark);
|
||||
SkDebugf("--mode tile must be given a width > 0\n");
|
||||
gLogger.logError("--mode tile must be given a width > 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@ -256,14 +294,14 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
tileBenchmark->setTileHeightPercentage(atof(heightString));
|
||||
if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
|
||||
SkDELETE(tileBenchmark);
|
||||
SkDebugf("--mode tile must be given a height percentage > 0\n");
|
||||
gLogger.logError("--mode tile must be given a height percentage > 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
tileBenchmark->setTileHeight(atoi(heightString));
|
||||
if (!(tileBenchmark->getTileHeight() > 0)) {
|
||||
SkDELETE(tileBenchmark);
|
||||
SkDebugf("--mode tile must be given a height > 0\n");
|
||||
gLogger.logError("--mode tile must be given a height > 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@ -286,6 +324,9 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
|
||||
benchmark->setRepeats(repeats);
|
||||
benchmark->setDeviceType(deviceType);
|
||||
benchmark->setLogger(&gLogger);
|
||||
// Report current settings:
|
||||
gLogger.logProgress(commandLine);
|
||||
}
|
||||
|
||||
static void process_input(const SkString& input, sk_tools::PictureBenchmark& benchmark) {
|
||||
|
@ -85,13 +85,6 @@ namespace sk_tools {
|
||||
return skString.endsWith("%");
|
||||
}
|
||||
|
||||
// This copies how bench does printing of test results.
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
void print_msg(const char msg[]) { SkDebugf("%s", msg); }
|
||||
#else
|
||||
void print_msg(const char msg[]) { printf("%s", msg); }
|
||||
#endif
|
||||
|
||||
void setup_bitmap(SkBitmap* bitmap, int width, int height) {
|
||||
bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
||||
bitmap->allocPixels();
|
||||
|
@ -36,11 +36,6 @@ namespace sk_tools {
|
||||
// Returns true if the string ends with %
|
||||
bool is_percentage(const char* const string);
|
||||
|
||||
// Prints to STDOUT so that test results can be easily seperated from the
|
||||
// error stream. Note, that this still prints to the same stream as SkDebugf
|
||||
// on Andoid.
|
||||
void print_msg(const char msg[]);
|
||||
|
||||
// Prepares the bitmap so that it can be written.
|
||||
//
|
||||
// Specifically, it configures the bitmap, allocates pixels and then
|
||||
|
@ -104,7 +104,9 @@ static void render_picture(const SkString& inputPath, const SkString& outputDir,
|
||||
|
||||
renderer.init(&picture);
|
||||
|
||||
renderer.render();
|
||||
renderer.render(true);
|
||||
|
||||
renderer.resetState();
|
||||
|
||||
write_output(outputDir, inputFilename, renderer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user