Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dl_transform_benchmarks.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <functional>
6
7#include "flutter/benchmarking/benchmarking.h"
8
9#include "flutter/impeller/geometry/matrix.h"
10#include "flutter/impeller/geometry/rect.h"
14
15namespace flutter {
16
17namespace {
18
19static constexpr float kPiOver4 = impeller::kPiOver4;
20
21static constexpr float kSimplePerspective[16] = {
22 // clang-format off
23 2.0f, 0.0f, 0.0f, 0.0f,
24 0.0f, 2.0f, 0.0f, 0.0f,
25 0.0f, 0.0f, 1.0f, 0.0f,
26 0.0f, 0.0f, 0.0f, 3.0f
27 // clang-format on
28};
29
30// The following matrices slowly slide a perspective-skewed transform of
31// the rect past the near clipping plane. Keeping the Y perspective factor
32// at -0.006 allows the X perspective factor to slowly move the transformed
33// rectangle into the clipping pane over the range of [-0.01, to -0.025].
34static constexpr float kClipOneCornerPerspective[16] = {
35 // clang-format off
36 2.0f, 0.0f, 0.0f, -0.01f,
37 0.0f, 2.0f, 0.0f, -0.006f,
38 0.0f, 0.0f, 1.0f, 0.0f,
39 0.0f, 0.0f, 0.0f, 3.0f
40 // clang-format on
41};
42
43static constexpr float kClipTwoCornersPerspective[16] = {
44 // clang-format off
45 2.0f, 0.0f, 0.0f, -.015f,
46 0.0f, 2.0f, 0.0f, -.006f,
47 0.0f, 0.0f, 1.0f, 0.0f,
48 0.0f, 0.0f, 0.0f, 3.0f
49 // clang-format on
50};
51
52static constexpr float kClipThreeCornersPerspective[16] = {
53 // clang-format off
54 2.0f, 0.0f, 0.0f, -.02f,
55 0.0f, 2.0f, 0.0f, -.006f,
56 0.0f, 0.0f, 1.0f, 0.0f,
57 0.0f, 0.0f, 0.0f, 3.0f
58 // clang-format on
59};
60
61static constexpr float kClipFourCornersPerspective[16] = {
62 // clang-format off
63 2.0f, 0.0f, 0.0f, -.025f,
64 0.0f, 2.0f, 0.0f, -.006f,
65 0.0f, 0.0f, 1.0f, 0.0f,
66 0.0f, 0.0f, 0.0f, 3.0f
67 // clang-format on
68};
69
70enum class AdapterType {
71 kSkMatrix,
72 kSkM44,
73 kImpellerMatrix,
74};
75
76union TestPoint {
77 TestPoint() {}
78
81};
82
83union TestRect {
84 TestRect() {}
85
88};
89
90union TestTransform {
91 TestTransform() {}
92
96};
97
98// We use a virtual adapter class rather than templating the BM_* methods
99// to prevent the compiler from optimizing the benchmark bodies into a
100// null set of instructions because the calculation can be proven to have
101// no side effects and the result is never used.
102class TransformAdapter {
103 public:
104 TransformAdapter() = default;
105 virtual ~TransformAdapter() = default;
106
107 // Two methods to test the overhead of just calling a virtual method on
108 // the adapter (should be the same for all inheriting subclasses) and
109 // for a method that does a conversion to and from the TestRect object
110 // (which should be the same as the method call overhead since it does
111 // no work).
112 virtual void DoNothing(TestTransform& ignored) const = 0;
113
114 virtual void InitRectLTRB(TestRect& rect,
115 float left,
116 float top,
117 float right,
118 float bottom) const = 0;
119 virtual void InitPoint(TestPoint& point, float x, float y) const = 0;
120
121 // The actual methods that do work and are the meat of the benchmarks.
122 virtual void InitTransformIdentity(TestTransform& result) const = 0;
123 virtual void InitTransformColMatrix(TestTransform& result,
124 const float m[16]) const = 0;
125
126 virtual void Translate(TestTransform& result, float tx, float ty) const = 0;
127 virtual void Scale(TestTransform& result, float sx, float sy) const = 0;
128 virtual void RotateRadians(TestTransform& result, float radians) const = 0;
129
130 virtual void Concat(const TestTransform& a,
131 const TestTransform& b,
132 TestTransform& result) const = 0;
133
134 virtual void TransformPoint(const TestTransform& transform,
135 const TestPoint& in,
136 TestPoint& out) const = 0;
137 virtual void TransformPoints(const TestTransform& transform,
138 const TestPoint in[],
139 TestPoint out[],
140 int n) const = 0;
141 virtual void TransformRectFast(const TestTransform& transform,
142 const TestRect& in,
143 TestRect& out) const = 0;
144 virtual void TransformAndClipRect(const TestTransform& transform,
145 const TestRect& in,
146 TestRect& out) const = 0;
147 virtual int CountClippedCorners(const TestTransform& transform,
148 const TestRect& rect) const = 0;
149 virtual void InvertUnchecked(const TestTransform& transform,
150 TestTransform& result) const = 0;
151 virtual bool InvertAndCheck(const TestTransform& transform,
152 TestTransform& result) const = 0;
153};
154
155class SkiaAdapterBase : public TransformAdapter {
156 public:
157 // DoNothing methods used to measure overhead for various operations
158 void DoNothing(TestTransform& ignored) const override {}
159
160 void InitPoint(TestPoint& point, float x, float y) const override {
161 point.sk_point.set(x, y);
162 }
163
164 void InitRectLTRB(TestRect& rect,
165 float left,
166 float top,
167 float right,
168 float bottom) const override {
169 rect.sk_rect.setLTRB(left, top, right, bottom);
170 }
171};
172
173class SkMatrixAdapter : public SkiaAdapterBase {
174 public:
175 SkMatrixAdapter() = default;
176 ~SkMatrixAdapter() = default;
177
178 void InitTransformIdentity(TestTransform& result) const override {
179 result.sk_matrix.setIdentity();
180 }
181
182 virtual void InitTransformColMatrix(TestTransform& result,
183 const float m[16]) const override {
184 result.sk_matrix = SkM44::ColMajor(m).asM33();
185 }
186
187 void Translate(TestTransform& result, float tx, float ty) const override {
188 result.sk_matrix.preTranslate(tx, ty);
189 }
190
191 void Scale(TestTransform& result, float sx, float sy) const override {
192 result.sk_matrix.preScale(sx, sy);
193 }
194
195 void RotateRadians(TestTransform& result, float radians) const override {
196 result.sk_matrix.preRotate(SkRadiansToDegrees(radians));
197 }
198
199 void Concat(const TestTransform& a,
200 const TestTransform& b,
201 TestTransform& result) const override {
202 result.sk_matrix = SkMatrix::Concat(a.sk_matrix, b.sk_matrix);
203 }
204
205 void TransformPoint(const TestTransform& transform,
206 const TestPoint& in,
207 TestPoint& out) const override {
208 out.sk_point = transform.sk_matrix.mapPoint(in.sk_point);
209 }
210
211 void TransformPoints(const TestTransform& transform,
212 const TestPoint in[],
213 TestPoint out[],
214 int n) const override {
215 static_assert(sizeof(TestPoint) == sizeof(SkPoint));
216 transform.sk_matrix.mapPoints(reinterpret_cast<SkPoint*>(out),
217 reinterpret_cast<const SkPoint*>(in), n);
218 }
219
220 void TransformRectFast(const TestTransform& transform,
221 const TestRect& in,
222 TestRect& out) const override {
223 out.sk_rect =
224 transform.sk_matrix.mapRect(in.sk_rect, SkApplyPerspectiveClip::kNo);
225 }
226
227 void TransformAndClipRect(const TestTransform& transform,
228 const TestRect& in,
229 TestRect& out) const override {
230 out.sk_rect =
231 transform.sk_matrix.mapRect(in.sk_rect, SkApplyPerspectiveClip::kYes);
232 }
233
234 int CountClippedCorners(const TestTransform& transform,
235 const TestRect& rect) const {
236 SkPoint3 homogenous[4];
237 SkPoint corners[4];
238 rect.sk_rect.toQuad(corners);
239 transform.sk_matrix.mapHomogeneousPoints(homogenous, corners, 4);
240 int count = 0;
241 for (SkPoint3 hpt : homogenous) {
242 if (hpt.fZ <= 0) {
243 count++;
244 }
245 }
246 return count;
247 }
248
249 void InvertUnchecked(const TestTransform& transform,
250 TestTransform& result) const override {
251 [[maybe_unused]]
252 bool ret = transform.sk_matrix.invert(&result.sk_matrix);
253 }
254
255 bool InvertAndCheck(const TestTransform& transform,
256 TestTransform& result) const override {
257 return transform.sk_matrix.invert(&result.sk_matrix);
258 }
259};
260
261class SkM44Adapter : public SkiaAdapterBase {
262 public:
263 SkM44Adapter() = default;
264 ~SkM44Adapter() = default;
265
266 void InitTransformIdentity(TestTransform& storage) const override {
267 storage.sk_m44.setIdentity();
268 }
269
270 virtual void InitTransformColMatrix(TestTransform& result,
271 const float m[16]) const override {
272 result.sk_m44 = SkM44::ColMajor(m);
273 }
274
275 void Translate(TestTransform& storage, float tx, float ty) const override {
276 storage.sk_m44.preTranslate(tx, ty);
277 }
278
279 void Scale(TestTransform& storage, float sx, float sy) const override {
280 storage.sk_m44.preScale(sx, sy);
281 }
282
283 void RotateRadians(TestTransform& storage, float radians) const override {
284 storage.sk_m44.preConcat(SkM44::Rotate({0, 0, 1}, radians));
285 }
286
287 void Concat(const TestTransform& a,
288 const TestTransform& b,
289 TestTransform& result) const override {
290 result.sk_m44.setConcat(a.sk_m44, b.sk_m44);
291 }
292
293 void TransformPoint(const TestTransform& transform,
294 const TestPoint& in,
295 TestPoint& out) const override {
296 out.sk_point = transform.sk_m44.asM33().mapPoint(in.sk_point);
297 }
298
299 void TransformPoints(const TestTransform& transform,
300 const TestPoint in[],
301 TestPoint out[],
302 int n) const override {
303 static_assert(sizeof(TestPoint) == sizeof(SkPoint));
304 transform.sk_m44.asM33().mapPoints(reinterpret_cast<SkPoint*>(out),
305 reinterpret_cast<const SkPoint*>(in), n);
306 }
307
308 void TransformRectFast(const TestTransform& transform,
309 const TestRect& in,
310 TestRect& out) const override {
311 // clang-format off
312 out.sk_rect = transform.sk_m44
313 .asM33()
314 .mapRect(in.sk_rect, SkApplyPerspectiveClip::kNo);
315 // clang-format on
316 }
317
318 void TransformAndClipRect(const TestTransform& transform,
319 const TestRect& in,
320 TestRect& out) const override {
321 // clang-format off
322 out.sk_rect = transform.sk_m44
323 .asM33()
324 .mapRect(in.sk_rect, SkApplyPerspectiveClip::kYes);
325 // clang-format on
326 }
327
328 int CountClippedCorners(const TestTransform& transform,
329 const TestRect& rect) const {
330 SkPoint3 homogenous[4];
331 SkPoint corners[4];
332 rect.sk_rect.toQuad(corners);
333 transform.sk_m44.asM33().mapHomogeneousPoints(homogenous, corners, 4);
334 int count = 0;
335 for (SkPoint3 hpt : homogenous) {
336 if (hpt.fZ <= 0) {
337 count++;
338 }
339 }
340 return count;
341 }
342
343 void InvertUnchecked(const TestTransform& transform,
344 TestTransform& result) const override {
345 [[maybe_unused]]
346 bool ret = transform.sk_m44.invert(&result.sk_m44);
347 }
348
349 bool InvertAndCheck(const TestTransform& transform,
350 TestTransform& result) const override {
351 return transform.sk_m44.invert(&result.sk_m44);
352 }
353};
354
355class ImpellerMatrixAdapter : public TransformAdapter {
356 public:
357 ImpellerMatrixAdapter() = default;
358 ~ImpellerMatrixAdapter() = default;
359
360 void DoNothing(TestTransform& ignored) const override {}
361
362 void InitPoint(TestPoint& point, float x, float y) const override {
363 point.impeller_point = impeller::Point(x, y);
364 }
365
366 void InitRectLTRB(TestRect& rect,
367 float left,
368 float top,
369 float right,
370 float bottom) const override {
371 rect.impeller_rect = impeller::Rect::MakeLTRB(left, top, right, bottom);
372 }
373
374 void InitTransformIdentity(TestTransform& storage) const override {
375 storage.impeller_matrix = impeller::Matrix();
376 }
377
378 virtual void InitTransformColMatrix(TestTransform& result,
379 const float m[16]) const override {
380 // clang-format off
381 result.impeller_matrix = impeller::Matrix::MakeColumn(
382 m[ 0], m[ 1], m[ 2], m[ 3],
383 m[ 4], m[ 5], m[ 6], m[ 7],
384 m[ 8], m[ 9], m[10], m[11],
385 m[12], m[13], m[14], m[15]
386 );
387 // clang-format on
388 }
389
390 void Translate(TestTransform& storage, float tx, float ty) const override {
391 storage.impeller_matrix = storage.impeller_matrix.Translate({tx, ty});
392 }
393
394 void Scale(TestTransform& storage, float sx, float sy) const override {
395 storage.impeller_matrix = storage.impeller_matrix.Scale({sx, sy, 1.0f});
396 }
397
398 void RotateRadians(TestTransform& storage, float radians) const override {
399 storage.impeller_matrix =
400 storage.impeller_matrix *
402 }
403
404 void Concat(const TestTransform& a,
405 const TestTransform& b,
406 TestTransform& result) const override {
407 result.impeller_matrix = a.impeller_matrix * b.impeller_matrix;
408 }
409
410 void TransformPoint(const TestTransform& transform,
411 const TestPoint& in,
412 TestPoint& out) const override {
413 out.impeller_point = transform.impeller_matrix * in.impeller_point;
414 }
415
416 void TransformPoints(const TestTransform& transform,
417 const TestPoint in[],
418 TestPoint out[],
419 int n) const override {
420 for (int i = 0; i < n; i++) {
421 out[i].impeller_point = transform.impeller_matrix * in[i].impeller_point;
422 }
423 }
424
425 void TransformRectFast(const TestTransform& transform,
426 const TestRect& in,
427 TestRect& out) const override {
428 out.impeller_rect =
429 in.impeller_rect.TransformBounds(transform.impeller_matrix);
430 }
431
432 void TransformAndClipRect(const TestTransform& transform,
433 const TestRect& in,
434 TestRect& out) const override {
435 out.impeller_rect =
436 in.impeller_rect.TransformAndClipBounds(transform.impeller_matrix);
437 }
438
439 int CountClippedCorners(const TestTransform& transform,
440 const TestRect& rect) const {
441 auto corners = rect.impeller_rect.GetPoints();
442 int count = 0;
443 for (auto pt : corners) {
444 auto hpt = transform.impeller_matrix.TransformHomogenous(pt);
445 if (hpt.z <= 0) {
446 count++;
447 }
448 }
449 return count;
450 }
451
452 void InvertUnchecked(const TestTransform& transform,
453 TestTransform& result) const override {
454 result.impeller_matrix = transform.impeller_matrix.Invert();
455 }
456
457 bool InvertAndCheck(const TestTransform& transform,
458 TestTransform& result) const override {
459 result.impeller_matrix = transform.impeller_matrix.Invert();
460 return transform.impeller_matrix.GetDeterminant() != 0.0f;
461 }
462};
463
464// The rect argument is passed in by the TransformRect benchmarks so that
465// the setup function can make sure that it sets up a transform that
466// clips the desired number of corners during the bounds transform.
467using SetupFunction =
468 std::function<void(TransformAdapter*, TestTransform&, const TestRect*)>;
469
470static void SetupIdentity(const TransformAdapter* adapter,
471 TestTransform& transform,
472 const TestRect* rect) {
473 adapter->InitTransformIdentity(transform);
474}
475
476static void SetupTranslate(const TransformAdapter* adapter,
477 TestTransform& transform,
478 const TestRect* rect) {
479 adapter->InitTransformIdentity(transform);
480 adapter->Translate(transform, 10.2, 12.3);
481}
482
483static void SetupScale(const TransformAdapter* adapter,
484 TestTransform& transform,
485 const TestRect* rect) {
486 adapter->InitTransformIdentity(transform);
487 adapter->Scale(transform, 2.0, 2.0);
488}
489
490static void SetupScaleTranslate(const TransformAdapter* adapter,
491 TestTransform& transform,
492 const TestRect* rect) {
493 adapter->InitTransformIdentity(transform);
494 adapter->Scale(transform, 2.0, 2.0);
495 adapter->Translate(transform, 10.2, 12.3);
496}
497
498static void SetupRotate(const TransformAdapter* adapter,
499 TestTransform& transform,
500 const TestRect* rect) {
501 adapter->InitTransformIdentity(transform);
502 adapter->RotateRadians(transform, kPiOver4);
503}
504
505static void SetupPerspective(const TransformAdapter* adapter,
506 TestTransform& transform,
507 const TestRect* rect) {
508 adapter->InitTransformColMatrix(transform, kSimplePerspective);
509 if (rect) {
510 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 0);
511 }
512}
513
514static void SetupPerspectiveClipNone(const TransformAdapter* adapter,
515 TestTransform& transform,
516 const TestRect* rect) {
517 adapter->InitTransformColMatrix(transform, kSimplePerspective);
518 if (rect) {
519 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 0);
520 }
521}
522
523static void SetupPerspectiveClipOne(const TransformAdapter* adapter,
524 TestTransform& transform,
525 const TestRect* rect) {
526 adapter->InitTransformColMatrix(transform, kClipOneCornerPerspective);
527 if (rect) {
528 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 1);
529 }
530}
531
532static void SetupPerspectiveClipTwo(const TransformAdapter* adapter,
533 TestTransform& transform,
534 const TestRect* rect) {
535 adapter->InitTransformColMatrix(transform, kClipTwoCornersPerspective);
536 if (rect) {
537 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 2);
538 }
539}
540
541static void SetupPerspectiveClipThree(const TransformAdapter* adapter,
542 TestTransform& transform,
543 const TestRect* rect) {
544 adapter->InitTransformColMatrix(transform, kClipThreeCornersPerspective);
545 if (rect) {
546 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 3);
547 }
548}
549
550static void SetupPerspectiveClipFour(const TransformAdapter* adapter,
551 TestTransform& transform,
552 const TestRect* rect) {
553 adapter->InitTransformColMatrix(transform, kClipFourCornersPerspective);
554 if (rect) {
555 FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 4);
556 }
557}
558
559// We use a function to return the appropriate adapter so that all methods
560// used in benchmarking are "pure virtual" and cannot be optimized out
561// due to issues such as the arguments being constexpr and the result
562// simplified to a constant value.
563static std::unique_ptr<TransformAdapter> GetAdapter(AdapterType type) {
564 switch (type) {
565 case AdapterType::kSkMatrix:
566 return std::make_unique<SkMatrixAdapter>();
567 case AdapterType::kSkM44:
568 return std::make_unique<SkM44Adapter>();
569 case AdapterType::kImpellerMatrix:
570 return std::make_unique<ImpellerMatrixAdapter>();
571 }
573}
574
575} // namespace
576
577static void BM_AdapterDispatchOverhead(benchmark::State& state,
578 AdapterType type) {
579 auto adapter = GetAdapter(type);
580 TestTransform transform;
581 while (state.KeepRunning()) {
582 adapter->DoNothing(transform);
583 }
584}
585
586static void BM_SetIdentity(benchmark::State& state, AdapterType type) {
587 auto adapter = GetAdapter(type);
588 TestTransform transform;
589 while (state.KeepRunning()) {
590 adapter->InitTransformIdentity(transform);
591 }
592}
593
594static void BM_SetPerspective(benchmark::State& state, AdapterType type) {
595 auto adapter = GetAdapter(type);
596 TestTransform transform;
597 while (state.KeepRunning()) {
598 adapter->InitTransformColMatrix(transform, kSimplePerspective);
599 }
600}
601
602static void BM_Translate(benchmark::State& state,
603 AdapterType type,
604 float tx,
605 float ty) {
606 auto adapter = GetAdapter(type);
607 TestTransform transform;
608 adapter->InitTransformIdentity(transform);
609 bool flip = true;
610 while (state.KeepRunning()) {
611 if (flip) {
612 adapter->Translate(transform, tx, ty);
613 } else {
614 adapter->Translate(transform, -tx, -ty);
615 }
616 flip = !flip;
617 }
618}
619
620static void BM_Scale(benchmark::State& state, AdapterType type, float scale) {
621 auto adapter = GetAdapter(type);
622 TestTransform transform;
623 adapter->InitTransformIdentity(transform);
624 float inv_scale = 1.0f / scale;
625 bool flip = true;
626 while (state.KeepRunning()) {
627 if (flip) {
628 adapter->Scale(transform, scale, scale);
629 } else {
630 adapter->Scale(transform, inv_scale, inv_scale);
631 }
632 flip = !flip;
633 }
634}
635
636static void BM_Rotate(benchmark::State& state,
637 AdapterType type,
638 float radians) {
639 auto adapter = GetAdapter(type);
640 TestTransform transform;
641 adapter->InitTransformIdentity(transform);
642 while (state.KeepRunning()) {
643 adapter->RotateRadians(transform, radians);
644 }
645}
646
647static void BM_Concat(benchmark::State& state,
648 AdapterType type,
649 const SetupFunction& a_setup,
650 const SetupFunction& b_setup) {
651 auto adapter = GetAdapter(type);
652 TestTransform a, b, result;
653 a_setup(adapter.get(), a, nullptr);
654 b_setup(adapter.get(), b, nullptr);
655 while (state.KeepRunning()) {
656 adapter->Concat(a, b, result);
657 }
658}
659
660static void BM_TransformPoint(benchmark::State& state,
661 AdapterType type,
662 const SetupFunction& setup) {
663 auto adapter = GetAdapter(type);
664 TestTransform transform;
665 setup(adapter.get(), transform, nullptr);
666 TestPoint point, result;
667 adapter->InitPoint(point, 25.7, 32.4);
668 while (state.KeepRunning()) {
669 adapter->TransformPoint(transform, point, result);
670 }
671}
672
673static void BM_TransformPoints(benchmark::State& state,
674 AdapterType type,
675 const SetupFunction& setup) {
676 auto adapter = GetAdapter(type);
677 TestTransform transform;
678 setup(adapter.get(), transform, nullptr);
679 const int Xs = 10;
680 const int Ys = 10;
681 const int N = Xs * Ys;
682 TestPoint points[N];
683 for (int i = 0; i < Xs; i++) {
684 for (int j = 0; j < Ys; j++) {
685 int index = i * Xs + j;
686 FML_CHECK(index < N);
687 adapter->InitPoint(points[index], i * 23.3 + 17, j * 32.7 + 12);
688 }
689 }
690 TestPoint results[N];
691 int64_t item_count = 0;
692 while (state.KeepRunning()) {
693 adapter->TransformPoints(transform, points, results, N);
694 item_count += N;
695 }
696 state.SetItemsProcessed(item_count);
697}
698
699static void BM_TransformRectFast(benchmark::State& state,
700 AdapterType type,
701 const SetupFunction& setup) {
702 auto adapter = GetAdapter(type);
703 TestTransform transform;
704 TestRect rect, result;
705 adapter->InitRectLTRB(rect, 100, 100, 200, 200);
706 setup(adapter.get(), transform, &rect);
707 while (state.KeepRunning()) {
708 adapter->TransformRectFast(transform, rect, result);
709 }
710}
711
712static void BM_TransformAndClipRect(benchmark::State& state,
713 AdapterType type,
714 const SetupFunction& setup) {
715 auto adapter = GetAdapter(type);
716 TestTransform transform;
717 TestRect rect, result;
718 adapter->InitRectLTRB(rect, 100, 100, 200, 200);
719 setup(adapter.get(), transform, &rect);
720 while (state.KeepRunning()) {
721 adapter->TransformAndClipRect(transform, rect, result);
722 }
723}
724
725static void BM_InvertUnchecked(benchmark::State& state,
726 AdapterType type,
727 const SetupFunction& setup) {
728 auto adapter = GetAdapter(type);
729 TestTransform transform;
730 setup(adapter.get(), transform, nullptr);
731 TestTransform result;
732 while (state.KeepRunning()) {
733 adapter->InvertUnchecked(transform, result);
734 }
735}
736
737static void BM_InvertAndCheck(benchmark::State& state,
738 AdapterType type,
739 const SetupFunction& setup) {
740 auto adapter = GetAdapter(type);
741 TestTransform transform;
742 setup(adapter.get(), transform, nullptr);
743 TestTransform result;
744 while (state.KeepRunning()) {
745 adapter->InvertAndCheck(transform, result);
746 }
747}
748
749#define BENCHMARK_CAPTURE_TYPE(name, type) \
750 BENCHMARK_CAPTURE(name, type, AdapterType::k##type)
751
752#define BENCHMARK_CAPTURE_TYPE_ARGS(name, type, ...) \
753 BENCHMARK_CAPTURE(name, type, AdapterType::k##type, __VA_ARGS__)
754
755#define BENCHMARK_CAPTURE_ALL(name) \
756 BENCHMARK_CAPTURE_TYPE(name, SkMatrix); \
757 BENCHMARK_CAPTURE_TYPE(name, SkM44); \
758 BENCHMARK_CAPTURE_TYPE(name, ImpellerMatrix)
759
760#define BENCHMARK_CAPTURE_ALL_ARGS(name, ...) \
761 BENCHMARK_CAPTURE_TYPE_ARGS(name, SkMatrix, __VA_ARGS__); \
762 BENCHMARK_CAPTURE_TYPE_ARGS(name, SkM44, __VA_ARGS__); \
763 BENCHMARK_CAPTURE_TYPE_ARGS(name, ImpellerMatrix, __VA_ARGS__)
764
766
772
773// clang-format off
774#define BENCHMARK_CAPTURE_TYPE_SETUP(name, type, setup) \
775 BENCHMARK_CAPTURE(name, setup/type, AdapterType::k##type, Setup##setup)
776// clang-format on
777
778#define BENCHMARK_CAPTURE_ALL_SETUP(name, setup) \
779 BENCHMARK_CAPTURE_TYPE_SETUP(name, SkMatrix, setup); \
780 BENCHMARK_CAPTURE_TYPE_SETUP(name, SkM44, setup); \
781 BENCHMARK_CAPTURE_TYPE_SETUP(name, ImpellerMatrix, setup)
782
783// clang-format off
784#define BENCHMARK_CAPTURE_TYPE_SETUP2(name, type, setup1, setup2) \
785 BENCHMARK_CAPTURE(name, setup1*setup2/type, AdapterType::k##type, \
786 Setup##setup1, Setup##setup2)
787// clang-format on
788
789#define BENCHMARK_CAPTURE_ALL_SETUP2(name, setup1, setup2) \
790 BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkMatrix, setup1, setup2); \
791 BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkM44, setup1, setup2); \
792 BENCHMARK_CAPTURE_TYPE_SETUP2(name, ImpellerMatrix, setup1, setup2)
793
795BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, ScaleTranslate, ScaleTranslate);
797BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, ScaleTranslate, Perspective);
798BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, Perspective, ScaleTranslate);
799
806
813
820
827
838
849
850} // namespace flutter
int count
static const int points[]
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define SkRadiansToDegrees(radians)
Definition SkScalar.h:78
#define N
Definition beziers.cpp:19
Definition SkM44.h:150
static SkM44 ColMajor(const SkScalar c[16])
Definition SkM44.h:218
static SkM44 Rotate(SkV3 axis, SkScalar radians)
Definition SkM44.h:239
SkMatrix asM33() const
Definition SkM44.h:409
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition SkMatrix.h:1775
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:263
impeller::Point impeller_point
SkPoint sk_point
impeller::Matrix impeller_matrix
impeller::Rect impeller_rect
#define BENCHMARK_CAPTURE_ALL(name)
#define BENCHMARK_CAPTURE_ALL_SETUP(name, setup)
SkMatrix sk_matrix
#define BENCHMARK_CAPTURE_ALL_SETUP2(name, setup1, setup2)
SkRect sk_rect
#define BENCHMARK_CAPTURE_ALL_ARGS(name,...)
static bool b
struct MyStruct a[10]
AtkStateType state
GAsyncResult * result
#define FML_CHECK(condition)
Definition logging.h:85
#define FML_UNREACHABLE()
Definition logging.h:109
double y
double x
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
constexpr float kPiOver4
Definition math.h:33
static void BM_InvertUnchecked(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Concat(benchmark::State &state, AdapterType type, const SetupFunction &a_setup, const SetupFunction &b_setup)
static void BM_Rotate(benchmark::State &state, AdapterType type, float radians)
static void BM_TransformPoint(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_SetIdentity(benchmark::State &state, AdapterType type)
static void BM_SetPerspective(benchmark::State &state, AdapterType type)
static void BM_TransformRectFast(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_TransformPoints(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Scale(benchmark::State &state, AdapterType type, float scale)
static void BM_AdapterDispatchOverhead(benchmark::State &state, AdapterType type)
static void BM_InvertAndCheck(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_TransformAndClipRect(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Translate(benchmark::State &state, AdapterType type, float tx, float ty)
TPoint< Scalar > Point
Definition point.h:316
constexpr float kPiOver4
Definition constants.h:35
Definition setup.py:1
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
const Scalar scale
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition matrix.h:69
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:213
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129