xref: /aosp_15_r20/external/skia/bench/graphite/BoundsManagerBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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