Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
IntersectionTreeBench.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google Inc.
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"
10#include "src/base/SkMathPriv.h"
11#include "src/base/SkRandom.h"
13#include "tools/ToolUtils.h"
15
16#if defined(SK_ENABLE_SVG)
18#endif
19
20using namespace skia_private;
21
22static DEFINE_string(intersectionTreeFile, "",
23 "svg or skp for the IntersectionTree bench to sniff paths from.");
24
25namespace skgpu::graphite {
26
28protected:
29 const char* onGetName() final { return fName.c_str(); }
30
31 bool isSuitableFor(Backend backend) override {
33 }
34
35 void onDelayedSetup() final {
36 TArray<SkRect> rects;
37 this->gatherRects(&rects);
38 fRectCount = rects.size();
40 for (int i = 0; i < fRectCount; ++i) {
41 fRects[i] = rects[i];
42 }
45 }
46
47 virtual void gatherRects(TArray<SkRect>* rects) = 0;
48
49 void onDraw(int loops, SkCanvas*) final {
50 for (int i = 0; i < loops; ++i) {
51 this->doBench();
52 }
53 }
54
55 void doBench() {
56 Rect* rects = fRects;
57 Rect* collided = fRectBufferA;
58 int rectCount = fRectCount;
59 fNumTrees = 0;
60 while (rectCount > 0) {
61 IntersectionTree intersectionTree;
62 int collidedCount = 0;
63 for (int i = 0; i < rectCount; ++i) {
64 if (!intersectionTree.add(rects[i])) {
65 collided[collidedCount++] = rects[i];
66 }
67 }
68 std::swap(rects, collided);
69 if (collided == fRects) {
70 collided = fRectBufferB;
71 }
72 rectCount = collidedCount;
73 ++fNumTrees;
74 }
75 }
76
83 int fNumTrees = 0;
84};
85
87public:
88 RandomIntersectionBench(int numRandomRects) : fNumRandomRects(numRandomRects) {
89 fName.printf("IntersectionTree_%i", numRandomRects);
90 }
91
92private:
93 void gatherRects(TArray<SkRect>* rects) override {
94 SkRandom rand;
95 for (int i = 0; i < fNumRandomRects; ++i) {
96 rects->push_back(SkRect::MakeXYWH(rand.nextRangeF(0, 2000),
97 rand.nextRangeF(0, 2000),
98 rand.nextRangeF(0, 70),
99 rand.nextRangeF(0, 70)));
100 }
101 }
102
103 const int fNumRandomRects;
104};
105
107public:
109 if (FLAGS_intersectionTreeFile.isEmpty()) {
110 return;
111 }
112 const char* filename = strrchr(FLAGS_intersectionTreeFile[0], '/');
113 if (filename) {
114 ++filename;
115 } else {
116 filename = FLAGS_intersectionTreeFile[0];
117 }
118 fName.printf("IntersectionTree_file_%s", filename);
119 }
120
121private:
122 bool isSuitableFor(Backend backend) final {
123 if (FLAGS_intersectionTreeFile.isEmpty()) {
124 return false;
125 }
127 }
128
129 void gatherRects(TArray<SkRect>* rects) override {
130 if (FLAGS_intersectionTreeFile.isEmpty()) {
131 return;
132 }
133 auto callback = [&](const SkMatrix& matrix,
134 const SkPath& path,
135 const SkPaint& paint) {
136 if (paint.getStyle() == SkPaint::kStroke_Style) {
137 return; // Goes to stroker.
138 }
139 if (path.isConvex()) {
140 return; // Goes to convex renderer.
141 }
142 int numVerbs = path.countVerbs();
143 SkRect drawBounds = matrix.mapRect(path.getBounds());
144 float gpuFragmentWork = drawBounds.height() * drawBounds.width();
145 float cpuTessellationWork = numVerbs * SkNextLog2(numVerbs); // N log N.
146 constexpr static float kCpuWeight = 512;
147 constexpr static float kMinNumPixelsToTriangulate = 256 * 256;
148 if (cpuTessellationWork * kCpuWeight + kMinNumPixelsToTriangulate < gpuFragmentWork) {
149 return; // Goes to inner triangulator.
150 }
151 rects->push_back(drawBounds);
152 };
153 const char* path = FLAGS_intersectionTreeFile[0];
154 if (const char* ext = strrchr(path, '.'); ext && !strcmp(ext, ".svg")) {
155#if defined(SK_ENABLE_SVG)
157#else
158 SK_ABORT("must compile with svg backend to process svgs");
159#endif
160 } else {
162 }
163 SkDebugf(">> Found %i stencil/cover paths in %s <<\n",
164 rects->size(), FLAGS_intersectionTreeFile[0]);
165 }
166
168 if (FLAGS_intersectionTreeFile.isEmpty()) {
169 return;
170 }
171 SkDebugf(">> Reordered %s into %i different stencil/cover draws <<\n",
172 FLAGS_intersectionTreeFile[0], fNumTrees);
173 }
174};
175
176} // namespace skgpu::graphite
177
183DEF_BENCH( return new skgpu::graphite::FileIntersectionBench(); ) // Sniffs --intersectionTreeFile
#define DEF_BENCH(code)
Definition Benchmark.h:20
#define DEFINE_string(name, defaultValue, helpString)
const char * backend
#define SK_ABORT(message,...)
Definition SkAssert.h:70
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static int SkNextLog2(uint32_t value)
Definition SkMathPriv.h:238
T * makeArray(size_t count)
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
float nextRangeF(float min, float max)
Definition SkRandom.h:64
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition SkString.cpp:534
const char * c_str() const
Definition SkString.h:133
void gatherRects(TArray< SkRect > *rects) override
bool isSuitableFor(Backend backend) override
void onDraw(int loops, SkCanvas *) final
virtual void gatherRects(TArray< SkRect > *rects)=0
void gatherRects(TArray< SkRect > *rects) override
int size() const
Definition SkTArray.h:416
const Paint & paint
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
void ExtractPathsFromSVG(const char filepath[], std::function< PathSniffCallback >)
void ExtractPathsFromSKP(const char filepath[], std::function< PathSniffCallback > callback)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
constexpr float height() const
Definition SkRect.h:769
constexpr float width() const
Definition SkRect.h:762