Index: tools/VisualBench.cpp |
diff --git a/tools/VisualBench.cpp b/tools/VisualBench.cpp |
index 3f8d8036aada0d12fd3bcb370dda2fb2c588ad58..31bc8f3595f39e74f230ad84bf6f3d33c9cf3bbb 100644 |
--- a/tools/VisualBench.cpp |
+++ b/tools/VisualBench.cpp |
@@ -8,6 +8,7 @@ |
#include "VisualBench.h" |
+#include "ProcStats.h" |
#include "SkApplication.h" |
#include "SkCanvas.h" |
#include "SkCommandLineFlags.h" |
@@ -18,35 +19,45 @@ |
#include "SkImageDecoder.h" |
#include "SkOSFile.h" |
#include "SkStream.h" |
+#include "Stats.h" |
#include "Timer.h" |
#include "gl/GrGLInterface.h" |
__SK_FORCE_IMAGE_DECODER_LINKING; |
+DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag."); |
+DEFINE_int32(maxFrames, 20, "Number of times to render each skp."); |
robertphillips
2015/06/01 14:26:00
Should maxFrames be repeat or samples ?
joshualitt
2015/06/01 16:16:09
Acknowledged.
|
+DEFINE_int32(msaa, 0, "Number of msaa samples."); |
+ |
+static SkString humanize(double ms) { |
robertphillips
2015/06/01 14:26:00
add brackets & newlines ?
joshualitt
2015/06/01 16:16:09
Acknowledged.
|
+ if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); |
+ return HumanizeMs(ms); |
+} |
+ |
+#define HUMANIZE(time) humanize(time).c_str() |
+ |
VisualBench::VisualBench(void* hwnd, int argc, char** argv) |
: INHERITED(hwnd) |
- , fCurrentLoops(1) |
, fCurrentPicture(0) |
, fCurrentFrame(0) { |
SkCommandLineFlags::Parse(argc, argv); |
+ // load all SKPs |
SkTArray<SkString> skps; |
for (int i = 0; i < FLAGS_skps.count(); i++) { |
if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { |
skps.push_back() = FLAGS_skps[i]; |
+ fTimings.push_back().fName = FLAGS_skps[i]; |
} else { |
SkOSFile::Iter it(FLAGS_skps[i], ".skp"); |
SkString path; |
while (it.next(&path)) { |
skps.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str()); |
+ fTimings.push_back().fName = path.c_str(); |
} |
} |
} |
- this->setTitle(); |
- this->setupBackend(); |
- |
- // Load picture for playback |
for (int i = 0; i < skps.count(); i++) { |
SkFILEStream stream(skps[i].c_str()); |
if (stream.isValid()) { |
@@ -55,6 +66,13 @@ VisualBench::VisualBench(void* hwnd, int argc, char** argv) |
SkDebugf("couldn't load picture at \"path\"\n", skps[i].c_str()); |
} |
} |
+ |
+ if (fPictures.empty()) { |
+ SkDebugf("no valid skps found\n"); |
+ } |
+ |
+ this->setTitle(); |
+ this->setupBackend(); |
} |
VisualBench::~VisualBench() { |
@@ -79,7 +97,7 @@ bool VisualBench::setupBackend() { |
this->setVisibleP(true); |
this->setClipToBounds(false); |
- if (!this->attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo)) { |
+ if (!this->attach(kNativeGL_BackEndType, FLAGS_msaa, &fAttachmentInfo)) { |
SkDebugf("Not possible to create backend.\n"); |
INHERITED::detach(); |
return false; |
@@ -87,7 +105,11 @@ bool VisualBench::setupBackend() { |
this->setFullscreen(true); |
this->setVsync(false); |
+ this->resetContext(); |
+ return true; |
+} |
+void VisualBench::resetContext() { |
fInterface.reset(GrGLCreateNativeInterface()); |
SkASSERT(fInterface); |
@@ -97,26 +119,62 @@ bool VisualBench::setupBackend() { |
// setup rendertargets |
this->setupRenderTarget(); |
- return true; |
} |
void VisualBench::setupRenderTarget() { |
fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fContext)); |
} |
-void VisualBench::draw(SkCanvas* canvas) { |
- fCurrentFrame++; |
+void VisualBench::timeFrame(SkCanvas* canvas) { |
WallTimer timer; |
bsalomon
2015/06/01 13:49:54
I think you should time outside the loop
joshualitt
2015/06/01 16:16:09
Acknowledged.
|
timer.start(); |
- for (int i = 0; i < fCurrentLoops; i++) { |
- canvas->drawPicture(fPictures[fCurrentPicture]); |
- } |
+ canvas->drawPicture(fPictures[fCurrentPicture]); |
// in case we have queued drawing calls |
fContext->flush(); |
INHERITED::present(); |
timer.end(); |
+ if (fCurrentFrame > FLAGS_gpuFrameLag) { |
+ fTimings[fCurrentPicture].fMeasurements.push_back(timer.fWall); |
+ } |
+} |
- SkDebugf("%s\n", HumanizeMs(timer.fWall).c_str()); |
+void VisualBench::printStats() { |
+ const SkTArray<double>& measurements = fTimings[fCurrentPicture].fMeasurements; |
+ if (FLAGS_verbose) { |
+ for (int i = 0; i < measurements.count(); i++) { |
+ SkDebugf("%s ", HUMANIZE(measurements[i])); |
+ } |
+ SkDebugf("%s\n", fTimings[fCurrentPicture].fName.c_str()); |
+ } else { |
+ SkASSERT(measurements.count()); |
+ Stats stats(measurements.begin(), measurements.count()); |
robertphillips
2015/06/01 14:31:07
stdDevPercent ?
joshualitt
2015/06/01 16:16:09
Acknowledged.
|
+ const double stddev_percent = 100 * sqrt(stats.var) / stats.mean; |
+ SkDebugf("%4d/%-4dMB\t%s\t%s\t%s\t%s\t%.0f%%\t%s\n" |
robertphillips
2015/06/01 14:26:00
I think we only do the "lead-with-," thing for cto
joshualitt
2015/06/01 16:16:09
Acknowledged.
|
+ , sk_tools::getCurrResidentSetSizeMB() |
+ , sk_tools::getMaxResidentSetSizeMB() |
robertphillips
2015/06/01 14:31:07
This probably isn't yours but why isn't this fMin
joshualitt
2015/06/01 16:16:09
no idea, might be Mike Klein's code.
|
+ , HUMANIZE(stats.min) |
+ , HUMANIZE(stats.median) |
+ , HUMANIZE(stats.mean) |
+ , HUMANIZE(stats.max) |
+ , stddev_percent |
+ , fTimings[fCurrentPicture].fName.c_str() |
+ ); |
+ } |
+} |
+ |
+void VisualBench::draw(SkCanvas* canvas) { |
+ if (fCurrentPicture < fPictures.count()) { |
+ if (fCurrentFrame++ < FLAGS_maxFrames) { |
+ this->timeFrame(canvas); |
+ } else { |
+ this->printStats(); |
+ fCurrentPicture++; |
+ fCurrentFrame = 0; |
+ this->resetContext(); |
+ } |
+ } else { |
+ this->closeWindow(); |
+ } |
// Invalidate the window to force a redraw. Poor man's animation mechanism. |
this->inval(NULL); |