Skip to content

Commit

Permalink
[Impeller] add benchmarks for the stroke geometry entity code (flutte…
Browse files Browse the repository at this point in the history
…r#50616)

Adds benchmarks (and backend support methods) for tracking the performance of the stroking code in the entity geometry package.
  • Loading branch information
flar committed Feb 13, 2024
1 parent abb51c4 commit 03889fe
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 0 deletions.
38 changes: 38 additions & 0 deletions impeller/entity/geometry/stroke_path_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,44 @@ CapProc<VertexWriter> GetCapProc(Cap stroke_cap) {
}
} // namespace

std::vector<SolidFillVertexShader::PerVertexData>
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<PositionWriter>(stroke_join);
auto cap_proc = GetCapProc<PositionWriter>(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<TextureFillVertexShader::PerVertexData>
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<PositionUVWriter>(stroke_join);
auto cap_proc = GetCapProc<PositionUVWriter>(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,
Expand Down
21 changes: 21 additions & 0 deletions impeller/entity/geometry/stroke_path_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,27 @@ class StrokePathGeometry final : public Geometry {
// |Geometry|
std::optional<Rect> GetCoverage(const Matrix& transform) const override;

// Private for benchmarking and debugging
static std::vector<SolidFillVertexShader::PerVertexData>
GenerateSolidStrokeVertices(const Path::Polyline& polyline,
Scalar stroke_width,
Scalar miter_limit,
Join stroke_join,
Cap stroke_cap,
Scalar scale);

static std::vector<TextureFillVertexShader::PerVertexData>
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_;
Expand Down
1 change: 1 addition & 0 deletions impeller/geometry/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ executable("geometry_benchmarks") {
sources = [ "geometry_benchmarks.cc" ]
deps = [
":geometry",
"../entity",
"../tessellator",
"//flutter/benchmarking",
]
Expand Down
100 changes: 100 additions & 0 deletions impeller/geometry/geometry_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<SolidFillVertexShader::PerVertexData>
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<TextureFillVertexShader::PerVertexData>
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.
Expand Down Expand Up @@ -64,6 +97,48 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) {
state.counters["TotalPointCount"] = point_count;
}

template <class... Args>
static void BM_StrokePolyline(benchmark::State& state, Args&&... args) {
auto args_tuple = std::make_tuple(std::move(args)...);
auto path = std::get<Path>(args_tuple);
auto cap = std::get<Cap>(args_tuple);
auto join = std::get<Join>(args_tuple);
auto generate_uv = std::get<bool>(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<std::vector<Point>>();
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 <class... Args>
static void BM_Convex(benchmark::State& state, Args&&... args) {
auto args_tuple = std::make_tuple(std::move(args)...);
Expand All @@ -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 {

Expand Down

0 comments on commit 03889fe

Please sign in to comment.