e6d2024c68
This change updates a small subset of benchmarks to flush the GrContext between draw loops (specifically SKP benchmarks, SampleApp, and the warmup in visualbench). This helps improve timing accuracy by not allowing the gpu to batch across draw boundaries in the affected benchmarks. BUG=skia: Review URL: https://codereview.chromium.org/1427533002
158 lines
4.9 KiB
C++
158 lines
4.9 KiB
C++
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "SKPBench.h"
|
|
#include "SkCommandLineFlags.h"
|
|
#include "SkMultiPictureDraw.h"
|
|
#include "SkSurface.h"
|
|
|
|
#if SK_SUPPORT_GPU
|
|
#include "GrContext.h"
|
|
#endif
|
|
|
|
// These CPU tile sizes are not good per se, but they are similar to what Chrome uses.
|
|
DEFINE_int32(CPUbenchTileW, 256, "Tile width used for CPU SKP playback.");
|
|
DEFINE_int32(CPUbenchTileH, 256, "Tile height used for CPU SKP playback.");
|
|
|
|
DEFINE_int32(GPUbenchTileW, 1600, "Tile width used for GPU SKP playback.");
|
|
DEFINE_int32(GPUbenchTileH, 512, "Tile height used for GPU SKP playback.");
|
|
|
|
SKPBench::SKPBench(const char* name, const SkPicture* pic, const SkIRect& clip, SkScalar scale,
|
|
bool useMultiPictureDraw, bool doLooping)
|
|
: fPic(SkRef(pic))
|
|
, fClip(clip)
|
|
, fScale(scale)
|
|
, fName(name)
|
|
, fUseMultiPictureDraw(useMultiPictureDraw)
|
|
, fDoLooping(doLooping) {
|
|
fUniqueName.printf("%s_%.2g", name, scale); // Scale makes this unqiue for perf.skia.org traces.
|
|
if (useMultiPictureDraw) {
|
|
fUniqueName.append("_mpd");
|
|
}
|
|
}
|
|
|
|
SKPBench::~SKPBench() {
|
|
for (int i = 0; i < fSurfaces.count(); ++i) {
|
|
fSurfaces[i]->unref();
|
|
}
|
|
}
|
|
|
|
const char* SKPBench::onGetName() {
|
|
return fName.c_str();
|
|
}
|
|
|
|
const char* SKPBench::onGetUniqueName() {
|
|
return fUniqueName.c_str();
|
|
}
|
|
|
|
void SKPBench::onPerCanvasPreDraw(SkCanvas* canvas) {
|
|
SkIRect bounds;
|
|
SkAssertResult(canvas->getClipDeviceBounds(&bounds));
|
|
|
|
const bool gpu = canvas->getGrContext() != nullptr;
|
|
int tileW = gpu ? FLAGS_GPUbenchTileW : FLAGS_CPUbenchTileW,
|
|
tileH = gpu ? FLAGS_GPUbenchTileH : FLAGS_CPUbenchTileH;
|
|
|
|
tileW = SkTMin(tileW, bounds.width());
|
|
tileH = SkTMin(tileH, bounds.height());
|
|
|
|
int xTiles = SkScalarCeilToInt(bounds.width() / SkIntToScalar(tileW));
|
|
int yTiles = SkScalarCeilToInt(bounds.height() / SkIntToScalar(tileH));
|
|
|
|
fSurfaces.setReserve(xTiles * yTiles);
|
|
fTileRects.setReserve(xTiles * yTiles);
|
|
|
|
SkImageInfo ii = canvas->imageInfo().makeWH(tileW, tileH);
|
|
|
|
for (int y = bounds.fTop; y < bounds.fBottom; y += tileH) {
|
|
for (int x = bounds.fLeft; x < bounds.fRight; x += tileW) {
|
|
const SkIRect tileRect = SkIRect::MakeXYWH(x, y, tileW, tileH);
|
|
*fTileRects.append() = tileRect;
|
|
*fSurfaces.push() = canvas->newSurface(ii);
|
|
|
|
// Never want the contents of a tile to include stuff the parent
|
|
// canvas clips out
|
|
SkRect clip = SkRect::Make(bounds);
|
|
clip.offset(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fTop));
|
|
fSurfaces.top()->getCanvas()->clipRect(clip);
|
|
|
|
fSurfaces.top()->getCanvas()->setMatrix(canvas->getTotalMatrix());
|
|
fSurfaces.top()->getCanvas()->scale(fScale, fScale);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SKPBench::onPerCanvasPostDraw(SkCanvas* canvas) {
|
|
// Draw the last set of tiles into the master canvas in case we're
|
|
// saving the images
|
|
for (int i = 0; i < fTileRects.count(); ++i) {
|
|
SkAutoTUnref<SkImage> image(fSurfaces[i]->newImageSnapshot());
|
|
canvas->drawImage(image,
|
|
SkIntToScalar(fTileRects[i].fLeft), SkIntToScalar(fTileRects[i].fTop));
|
|
SkSafeSetNull(fSurfaces[i]);
|
|
}
|
|
|
|
fSurfaces.rewind();
|
|
fTileRects.rewind();
|
|
}
|
|
|
|
bool SKPBench::isSuitableFor(Backend backend) {
|
|
return backend != kNonRendering_Backend;
|
|
}
|
|
|
|
SkIPoint SKPBench::onGetSize() {
|
|
return SkIPoint::Make(fClip.width(), fClip.height());
|
|
}
|
|
|
|
void SKPBench::onDraw(int loops, SkCanvas* canvas) {
|
|
SkASSERT(fDoLooping || 1 == loops);
|
|
if (fUseMultiPictureDraw) {
|
|
for (int i = 0; i < loops; i++) {
|
|
this->drawMPDPicture();
|
|
}
|
|
} else {
|
|
for (int i = 0; i < loops; i++) {
|
|
this->drawPicture();
|
|
}
|
|
}
|
|
#if SK_SUPPORT_GPU
|
|
// Ensure the GrContext doesn't batch across draw loops.
|
|
if (GrContext* context = canvas->getGrContext()) {
|
|
context->flush();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SKPBench::drawMPDPicture() {
|
|
SkMultiPictureDraw mpd;
|
|
|
|
for (int j = 0; j < fTileRects.count(); ++j) {
|
|
SkMatrix trans;
|
|
trans.setTranslate(-fTileRects[j].fLeft/fScale,
|
|
-fTileRects[j].fTop/fScale);
|
|
mpd.add(fSurfaces[j]->getCanvas(), fPic, &trans);
|
|
}
|
|
|
|
mpd.draw();
|
|
|
|
for (int j = 0; j < fTileRects.count(); ++j) {
|
|
fSurfaces[j]->getCanvas()->flush();
|
|
}
|
|
}
|
|
|
|
void SKPBench::drawPicture() {
|
|
for (int j = 0; j < fTileRects.count(); ++j) {
|
|
const SkMatrix trans = SkMatrix::MakeTrans(-fTileRects[j].fLeft / fScale,
|
|
-fTileRects[j].fTop / fScale);
|
|
fSurfaces[j]->getCanvas()->drawPicture(fPic, &trans, nullptr);
|
|
}
|
|
|
|
for (int j = 0; j < fTileRects.count(); ++j) {
|
|
fSurfaces[j]->getCanvas()->flush();
|
|
}
|
|
}
|