1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h" 8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/BoundsManager.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommandLineFlags.h" 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SVG) 17*c8dee2aaSAndroid Build Coastguard Worker #include "tools/SvgPathExtractor.h" 18*c8dee2aaSAndroid Build Coastguard Worker #endif 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private; 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(boundsManagerFile, "", 23*c8dee2aaSAndroid Build Coastguard Worker "svg or skp for the BoundsManager bench to sniff paths from."); 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker #define PRINT_DRAWSET_COUNT 0 // set to 1 to display number of CompressedPaintersOrder groups 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite { 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker class BoundsManagerBench : public Benchmark { 30*c8dee2aaSAndroid Build Coastguard Worker public: BoundsManagerBench(std::unique_ptr<BoundsManager> manager)31*c8dee2aaSAndroid Build Coastguard Worker BoundsManagerBench(std::unique_ptr<BoundsManager> manager) : fManager(std::move(manager)) {} 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker protected: 34*c8dee2aaSAndroid Build Coastguard Worker virtual void gatherRects(TArray<SkRect>* rects) = 0; 35*c8dee2aaSAndroid Build Coastguard Worker isSuitableFor(Backend backend)36*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend backend) override { 37*c8dee2aaSAndroid Build Coastguard Worker return backend == Backend::kNonRendering; 38*c8dee2aaSAndroid Build Coastguard Worker } 39*c8dee2aaSAndroid Build Coastguard Worker onGetName()40*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() final { return fName.c_str(); } 41*c8dee2aaSAndroid Build Coastguard Worker onDelayedSetup()42*c8dee2aaSAndroid Build Coastguard Worker void onDelayedSetup() final { 43*c8dee2aaSAndroid Build Coastguard Worker TArray<SkRect> rects; 44*c8dee2aaSAndroid Build Coastguard Worker this->gatherRects(&rects); 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker fRectCount = rects.size(); 47*c8dee2aaSAndroid Build Coastguard Worker fRects = fAlignedAllocator.makeArray<Rect>(fRectCount); 48*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fRectCount; ++i) { 49*c8dee2aaSAndroid Build Coastguard Worker fRects[i] = rects[i]; 50*c8dee2aaSAndroid Build Coastguard Worker } 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas *)53*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) final { 54*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 55*c8dee2aaSAndroid Build Coastguard Worker this->doBench(); 56*c8dee2aaSAndroid Build Coastguard Worker } 57*c8dee2aaSAndroid Build Coastguard Worker } 58*c8dee2aaSAndroid Build Coastguard Worker onPerCanvasPostDraw(SkCanvas *)59*c8dee2aaSAndroid Build Coastguard Worker void onPerCanvasPostDraw(SkCanvas*) override { 60*c8dee2aaSAndroid Build Coastguard Worker #if PRINT_DRAWSET_COUNT 61*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s >> grouped %d draws into %d sets <<\n", 62*c8dee2aaSAndroid Build Coastguard Worker fName.c_str(), fRectCount, fMaxRead.bits()); 63*c8dee2aaSAndroid Build Coastguard Worker #endif 64*c8dee2aaSAndroid Build Coastguard Worker } 65*c8dee2aaSAndroid Build Coastguard Worker doBench()66*c8dee2aaSAndroid Build Coastguard Worker void doBench() { 67*c8dee2aaSAndroid Build Coastguard Worker CompressedPaintersOrder maxRead = CompressedPaintersOrder::First(); 68*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fRectCount; ++i) { 69*c8dee2aaSAndroid Build Coastguard Worker const Rect& drawBounds = fRects[i]; 70*c8dee2aaSAndroid Build Coastguard Worker CompressedPaintersOrder order = fManager->getMostRecentDraw(drawBounds).next(); 71*c8dee2aaSAndroid Build Coastguard Worker fManager->recordDraw(drawBounds, order); 72*c8dee2aaSAndroid Build Coastguard Worker if (order > maxRead) { 73*c8dee2aaSAndroid Build Coastguard Worker maxRead = order; 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker } 76*c8dee2aaSAndroid Build Coastguard Worker 77*c8dee2aaSAndroid Build Coastguard Worker fMaxRead = maxRead; 78*c8dee2aaSAndroid Build Coastguard Worker fManager->reset(); 79*c8dee2aaSAndroid Build Coastguard Worker } 80*c8dee2aaSAndroid Build Coastguard Worker 81*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<BoundsManager> fManager; 82*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 83*c8dee2aaSAndroid Build Coastguard Worker SkArenaAlloc fAlignedAllocator{0}; 84*c8dee2aaSAndroid Build Coastguard Worker int fRectCount; 85*c8dee2aaSAndroid Build Coastguard Worker Rect* fRects; 86*c8dee2aaSAndroid Build Coastguard Worker 87*c8dee2aaSAndroid Build Coastguard Worker CompressedPaintersOrder fMaxRead; 88*c8dee2aaSAndroid Build Coastguard Worker }; 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker class RandomBoundsManagerBench : public BoundsManagerBench { 91*c8dee2aaSAndroid Build Coastguard Worker public: RandomBoundsManagerBench(std::unique_ptr<BoundsManager> manager,const char * managerName,int numRandomRects)92*c8dee2aaSAndroid Build Coastguard Worker RandomBoundsManagerBench(std::unique_ptr<BoundsManager> manager, 93*c8dee2aaSAndroid Build Coastguard Worker const char* managerName, 94*c8dee2aaSAndroid Build Coastguard Worker int numRandomRects) 95*c8dee2aaSAndroid Build Coastguard Worker : BoundsManagerBench(std::move(manager)) 96*c8dee2aaSAndroid Build Coastguard Worker , fNumRandomRects(numRandomRects) { 97*c8dee2aaSAndroid Build Coastguard Worker fName.printf("BoundsManager_rand_%i_%s", numRandomRects, managerName); 98*c8dee2aaSAndroid Build Coastguard Worker } 99*c8dee2aaSAndroid Build Coastguard Worker 100*c8dee2aaSAndroid Build Coastguard Worker private: gatherRects(TArray<SkRect> * rects)101*c8dee2aaSAndroid Build Coastguard Worker void gatherRects(TArray<SkRect>* rects) override { 102*c8dee2aaSAndroid Build Coastguard Worker SkRandom rand; 103*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fNumRandomRects; ++i) { 104*c8dee2aaSAndroid Build Coastguard Worker rects->push_back(SkRect::MakeXYWH(rand.nextRangeF(0, 2000), 105*c8dee2aaSAndroid Build Coastguard Worker rand.nextRangeF(0, 2000), 106*c8dee2aaSAndroid Build Coastguard Worker rand.nextRangeF(0, 70), 107*c8dee2aaSAndroid Build Coastguard Worker rand.nextRangeF(0, 70))); 108*c8dee2aaSAndroid Build Coastguard Worker } 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker int fNumRandomRects; 112*c8dee2aaSAndroid Build Coastguard Worker }; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker class FileBoundsManagerBench : public BoundsManagerBench { 115*c8dee2aaSAndroid Build Coastguard Worker public: FileBoundsManagerBench(std::unique_ptr<BoundsManager> manager,const char * managerName)116*c8dee2aaSAndroid Build Coastguard Worker FileBoundsManagerBench(std::unique_ptr<BoundsManager> manager, 117*c8dee2aaSAndroid Build Coastguard Worker const char* managerName) 118*c8dee2aaSAndroid Build Coastguard Worker : BoundsManagerBench(std::move(manager)) { 119*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_boundsManagerFile.isEmpty()) { 120*c8dee2aaSAndroid Build Coastguard Worker const char* filename = strrchr(FLAGS_boundsManagerFile[0], '/'); 121*c8dee2aaSAndroid Build Coastguard Worker if (filename) { 122*c8dee2aaSAndroid Build Coastguard Worker ++filename; 123*c8dee2aaSAndroid Build Coastguard Worker } else { 124*c8dee2aaSAndroid Build Coastguard Worker filename = FLAGS_boundsManagerFile[0]; 125*c8dee2aaSAndroid Build Coastguard Worker } 126*c8dee2aaSAndroid Build Coastguard Worker fName.printf("BoundsManager_file_%s_%s", filename, managerName); 127*c8dee2aaSAndroid Build Coastguard Worker } 128*c8dee2aaSAndroid Build Coastguard Worker } 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Worker private: isSuitableFor(Backend backend)131*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend backend) final { 132*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_boundsManagerFile.isEmpty()) { 133*c8dee2aaSAndroid Build Coastguard Worker return false; 134*c8dee2aaSAndroid Build Coastguard Worker } 135*c8dee2aaSAndroid Build Coastguard Worker return BoundsManagerBench::isSuitableFor(backend); 136*c8dee2aaSAndroid Build Coastguard Worker } 137*c8dee2aaSAndroid Build Coastguard Worker gatherRects(TArray<SkRect> * rects)138*c8dee2aaSAndroid Build Coastguard Worker void gatherRects(TArray<SkRect>* rects) override { 139*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_boundsManagerFile.isEmpty()) { 140*c8dee2aaSAndroid Build Coastguard Worker return; 141*c8dee2aaSAndroid Build Coastguard Worker } 142*c8dee2aaSAndroid Build Coastguard Worker SkRect fileBounds = SkRect::MakeEmpty(); 143*c8dee2aaSAndroid Build Coastguard Worker auto callback = [&](const SkMatrix& matrix, 144*c8dee2aaSAndroid Build Coastguard Worker const SkPath& path, 145*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint) { 146*c8dee2aaSAndroid Build Coastguard Worker if (!paint.canComputeFastBounds() || path.isInverseFillType()) { 147*c8dee2aaSAndroid Build Coastguard Worker // These would pessimistically cover the entire canvas, but we don't have enough 148*c8dee2aaSAndroid Build Coastguard Worker // info in the benchmark to handle that, so just skip these draws. 149*c8dee2aaSAndroid Build Coastguard Worker return; 150*c8dee2aaSAndroid Build Coastguard Worker } 151*c8dee2aaSAndroid Build Coastguard Worker 152*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds = path.getBounds(); 153*c8dee2aaSAndroid Build Coastguard Worker SkRect drawBounds = matrix.mapRect(paint.computeFastBounds(bounds, &bounds)); 154*c8dee2aaSAndroid Build Coastguard Worker rects->push_back(drawBounds); 155*c8dee2aaSAndroid Build Coastguard Worker 156*c8dee2aaSAndroid Build Coastguard Worker fileBounds.join(drawBounds); 157*c8dee2aaSAndroid Build Coastguard Worker }; 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker const char* path = FLAGS_boundsManagerFile[0]; 160*c8dee2aaSAndroid Build Coastguard Worker if (const char* ext = strrchr(path, '.'); ext && !strcmp(ext, ".svg")) { 161*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SVG) 162*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::ExtractPathsFromSVG(path, callback); 163*c8dee2aaSAndroid Build Coastguard Worker #else 164*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("must compile with svg backend to process svgs"); 165*c8dee2aaSAndroid Build Coastguard Worker #endif 166*c8dee2aaSAndroid Build Coastguard Worker } else { 167*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::ExtractPathsFromSKP(path, callback); 168*c8dee2aaSAndroid Build Coastguard Worker } 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker #if PRINT_DRAWSET_COUNT 171*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s bounds are [%f %f %f %f]\n", 172*c8dee2aaSAndroid Build Coastguard Worker FLAGS_boundsManagerFile[0], 173*c8dee2aaSAndroid Build Coastguard Worker fileBounds.fLeft, fileBounds.fTop, fileBounds.fRight, fileBounds.fBottom); 174*c8dee2aaSAndroid Build Coastguard Worker #endif 175*c8dee2aaSAndroid Build Coastguard Worker } 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Worker }; 178*c8dee2aaSAndroid Build Coastguard Worker 179*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite 180*c8dee2aaSAndroid Build Coastguard Worker 181*c8dee2aaSAndroid Build Coastguard Worker #define DEF_BOUNDS_MANAGER_BENCH_SET(manager, name) \ 182*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 100); ) \ 183*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 500); ) \ 184*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 1000); ) \ 185*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new skgpu::graphite::RandomBoundsManagerBench(manager, name, 10000); ) \ 186*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new skgpu::graphite::FileBoundsManagerBench(manager, name); ) 187*c8dee2aaSAndroid Build Coastguard Worker 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::NaiveBoundsManager>(), "naive") 190*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::BruteForceBoundsManager>(), "brute") 191*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::Make({1800, 1800}, 128), "grid128") 192*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::Make({1800, 1800}, 512), "grid512") 193*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::HybridBoundsManager>(SkISize{1800, 1800}, 16, 64), "hybrid16x16n128") 194*c8dee2aaSAndroid Build Coastguard Worker DEF_BOUNDS_MANAGER_BENCH_SET(std::make_unique<skgpu::graphite::HybridBoundsManager>(SkISize{1800, 1800}, 16, 128), "hybrid16x16n256") 195*c8dee2aaSAndroid Build Coastguard Worker // Uncomment and adjust device size to match reported bounds from --boundsManagerFile 196*c8dee2aaSAndroid Build Coastguard Worker // DEF_BOUNDS_MANAGER_BENCH_SET(skgpu::graphite::GridBoundsManager::MakeRes({w, h}, 8), "gridRes8") 197*c8dee2aaSAndroid Build Coastguard Worker 198*c8dee2aaSAndroid Build Coastguard Worker #undef DEF_BOUNDS_MANAGER_BENCH_SET 199