From cafa86dba48b7847c0b1d17dd621748c37b57834 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Tue, 13 Feb 2024 13:30:36 -0800 Subject: [PATCH] [Impeller] add benchmarks for the stroke geometry entity code --- .../entity/geometry/stroke_path_geometry.cc | 38 +++++++ .../entity/geometry/stroke_path_geometry.h | 21 ++++ impeller/geometry/BUILD.gn | 1 + impeller/geometry/geometry_benchmarks.cc | 100 ++++++++++++++++++ 4 files changed, 160 insertions(+) diff --git a/impeller/entity/geometry/stroke_path_geometry.cc b/impeller/entity/geometry/stroke_path_geometry.cc index 92197d91c6810..a079c9ba2d25c 100644 --- a/impeller/entity/geometry/stroke_path_geometry.cc +++ b/impeller/entity/geometry/stroke_path_geometry.cc @@ -491,6 +491,44 @@ CapProc GetCapProc(Cap stroke_cap) { } } // namespace +std::vector +StrokePathGeometry::GenerateSolidStrokeVertices(const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale) { + auto scaled_miter_limit = stroke_width * miter_limit * 0.5f; + auto join_proc = GetJoinProc(stroke_join); + auto cap_proc = GetCapProc(stroke_cap); + StrokeGenerator stroke_generator(polyline, stroke_width, scaled_miter_limit, + join_proc, cap_proc, scale); + PositionWriter vtx_builder; + stroke_generator.Generate(vtx_builder); + return vtx_builder.GetData(); +} + +std::vector +StrokePathGeometry::GenerateSolidStrokeVerticesUV( + const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale, + Point texture_origin, + Size texture_size, + const Matrix& effect_transform) { + auto scaled_miter_limit = stroke_width * miter_limit * 0.5f; + auto join_proc = GetJoinProc(stroke_join); + auto cap_proc = GetCapProc(stroke_cap); + StrokeGenerator stroke_generator(polyline, stroke_width, scaled_miter_limit, + join_proc, cap_proc, scale); + PositionUVWriter vtx_builder(texture_origin, texture_size, effect_transform); + stroke_generator.Generate(vtx_builder); + return vtx_builder.GetData(); +} + StrokePathGeometry::StrokePathGeometry(const Path& path, Scalar stroke_width, Scalar miter_limit, diff --git a/impeller/entity/geometry/stroke_path_geometry.h b/impeller/entity/geometry/stroke_path_geometry.h index 6260ca4fb9cec..15281cb0a6ad8 100644 --- a/impeller/entity/geometry/stroke_path_geometry.h +++ b/impeller/entity/geometry/stroke_path_geometry.h @@ -47,6 +47,27 @@ class StrokePathGeometry final : public Geometry { // |Geometry| std::optional GetCoverage(const Matrix& transform) const override; + // Private for benchmarking and debugging + static std::vector + GenerateSolidStrokeVertices(const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale); + + static std::vector + GenerateSolidStrokeVerticesUV(const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale, + Point texture_origin, + Size texture_size, + const Matrix& effect_transform); + friend class ImpellerBenchmarkAccessor; + bool SkipRendering() const; Path path_; diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn index 5129f34662e97..0db775b86090a 100644 --- a/impeller/geometry/BUILD.gn +++ b/impeller/geometry/BUILD.gn @@ -84,6 +84,7 @@ executable("geometry_benchmarks") { sources = [ "geometry_benchmarks.cc" ] deps = [ ":geometry", + "../entity", "../tessellator", "//flutter/benchmarking", ] diff --git a/impeller/geometry/geometry_benchmarks.cc b/impeller/geometry/geometry_benchmarks.cc index c4801e09fa630..1952c9f42aa03 100644 --- a/impeller/geometry/geometry_benchmarks.cc +++ b/impeller/geometry/geometry_benchmarks.cc @@ -4,12 +4,45 @@ #include "flutter/benchmarking/benchmarking.h" +#include "flutter/impeller/entity/solid_fill.vert.h" +#include "flutter/impeller/entity/texture_fill.vert.h" + +#include "impeller/entity/geometry/stroke_path_geometry.h" #include "impeller/geometry/path.h" #include "impeller/geometry/path_builder.h" #include "impeller/tessellator/tessellator.h" namespace impeller { +class ImpellerBenchmarkAccessor { + public: + static std::vector + GenerateSolidStrokeVertices(const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale) { + return StrokePathGeometry::GenerateSolidStrokeVertices( + polyline, stroke_width, miter_limit, stroke_join, stroke_cap, scale); + } + + static std::vector + GenerateSolidStrokeVerticesUV(const Path::Polyline& polyline, + Scalar stroke_width, + Scalar miter_limit, + Join stroke_join, + Cap stroke_cap, + Scalar scale, + Point texture_origin, + Size texture_size, + const Matrix& effect_transform) { + return StrokePathGeometry::GenerateSolidStrokeVerticesUV( + polyline, stroke_width, miter_limit, stroke_join, stroke_cap, scale, + texture_origin, texture_size, effect_transform); + } +}; + namespace { /// A path with many connected cubic components, including /// overlaps/self-intersections/multi-contour. @@ -64,6 +97,48 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) { state.counters["TotalPointCount"] = point_count; } +template +static void BM_StrokePolyline(benchmark::State& state, Args&&... args) { + auto args_tuple = std::make_tuple(std::move(args)...); + auto path = std::get(args_tuple); + auto cap = std::get(args_tuple); + auto join = std::get(args_tuple); + auto generate_uv = std::get(args_tuple); + + const Scalar stroke_width = 5.0f; + const Scalar miter_limit = 10.0f; + const Scalar scale = 1.0f; + const Point texture_origin = Point(0, 0); + const Size texture_size = Size(100, 100); + const Matrix effect_transform = Matrix::MakeScale({2.0f, 2.0f, 1.0f}); + + auto points = std::make_unique>(); + points->reserve(2048); + auto polyline = + path.CreatePolyline(1.0f, std::move(points), + [&points](Path::Polyline::PointBufferPtr reclaimed) { + points = std::move(reclaimed); + }); + + size_t point_count = 0u; + size_t single_point_count = 0u; + while (state.KeepRunning()) { + if (generate_uv) { + auto vertices = ImpellerBenchmarkAccessor::GenerateSolidStrokeVerticesUV( + polyline, stroke_width, miter_limit, join, cap, scale, // + texture_origin, texture_size, effect_transform); + single_point_count = vertices.size(); + } else { + auto vertices = ImpellerBenchmarkAccessor::GenerateSolidStrokeVertices( + polyline, stroke_width, miter_limit, join, cap, scale); + single_point_count = vertices.size(); + } + point_count += single_point_count; + } + state.counters["SinglePointCount"] = single_point_count; + state.counters["TotalPointCount"] = point_count; +} + template static void BM_Convex(benchmark::State& state, Args&&... args) { auto args_tuple = std::make_tuple(std::move(args)...); @@ -82,11 +157,36 @@ static void BM_Convex(benchmark::State& state, Args&&... args) { state.counters["TotalPointCount"] = point_count; } +#define MAKE_STROKE_BENCHMARK_CAPTURE(path, cap, join) \ + BENCHMARK_CAPTURE(BM_StrokePolyline, stroke_##path##_##cap##_##join, \ + Create##path(), Cap::k##cap, Join::k##join, false) + +#define MAKE_STROKE_BENCHMARK_CAPTURE_UV(path, cap, join) \ + BENCHMARK_CAPTURE(BM_StrokePolyline, stroke_##path##_##cap##_##join##_uv, \ + Create##path(), Cap::k##cap, Join::k##join, true) + +#define MAKE_STROKE_BENCHMARK_CAPTURE_CAPS_JOINS(path, uv) \ + MAKE_STROKE_BENCHMARK_CAPTURE##uv(path, Butt, Bevel); \ + MAKE_STROKE_BENCHMARK_CAPTURE##uv(path, Butt, Miter); \ + MAKE_STROKE_BENCHMARK_CAPTURE##uv(path, Butt, Round); \ + MAKE_STROKE_BENCHMARK_CAPTURE##uv(path, Square, Bevel); \ + MAKE_STROKE_BENCHMARK_CAPTURE##uv(path, Round, Bevel) + +#define MAKE_STROKE_BENCHMARK_CAPTURE_UVS(path) \ + MAKE_STROKE_BENCHMARK_CAPTURE_CAPS_JOINS(path, ); \ + MAKE_STROKE_BENCHMARK_CAPTURE_CAPS_JOINS(path, _UV) + BENCHMARK_CAPTURE(BM_Polyline, cubic_polyline, CreateCubic(), false); BENCHMARK_CAPTURE(BM_Polyline, cubic_polyline_tess, CreateCubic(), true); +MAKE_STROKE_BENCHMARK_CAPTURE_UVS(Cubic); + BENCHMARK_CAPTURE(BM_Polyline, quad_polyline, CreateQuadratic(), false); BENCHMARK_CAPTURE(BM_Polyline, quad_polyline_tess, CreateQuadratic(), true); +MAKE_STROKE_BENCHMARK_CAPTURE_UVS(Quadratic); + BENCHMARK_CAPTURE(BM_Convex, rrect_convex, CreateRRect(), true); +MAKE_STROKE_BENCHMARK_CAPTURE(RRect, Butt, Bevel); +MAKE_STROKE_BENCHMARK_CAPTURE_UV(RRect, Butt, Bevel); namespace {