182 lines
6.6 KiB
C++
182 lines
6.6 KiB
C++
|
|
/*
|
||
|
|
* Copyright 2022 Google LLC
|
||
|
|
*
|
||
|
|
* Use of this source code is governed by a BSD-style license that can be
|
||
|
|
* found in the LICENSE file.
|
||
|
|
*/
|
||
|
|
#include "bench/Benchmark.h"
|
||
|
|
#include "include/core/SkPaint.h"
|
||
|
|
#include "include/core/SkPath.h"
|
||
|
|
#include "src/base/SkArenaAlloc.h"
|
||
|
|
#include "src/base/SkRandom.h"
|
||
|
|
#include "src/gpu/graphite/geom/BoundsManager.h"
|
||
|
|
#include "tools/ToolUtils.h"
|
||
|
|
#include "tools/flags/CommandLineFlags.h"
|
||
|
|
|
||
|
|
static DEFINE_string(boundsManagerFile, "",
|
||
|
|
"svg or skp for the BoundsManager bench to sniff paths from.");
|
||
|
|
|
||
|
|
#define PRINT_DRAWSET_COUNT 0 // set to 1 to display number of CompressedPaintersOrder groups
|
||
|
|
|
||
|
|
namespace skgpu::graphite {
|
||
|
|
|
||
|
|
class BoundsManagerBench : public Benchmark {
|
||
|
|
public:
|
||
|
|
BoundsManagerBench(std::unique_ptr<BoundsManager> manager) : fManager(std::move(manager)) {}
|
||
|
|
|
||
|
|
protected:
|
||
|
|
virtual void gatherRects(SkTArray<SkRect>* rects) = 0;
|
||
|
|
|
||
|
|
bool isSuitableFor(Backend backend) override {
|
||
|
|
return backend == kNonRendering_Backend;
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* onGetName() final { return fName.c_str(); }
|
||
|
|
|
||
|
|
void onDelayedSetup() final {
|
||
|
|
SkTArray<SkRect> rects;
|
||
|
|
this->gatherRects(&rects);
|
||
|
|
|
||
|
|
fRectCount = rects.size();
|
||
|
|
fRects = fAlignedAllocator.makeArray<Rect>(fRectCount);
|
||
|
|
for (int i = 0; i < fRectCount; ++i) {
|
||
|
|
fRects[i] = rects[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void onDraw(int loops, SkCanvas*) final {
|
||
|
|
for (int i = 0; i < loops; ++i) {
|
||
|
|
this->doBench();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void onPerCanvasPostDraw(SkCanvas*) override {
|
||
|
|
#if PRINT_DRAWSET_COUNT
|
||
|
|
SkDebugf("%s >> grouped %d draws into %d sets <<\n",
|
||
|
|
fName.c_str(), fRectCount, fMaxRead.bits());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void doBench() {
|
||
|
|
CompressedPaintersOrder maxRead = CompressedPaintersOrder::First();
|
||
|
|
for (int i = 0; i < fRectCount; ++i) {
|
||
|
|
const Rect& drawBounds = fRects[i];
|
||
|
|
CompressedPaintersOrder order = fManager->getMostRecentDraw(drawBounds).next();
|
||
|
|
fManager->recordDraw(drawBounds, order);
|
||
|
|
if (order > maxRead) {
|
||
|
|
maxRead = order;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fMaxRead = maxRead;
|
||
|
|
fManager->reset();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::unique_ptr<BoundsManager> fManager;
|
||
|
|
SkString fName;
|
||
|
|
SkArenaAlloc fAlignedAllocator{0};
|
||
|
|
int fRectCount;
|
||
|
|
Rect* fRects;
|
||
|
|
|
||
|
|
CompressedPaintersOrder fMaxRead;
|
||
|
|
};
|
||
|
|
|
||
|
|
class RandomBoundsManagerBench : public BoundsManagerBench {
|
||
|
|
public:
|
||
|
|
RandomBoundsManagerBench(std::unique_ptr<BoundsManager> manager,
|
||
|
|
const char* managerName,
|
||
|
|
int numRandomRects)
|
||
|
|
: BoundsManagerBench(std::move(manager))
|
||
|
|
, fNumRandomRects(numRandomRects) {
|
||
|
|
fName.printf("BoundsManager_rand_%i_%s", numRandomRects, managerName);
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
void gatherRects(SkTArray<SkRect>* rects) override {
|
||
|
|
SkRandom rand;
|
||
|
|
for (int i = 0; i < fNumRandomRects; ++i) {
|
||
|
|
rects->push_back(SkRect::MakeXYWH(rand.nextRangeF(0, 2000),
|
||
|
|
rand.nextRangeF(0, 2000),
|
||
|
|
rand.nextRangeF(0, 70),
|
||
|
|
rand.nextRangeF(0, 70)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int fNumRandomRects;
|
||
|
|
};
|
||
|
|
|
||
|
|
class FileBoundsManagerBench : public BoundsManagerBench {
|
||
|
|
public:
|
||
|
|
FileBoundsManagerBench(std::unique_ptr<BoundsManager> manager,
|
||
|
|
const char* managerName)
|
||
|
|
: BoundsManagerBench(std::move(manager)) {
|
||
|
|
if (!FLAGS_boundsManagerFile.isEmpty()) {
|
||
|
|
const char* filename = strrchr(FLAGS_boundsManagerFile[0], '/');
|
||
|
|
if (filename) {
|
||
|
|
++filename;
|
||
|
|
} else {
|
||
|
|
filename = FLAGS_boundsManagerFile[0];
|
||
|
|
}
|
||
|
|
fName.printf("BoundsManager_file_%s_%s", filename, managerName);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
bool isSuitableFor(Backend backend) final {
|
||
|
|
if (FLAGS_boundsManagerFile.isEmpty()) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return BoundsManagerBench::isSuitableFor(backend);
|
||
|
|
}
|
||
|
|
|
||
|
|
void gatherRects(SkTArray<SkRect>* rects) override {
|
||
|
|
if (FLAGS_boundsManagerFile.isEmpty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
SkRect fileBounds = SkRect::MakeEmpty();
|
||
|
|
ToolUtils::sniff_paths(FLAGS_boundsManagerFile[0], [&](const SkMatrix& matrix,
|
||
|
|
const SkPath& path,
|
||
|
|
const SkPaint& paint) {
|
||
|
|
if (!paint.canComputeFastBounds() || path.isInverseFillType()) {
|
||
|
|
// These would pessimistically cover the entire canvas, but we don't have enough
|
||
|
|
// info in the benchmark to handle that, so just skip these draws.
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
SkRect bounds = path.getBounds();
|
||
|
|
SkRect drawBounds = matrix.mapRect(paint.computeFastBounds(bounds, &bounds));
|
||
|
|
rects->push_back(drawBounds);
|
||
|
|
|
||
|
|
fileBounds.join(drawBounds);
|
||
|
|
});
|
||
|
|
|
||
|
|
#if PRINT_DRAWSET_COUNT
|
||
|
|
SkDebugf("%s bounds are [%f %f %f %f]\n",
|
||
|
|
FLAGS_boundsManagerFile[0],
|
||
|
|
fileBounds.fLeft, fileBounds.fTop, fileBounds.fRight, fileBounds.fBottom);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
} // namespace skgpu::graphite
|
||
|
|
|
||
|
|
#define DEF_BOUNDS_MANAGER_BENCH_SET(manager, name) \
|
||
|
|
DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 100); ) \
|
||
|
|
DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 500); ) \
|
||
|
|
DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 1000); ) \
|
||
|
|
DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 10000); ) \
|
||
|
|
DEF_BENCH( return new skgpu::graphite::FileBoundsManagerBench(manager, name); )
|
||
|
|
|
||
|
|
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::NaiveBoundsManager>(), "naive")
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::BruteForceBoundsManager>(), "brute")
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::Make({1800, 1800}, 128), "grid128")
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::Make({1800, 1800}, 512), "grid512")
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::HybridBoundsManager>(SkISize{1800, 1800}, 16, 64), "hybrid16x16n128")
|
||
|
|
DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::HybridBoundsManager>(SkISize{1800, 1800}, 16, 128), "hybrid16x16n256")
|
||
|
|
// Uncomment and adjust device size to match reported bounds from --boundsManagerFile
|
||
|
|
// DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::MakeRes({w, h}, 8), "gridRes8")
|
||
|
|
|
||
|
|
#undef DEF_BOUNDS_MANAGER_BENCH_SET
|