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