blob: 012b52e2fb9bb240cfa1d8cfe998120b1c4ef0f3 [file] [log] [blame]
Chris Dalton7f0b8972020-04-23 15:52:24 -06001/*
2 * Copyright 2020 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
8#include "bench/Benchmark.h"
Robert Phillipsf0288102020-07-06 13:45:34 -04009#include "include/gpu/GrDirectContext.h"
Chris Daltonf6bf5162020-05-13 19:18:46 -060010#include "src/core/SkPathPriv.h"
Adlai Hollera0693042020-10-14 11:23:11 -040011#include "src/gpu/GrDirectContextPriv.h"
Chris Dalton7f0b8972020-04-23 15:52:24 -060012#include "src/gpu/GrOpFlushState.h"
Chris Dalton90ad0fe2020-11-09 14:13:39 -070013#include "src/gpu/mock/GrMockOpTarget.h"
Chris Daltonb5391d92020-05-24 14:55:54 -060014#include "src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h"
Chris Dalton078f8752020-07-30 19:50:46 -060015#include "src/gpu/tessellate/GrPathTessellateOp.h"
Chris Daltonb5391d92020-05-24 14:55:54 -060016#include "src/gpu/tessellate/GrResolveLevelCounter.h"
Chris Daltonc2a17462020-12-09 16:46:22 -070017#include "src/gpu/tessellate/GrStrokeIndirectOp.h"
Chris Dalton0e543092020-11-03 14:09:16 -070018#include "src/gpu/tessellate/GrStrokeTessellateOp.h"
Chris Daltonf6bf5162020-05-13 19:18:46 -060019#include "src/gpu/tessellate/GrWangsFormula.h"
Chris Daltonf5132a02020-04-27 23:40:03 -060020#include "tools/ToolUtils.h"
Chris Daltonc2a17462020-12-09 16:46:22 -070021#include <vector>
Chris Dalton7f0b8972020-04-23 15:52:24 -060022
23// This is the number of cubics in desk_chalkboard.skp. (There are no quadratics in the chalkboard.)
24constexpr static int kNumCubicsInChalkboard = 47182;
25
Chris Dalton90ad0fe2020-11-09 14:13:39 -070026static sk_sp<GrDirectContext> make_mock_context() {
27 GrMockOptions mockOptions;
28 mockOptions.fDrawInstancedSupport = true;
29 mockOptions.fMaxTessellationSegments = 64;
30 mockOptions.fMapBufferFlags = GrCaps::kCanMap_MapFlag;
31 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fRenderability =
32 GrMockOptions::ConfigOptions::Renderability::kMSAA;
33 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fTexturable = true;
34 mockOptions.fIntegerSupport = true;
35
36 GrContextOptions ctxOptions;
37 ctxOptions.fGpuPathRenderers = GpuPathRenderers::kTessellation;
Chris Dalton15f51842020-12-15 19:55:10 -070038 ctxOptions.fSuppressTessellationShaders = false;
Chris Dalton90ad0fe2020-11-09 14:13:39 -070039
40 return GrDirectContext::MakeMock(&mockOptions, ctxOptions);
41}
42
Chris Dalton7f0b8972020-04-23 15:52:24 -060043static SkPath make_cubic_path() {
44 SkRandom rand;
45 SkPath path;
46 for (int i = 0; i < kNumCubicsInChalkboard/2; ++i) {
Chris Dalton2f2d81c2020-05-13 17:57:37 -060047 float x = std::ldexp(rand.nextF(), (i % 18)) / 1e3f;
Chris Dalton7f0b8972020-04-23 15:52:24 -060048 path.cubicTo(111.625f*x, 308.188f*x, 764.62f*x, -435.688f*x, 742.63f*x, 85.187f*x);
49 path.cubicTo(764.62f*x, -435.688f*x, 111.625f*x, 308.188f*x, 0, 0);
50 }
51 return path;
52}
53
Chris Dalton078f8752020-07-30 19:50:46 -060054// This serves as a base class for benchmarking individual methods on GrPathTessellateOp.
55class GrPathTessellateOp::TestingOnly_Benchmark : public Benchmark {
Chris Dalton7f0b8972020-04-23 15:52:24 -060056public:
57 TestingOnly_Benchmark(const char* subName, SkPath path, const SkMatrix& m)
Chris Daltonb96995d2020-06-04 16:44:29 -060058 : fOp(m, path, GrPaint(), GrAAType::kMSAA, GrTessellationPathRenderer::OpFlags::kNone) {
Chris Dalton7f0b8972020-04-23 15:52:24 -060059 fName.printf("tessellate_%s", subName);
60 }
61
62 const char* onGetName() override { return fName.c_str(); }
63 bool isSuitableFor(Backend backend) final { return backend == kNonRendering_Backend; }
64
Chris Daltonb5391d92020-05-24 14:55:54 -060065 class prepareMiddleOutStencilGeometry;
66 class prepareMiddleOutStencilGeometry_indirect;
67 class prepareIndirectOuterCubics;
68 class prepareTessellatedOuterCubics;
69 class prepareTessellatedCubicWedges;
70 class wangs_formula_cubic_log2;
71 class wangs_formula_cubic_log2_scale;
72 class wangs_formula_cubic_log2_affine;
73 class middle_out_triangulation;
Chris Dalton7f0b8972020-04-23 15:52:24 -060074
75private:
Chris Dalton0e543092020-11-03 14:09:16 -070076 void onDelayedSetup() override {
Chris Dalton90ad0fe2020-11-09 14:13:39 -070077 fTarget = std::make_unique<GrMockOpTarget>(make_mock_context());
Chris Dalton0e543092020-11-03 14:09:16 -070078 }
79
Chris Dalton7f0b8972020-04-23 15:52:24 -060080 void onDraw(int loops, SkCanvas*) final {
Chris Dalton0e543092020-11-03 14:09:16 -070081 if (!fTarget->mockContext()) {
Chris Dalton1443c9d2020-05-27 09:43:34 -060082 SkDebugf("ERROR: could not create mock context.");
83 return;
84 }
Chris Dalton7f0b8972020-04-23 15:52:24 -060085 for (int i = 0; i < loops; ++i) {
86 fOp.fTriangleBuffer.reset();
Chris Daltone74cebe2020-09-24 09:32:54 -060087 fOp.fTriangleVertexCount = 0;
Chris Dalton5e1545f2020-09-25 16:24:03 -060088 fOp.fPipelineForStencils = nullptr;
89 fOp.fPipelineForFills = nullptr;
Chris Daltone74cebe2020-09-24 09:32:54 -060090 fOp.fStencilTrianglesProgram = nullptr;
Chris Dalton5e1545f2020-09-25 16:24:03 -060091 fOp.fFillTrianglesProgram = nullptr;
Chris Dalton7f0b8972020-04-23 15:52:24 -060092 fOp.fCubicBuffer.reset();
Chris Daltone74cebe2020-09-24 09:32:54 -060093 fOp.fCubicVertexCount = 0;
Chris Dalton5e1545f2020-09-25 16:24:03 -060094 // Make fStencilCubicsProgram non-null to keep assertions happy.
Chris Daltone74cebe2020-09-24 09:32:54 -060095 fOp.fStencilCubicsProgram = (GrProgramInfo*)-1;
Chris Dalton5e1545f2020-09-25 16:24:03 -060096 fOp.fFillPathProgram = nullptr;
Chris Dalton0e543092020-11-03 14:09:16 -070097 this->runBench(fTarget.get(), &fOp);
98 fTarget->resetAllocator();
Chris Dalton7f0b8972020-04-23 15:52:24 -060099 }
100 }
101
Chris Dalton078f8752020-07-30 19:50:46 -0600102 virtual void runBench(GrMeshDrawOp::Target*, GrPathTessellateOp*) = 0;
Chris Dalton7f0b8972020-04-23 15:52:24 -0600103
Chris Dalton078f8752020-07-30 19:50:46 -0600104 GrPathTessellateOp fOp;
Chris Dalton90ad0fe2020-11-09 14:13:39 -0700105 std::unique_ptr<GrMockOpTarget> fTarget;
Chris Dalton7f0b8972020-04-23 15:52:24 -0600106 SkString fName;
107};
108
Chris Daltone2067642020-09-23 11:07:20 -0600109#define DEF_PATH_TESS_BENCH(NAME, PATH, MATRIX, TARGET, OP) \
Chris Dalton078f8752020-07-30 19:50:46 -0600110 class GrPathTessellateOp::TestingOnly_Benchmark::NAME \
111 : public GrPathTessellateOp::TestingOnly_Benchmark { \
Chris Daltonb5391d92020-05-24 14:55:54 -0600112 public: \
113 NAME() : TestingOnly_Benchmark(#NAME, (PATH), (MATRIX)) {} \
Chris Dalton078f8752020-07-30 19:50:46 -0600114 void runBench(GrMeshDrawOp::Target* target, GrPathTessellateOp* op) override; \
Chris Daltonb5391d92020-05-24 14:55:54 -0600115 }; \
Chris Dalton078f8752020-07-30 19:50:46 -0600116 DEF_BENCH( return new GrPathTessellateOp::TestingOnly_Benchmark::NAME(); ); \
117 void GrPathTessellateOp::TestingOnly_Benchmark::NAME::runBench( \
118 GrMeshDrawOp::Target* TARGET, GrPathTessellateOp* op)
Chris Dalton7f0b8972020-04-23 15:52:24 -0600119
Chris Daltone2067642020-09-23 11:07:20 -0600120DEF_PATH_TESS_BENCH(prepareMiddleOutStencilGeometry, make_cubic_path(), SkMatrix::I(), target, op) {
Chris Daltone74cebe2020-09-24 09:32:54 -0600121 // Make fStencilTrianglesProgram non-null so we benchmark the tessellation path with separate
122 // triangles.
123 op->fStencilTrianglesProgram = (GrProgramInfo*)-1;
Chris Daltonb5391d92020-05-24 14:55:54 -0600124 op->prepareMiddleOutTrianglesAndCubics(target);
125}
Chris Dalton7f0b8972020-04-23 15:52:24 -0600126
Chris Daltone2067642020-09-23 11:07:20 -0600127DEF_PATH_TESS_BENCH(prepareMiddleOutStencilGeometry_indirect, make_cubic_path(), SkMatrix::I(),
128 target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600129 GrResolveLevelCounter resolveLevelCounter;
Chris Daltone74cebe2020-09-24 09:32:54 -0600130 op->prepareMiddleOutTrianglesAndCubics(target, &resolveLevelCounter);
Chris Daltonb5391d92020-05-24 14:55:54 -0600131}
Chris Dalton7f0b8972020-04-23 15:52:24 -0600132
Chris Daltone2067642020-09-23 11:07:20 -0600133DEF_PATH_TESS_BENCH(prepareIndirectOuterCubics, make_cubic_path(), SkMatrix::I(), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600134 GrResolveLevelCounter resolveLevelCounter;
135 resolveLevelCounter.reset(op->fPath, SkMatrix::I(), 4);
136 op->prepareIndirectOuterCubics(target, resolveLevelCounter);
137}
Chris Dalton7f0b8972020-04-23 15:52:24 -0600138
Chris Daltone2067642020-09-23 11:07:20 -0600139DEF_PATH_TESS_BENCH(prepareTessellatedOuterCubics, make_cubic_path(), SkMatrix::I(), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600140 op->prepareTessellatedOuterCubics(target, kNumCubicsInChalkboard);
141}
Chris Dalton7f0b8972020-04-23 15:52:24 -0600142
Chris Daltone2067642020-09-23 11:07:20 -0600143DEF_PATH_TESS_BENCH(prepareTessellatedCubicWedges, make_cubic_path(), SkMatrix::I(), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600144 op->prepareTessellatedCubicWedges(target);
145}
Chris Daltonf6bf5162020-05-13 19:18:46 -0600146
Chris Daltonb5391d92020-05-24 14:55:54 -0600147static void benchmark_wangs_formula_cubic_log2(const SkMatrix& matrix, const SkPath& path) {
148 int sum = 0;
149 GrVectorXform xform(matrix);
150 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
151 if (verb == SkPathVerb::kCubic) {
152 sum += GrWangsFormula::cubic_log2(4, pts, xform);
Chris Daltonf6bf5162020-05-13 19:18:46 -0600153 }
154 }
Chris Daltonb5391d92020-05-24 14:55:54 -0600155 // Don't let the compiler optimize away GrWangsFormula::cubic_log2.
156 if (sum <= 0) {
157 SK_ABORT("sum should be > 0.");
158 }
159}
Chris Daltonf6bf5162020-05-13 19:18:46 -0600160
Chris Daltone2067642020-09-23 11:07:20 -0600161DEF_PATH_TESS_BENCH(wangs_formula_cubic_log2, make_cubic_path(), SkMatrix::I(), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600162 benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
163}
164
Chris Daltone2067642020-09-23 11:07:20 -0600165DEF_PATH_TESS_BENCH(wangs_formula_cubic_log2_scale, make_cubic_path(), SkMatrix::Scale(1.1f, 0.9f),
166 target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600167 benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
168}
169
Chris Daltone2067642020-09-23 11:07:20 -0600170DEF_PATH_TESS_BENCH(wangs_formula_cubic_log2_affine, make_cubic_path(),
171 SkMatrix::MakeAll(.9f,0.9f,0, 1.1f,1.1f,0, 0,0,1), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600172 benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
173}
174
Chris Daltone2067642020-09-23 11:07:20 -0600175DEF_PATH_TESS_BENCH(middle_out_triangulation,
176 ToolUtils::make_star(SkRect::MakeWH(500, 500), kNumCubicsInChalkboard),
177 SkMatrix::I(), target, op) {
Chris Daltonb5391d92020-05-24 14:55:54 -0600178 int baseVertex;
179 auto vertexData = static_cast<SkPoint*>(target->makeVertexSpace(
180 sizeof(SkPoint), kNumCubicsInChalkboard, nullptr, &baseVertex));
181 GrMiddleOutPolygonTriangulator middleOut(vertexData, 3, kNumCubicsInChalkboard + 2);
182 for (auto [verb, pts, w] : SkPathPriv::Iterate(op->fPath)) {
183 switch (verb) {
184 case SkPathVerb::kMove:
185 middleOut.closeAndMove(pts[0]);
186 break;
187 case SkPathVerb::kLine:
188 middleOut.pushVertex(pts[1]);
189 break;
190 case SkPathVerb::kClose:
191 middleOut.close();
192 break;
193 case SkPathVerb::kQuad:
194 case SkPathVerb::kConic:
195 case SkPathVerb::kCubic:
196 SkUNREACHABLE;
197 }
198 middleOut.closeAndMove(pts[0]);
199 }
200}
Chris Daltone2067642020-09-23 11:07:20 -0600201
Chris Dalton0e543092020-11-03 14:09:16 -0700202class GrStrokeTessellateOp::TestingOnly_Benchmark : public Benchmark {
Chris Dalton2882e702020-11-02 12:43:06 -0700203public:
Chris Dalton0e543092020-11-03 14:09:16 -0700204 TestingOnly_Benchmark(float matrixScale, const char* suffix) : fMatrixScale(matrixScale) {
205 fName.printf("tessellate_GrStrokeTessellateOp_prepare%s", suffix);
Chris Dalton2882e702020-11-02 12:43:06 -0700206 }
207
208private:
209 const char* onGetName() override { return fName.c_str(); }
Chris Daltone2067642020-09-23 11:07:20 -0600210 bool isSuitableFor(Backend backend) final { return backend == kNonRendering_Backend; }
211
212 void onDelayedSetup() override {
Chris Dalton90ad0fe2020-11-09 14:13:39 -0700213 fTarget = std::make_unique<GrMockOpTarget>(make_mock_context());
Chris Daltone2067642020-09-23 11:07:20 -0600214 fPath.reset().moveTo(0, 0);
215 for (int i = 0; i < kNumCubicsInChalkboard/2; ++i) {
Chris Dalton2882e702020-11-02 12:43:06 -0700216 fPath.cubicTo(100, 0, 50, 100, 100, 100);
217 fPath.cubicTo(0, -100, 200, 100, 0, 0);
Chris Daltone2067642020-09-23 11:07:20 -0600218 }
219 fStrokeRec.setStrokeStyle(8);
220 fStrokeRec.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kMiter_Join, 4);
221 }
222
223 void onDraw(int loops, SkCanvas*) final {
Chris Dalton0e543092020-11-03 14:09:16 -0700224 if (!fTarget->mockContext()) {
Chris Daltone2067642020-09-23 11:07:20 -0600225 SkDebugf("ERROR: could not create mock context.");
226 return;
227 }
228 for (int i = 0; i < loops; ++i) {
Chris Dalton0e543092020-11-03 14:09:16 -0700229 GrStrokeTessellateOp op(GrAAType::kMSAA, SkMatrix::Scale(fMatrixScale, fMatrixScale),
230 fStrokeRec, fPath, GrPaint());
231 op.fTarget = fTarget.get();
232 op.prepareBuffers();
Chris Daltone2067642020-09-23 11:07:20 -0600233 }
234 }
235
Chris Dalton2882e702020-11-02 12:43:06 -0700236 const float fMatrixScale;
237 SkString fName;
Chris Dalton90ad0fe2020-11-09 14:13:39 -0700238 std::unique_ptr<GrMockOpTarget> fTarget;
Chris Daltone2067642020-09-23 11:07:20 -0600239 SkPath fPath;
240 SkStrokeRec fStrokeRec = SkStrokeRec(SkStrokeRec::kFill_InitStyle);
Chris Daltone2067642020-09-23 11:07:20 -0600241};
242
Chris Dalton0e543092020-11-03 14:09:16 -0700243DEF_BENCH( return new GrStrokeTessellateOp::TestingOnly_Benchmark(1, ""); )
244DEF_BENCH( return new GrStrokeTessellateOp::TestingOnly_Benchmark(5, "_one_chop"); )
Chris Daltonc2a17462020-12-09 16:46:22 -0700245
246class GrStrokeIndirectOp::Benchmark : public ::Benchmark {
Chris Daltonad482802020-12-28 09:02:47 -0700247protected:
248 Benchmark(const char* nameSuffix, SkPaint::Join join) : fJoin(join) {
Chris Daltonc2a17462020-12-09 16:46:22 -0700249 fName.printf("tessellate_GrStrokeIndirectOpBench%s", nameSuffix);
250 }
251
Chris Daltonad482802020-12-28 09:02:47 -0700252 const SkPaint::Join fJoin;
Chris Daltonc2a17462020-12-09 16:46:22 -0700253
Chris Daltonad482802020-12-28 09:02:47 -0700254private:
255 const char* onGetName() final { return fName.c_str(); }
256 bool isSuitableFor(Backend backend) final { return backend == kNonRendering_Backend; }
257 void onDelayedSetup() final {
Chris Daltonc2a17462020-12-09 16:46:22 -0700258 fTarget = std::make_unique<GrMockOpTarget>(make_mock_context());
Chris Daltonc2a17462020-12-09 16:46:22 -0700259 fStrokeRec.setStrokeStyle(8);
260 fStrokeRec.setStrokeParams(SkPaint::kButt_Cap, fJoin, 4);
Chris Daltonad482802020-12-28 09:02:47 -0700261 this->setupPaths(&fPaths);
Chris Daltonc2a17462020-12-09 16:46:22 -0700262 }
Chris Daltonc2a17462020-12-09 16:46:22 -0700263 void onDraw(int loops, SkCanvas*) final {
264 if (!fTarget->mockContext()) {
265 SkDebugf("ERROR: could not create mock context.");
266 return;
267 }
268 for (int i = 0; i < loops; ++i) {
Chris Daltonad482802020-12-28 09:02:47 -0700269 for (const SkPath& path : fPaths) {
270 GrStrokeIndirectOp op(GrAAType::kMSAA, SkMatrix::I(), path, fStrokeRec, GrPaint());
271 op.prePrepareResolveLevels(fTarget->allocator());
272 op.prepareBuffers(fTarget.get());
273 }
274 fTarget->resetAllocator();
275 }
276 }
277 virtual void setupPaths(SkTArray<SkPath>*) = 0;
278
279 SkString fName;
280 std::unique_ptr<GrMockOpTarget> fTarget;
281 SkTArray<SkPath> fPaths;
282 SkStrokeRec fStrokeRec{SkStrokeRec::kHairline_InitStyle};
283};
284
285class StrokeIndirectBenchmark : public GrStrokeIndirectOp::Benchmark {
286public:
287 StrokeIndirectBenchmark(const char* nameSuffix, SkPaint::Join join, std::vector<SkPoint> pts)
288 : Benchmark(nameSuffix, join), fPts(std::move(pts)) {}
289
290private:
291 void setupPaths(SkTArray<SkPath>* paths) final {
292 SkPath& path = paths->push_back();
293 if (fJoin == SkPaint::kRound_Join) {
294 path.reset().moveTo(fPts.back());
295 for (size_t i = 0; i < kNumCubicsInChalkboard/fPts.size(); ++i) {
296 for (size_t j = 0; j < fPts.size(); ++j) {
297 path.lineTo(fPts[j]);
298 }
299 }
300 } else {
301 path.reset().moveTo(fPts[0]);
302 for (int i = 0; i < kNumCubicsInChalkboard/2; ++i) {
303 if (fPts.size() == 4) {
304 path.cubicTo(fPts[1], fPts[2], fPts[3]);
305 path.cubicTo(fPts[2], fPts[1], fPts[0]);
306 } else {
307 SkASSERT(fPts.size() == 3);
308 path.quadTo(fPts[1], fPts[2]);
309 path.quadTo(fPts[2], fPts[1]);
310 }
311 }
Chris Daltonc2a17462020-12-09 16:46:22 -0700312 }
313 }
314
Chris Daltonad482802020-12-28 09:02:47 -0700315 const std::vector<SkPoint> fPts;
Chris Daltonc2a17462020-12-09 16:46:22 -0700316};
317
Chris Daltonad482802020-12-28 09:02:47 -0700318DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700319 "_inflect1", SkPaint::kBevel_Join, {{0,0}, {100,0}, {0,100}, {100,100}}); )
320
Chris Daltonad482802020-12-28 09:02:47 -0700321DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700322 "_inflect2", SkPaint::kBevel_Join, {{37,162}, {412,160}, {249,65}, {112,360}}); )
323
Chris Daltonad482802020-12-28 09:02:47 -0700324DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700325 "_loop", SkPaint::kBevel_Join, {{0,0}, {100,0}, {0,100}, {0,0}}); )
326
Chris Daltonad482802020-12-28 09:02:47 -0700327DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700328 "_nochop", SkPaint::kBevel_Join, {{0,0}, {50,0}, {100,50}, {100,100}}); )
329
Chris Daltonad482802020-12-28 09:02:47 -0700330DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700331 "_quad", SkPaint::kBevel_Join, {{0,0}, {50,100}, {100,0}}); )
332
Chris Daltonad482802020-12-28 09:02:47 -0700333DEF_BENCH( return new StrokeIndirectBenchmark(
Chris Daltonc2a17462020-12-09 16:46:22 -0700334 "_roundjoin", SkPaint::kRound_Join, {{0,0}, {50,100}, {100,0}}); )
Chris Daltonad482802020-12-28 09:02:47 -0700335
336class SingleVerbStrokeIndirectBenchmark : public GrStrokeIndirectOp::Benchmark {
337public:
338 SingleVerbStrokeIndirectBenchmark(const char* nameSuffix, SkPathVerb verb)
339 : Benchmark(nameSuffix, SkPaint::kBevel_Join), fVerb(verb) {}
340
341private:
342 void setupPaths(SkTArray<SkPath>* paths) override {
343 SkRandom rand;
344 for (int i = 0; i < kNumCubicsInChalkboard; ++i) {
345 switch (fVerb) {
346 case SkPathVerb::kQuad:
347 paths->push_back().quadTo(rand.nextF(), rand.nextF(), rand.nextF(),
348 rand.nextF());
349 break;
350 case SkPathVerb::kCubic:
351 switch (i % 3) {
352 case 0:
353 paths->push_back().cubicTo(100, 0, 0, 100, 100, 100); // 1 inflection.
354 break;
355 case 1:
356 paths->push_back().cubicTo(100, 0, 0, 100, 0, 0); // loop.
357 break;
358 case 2:
359 paths->push_back().cubicTo(50, 0, 100, 50, 100, 100); // no chop.
360 break;
361 }
362 break;
363 default:
364 SkUNREACHABLE;
365 }
366 }
367 }
368
369 const SkPathVerb fVerb;
370};
371
372DEF_BENCH( return new SingleVerbStrokeIndirectBenchmark("_singlequads", SkPathVerb::kQuad); )
373DEF_BENCH( return new SingleVerbStrokeIndirectBenchmark("_singlecubics", SkPathVerb::kCubic); )