Some cleanups of VisualBench
BUG=skia: Review URL: https://codereview.chromium.org/1240633005
This commit is contained in:
parent
5150a77ee7
commit
a2a6fe8699
@ -170,15 +170,24 @@ bool VisualBench::advanceRecordIfNecessary(SkCanvas* canvas) {
|
||||
|
||||
canvas->clear(0xffffffff);
|
||||
fBenchmark->preDraw();
|
||||
fBenchmark->perCanvasPreDraw(canvas);
|
||||
fRecords.push_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void VisualBench::nextState(State nextState) {
|
||||
fState = nextState;
|
||||
}
|
||||
|
||||
void VisualBench::perCanvasPreDraw(SkCanvas* canvas, State nextState) {
|
||||
fBenchmark->perCanvasPreDraw(canvas);
|
||||
fCurrentFrame = 0;
|
||||
this->nextState(nextState);
|
||||
}
|
||||
|
||||
void VisualBench::preWarm(State nextState) {
|
||||
if (fCurrentFrame >= FLAGS_gpuFrameLag) {
|
||||
// we currently time across all frames to make sure we capture all GPU work
|
||||
fState = nextState;
|
||||
this->nextState(nextState);
|
||||
fCurrentFrame = 0;
|
||||
fTimer.start();
|
||||
} else {
|
||||
@ -193,33 +202,20 @@ void VisualBench::draw(SkCanvas* canvas) {
|
||||
}
|
||||
this->renderFrame(canvas);
|
||||
switch (fState) {
|
||||
case kPreWarmLoopsPerCanvasPreDraw_State: {
|
||||
this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
|
||||
break;
|
||||
}
|
||||
case kPreWarmLoops_State: {
|
||||
this->preWarm(kTuneLoops_State);
|
||||
break;
|
||||
}
|
||||
case kTuneLoops_State: {
|
||||
if (1 << 30 == fLoops) {
|
||||
// We're about to wrap. Something's wrong with the bench.
|
||||
SkDebugf("InnerLoops wrapped\n");
|
||||
fLoops = 0;
|
||||
} else {
|
||||
fTimer.end();
|
||||
double elapsed = fTimer.fWall;
|
||||
if (elapsed > FLAGS_loopMs) {
|
||||
fState = kPreWarmTiming_State;
|
||||
|
||||
// Scale back the number of loops
|
||||
fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsed);
|
||||
fFlushes = (int)ceil(FLAGS_flushMs / elapsed);
|
||||
} else {
|
||||
fState = kPreWarmLoops_State;
|
||||
fLoops *= 2;
|
||||
}
|
||||
|
||||
fCurrentFrame = 0;
|
||||
fTimer = WallTimer();
|
||||
this->resetContext();
|
||||
}
|
||||
this->tuneLoops();
|
||||
break;
|
||||
}
|
||||
case kPreWarmTimingPerCanvasPreDraw_State: {
|
||||
this->perCanvasPreDraw(canvas, kPreWarmTiming_State);
|
||||
break;
|
||||
}
|
||||
case kPreWarmTiming_State: {
|
||||
@ -227,27 +223,7 @@ void VisualBench::draw(SkCanvas* canvas) {
|
||||
break;
|
||||
}
|
||||
case kTiming_State: {
|
||||
if (fCurrentFrame >= FLAGS_frames) {
|
||||
fTimer.end();
|
||||
fRecords.back().fMeasurements.push_back(
|
||||
fTimer.fWall / (FLAGS_frames * fLoops * fFlushes));
|
||||
if (fCurrentSample++ >= FLAGS_samples) {
|
||||
fState = kPreWarmLoops_State;
|
||||
this->printStats();
|
||||
fBenchmark->perCanvasPostDraw(canvas);
|
||||
fBenchmark.reset(NULL);
|
||||
fCurrentSample = 0;
|
||||
fFlushes = 1;
|
||||
fLoops = 1;
|
||||
} else {
|
||||
fState = kPreWarmTiming_State;
|
||||
}
|
||||
fTimer = WallTimer();
|
||||
this->resetContext();
|
||||
fCurrentFrame = 0;
|
||||
} else {
|
||||
fCurrentFrame++;
|
||||
}
|
||||
this->timing(canvas);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -256,6 +232,70 @@ void VisualBench::draw(SkCanvas* canvas) {
|
||||
this->inval(NULL);
|
||||
}
|
||||
|
||||
inline double VisualBench::elapsed() {
|
||||
fTimer.end();
|
||||
return fTimer.fWall;
|
||||
}
|
||||
|
||||
void VisualBench::resetTimingState() {
|
||||
fCurrentFrame = 0;
|
||||
fTimer = WallTimer();
|
||||
this->resetContext();
|
||||
}
|
||||
|
||||
void VisualBench::scaleLoops(double elapsedMs) {
|
||||
// Scale back the number of loops
|
||||
fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs);
|
||||
fFlushes = (int)ceil(FLAGS_flushMs / elapsedMs);
|
||||
}
|
||||
|
||||
inline void VisualBench::tuneLoops() {
|
||||
if (1 << 30 == fLoops) {
|
||||
// We're about to wrap. Something's wrong with the bench.
|
||||
SkDebugf("InnerLoops wrapped\n");
|
||||
fLoops = 0;
|
||||
} else {
|
||||
double elapsedMs = this->elapsed();
|
||||
if (elapsedMs > FLAGS_loopMs) {
|
||||
this->scaleLoops(elapsedMs);
|
||||
this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
|
||||
} else {
|
||||
fLoops *= 2;
|
||||
this->nextState(kPreWarmLoops_State);
|
||||
}
|
||||
this->resetTimingState();
|
||||
}
|
||||
}
|
||||
|
||||
void VisualBench::recordMeasurement() {
|
||||
double measurement = this->elapsed() / (FLAGS_frames * fLoops * fFlushes);
|
||||
fRecords.back().fMeasurements.push_back(measurement);
|
||||
}
|
||||
|
||||
void VisualBench::postDraw(SkCanvas* canvas) {
|
||||
fBenchmark->perCanvasPostDraw(canvas);
|
||||
fBenchmark.reset(NULL);
|
||||
fCurrentSample = 0;
|
||||
fFlushes = 1;
|
||||
fLoops = 1;
|
||||
}
|
||||
|
||||
inline void VisualBench::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++;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualBench::onSizeChange() {
|
||||
this->setupRenderTarget();
|
||||
}
|
||||
|
@ -39,6 +39,34 @@ protected:
|
||||
void onSizeChange() override;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The heart of visual bench 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,
|
||||
};
|
||||
void setTitle();
|
||||
bool setupBackend();
|
||||
void resetContext();
|
||||
@ -47,19 +75,21 @@ private:
|
||||
void printStats();
|
||||
bool advanceRecordIfNecessary(SkCanvas*);
|
||||
inline void renderFrame(SkCanvas*);
|
||||
inline void nextState(State);
|
||||
void perCanvasPreDraw(SkCanvas*, State);
|
||||
void preWarm(State nextState);
|
||||
void scaleLoops(double elapsedMs);
|
||||
inline void tuneLoops();
|
||||
inline void timing(SkCanvas*);
|
||||
inline double elapsed();
|
||||
void resetTimingState();
|
||||
void postDraw(SkCanvas*);
|
||||
void recordMeasurement();
|
||||
|
||||
struct Record {
|
||||
SkTArray<double> fMeasurements;
|
||||
};
|
||||
|
||||
enum State {
|
||||
kPreWarmLoops_State,
|
||||
kTuneLoops_State,
|
||||
kPreWarmTiming_State,
|
||||
kTiming_State,
|
||||
};
|
||||
void preWarm(State nextState);
|
||||
|
||||
int fCurrentSample;
|
||||
int fCurrentFrame;
|
||||
int fFlushes;
|
||||
|
Loading…
Reference in New Issue
Block a user