Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] store all path point data in single buffer. #47896

Merged
merged 11 commits into from
Nov 16, 2023

Conversation

jonahwilliams
Copy link
Member

@jonahwilliams jonahwilliams commented Nov 10, 2023

Path objects are expensive to allocate, create, move, et cetera because of the large number of internal heap allocations performed. This change combines the linear, quad, and cubic buffers into a single point buffer that stores all points/control points inline.

The existing component buffer stores the index to the first point in the buffer, and the type field determines how many points are read.

Benchmarked in https://flutter-engine-perf.skia.org/e/?queries=test%3DBM_Polyline_cubic_polyline%26test%3DBM_Polyline_quad_polyline&selected=commit%3D38035%26name%3D%252Cconfig%253Ddefault%252Ccpu_scaling_enabled%253Dfalse%252Cexecutable%253D_b_s_w_ir_cache_builder_src_out_host_release_geometry_benchmarks%252Clibrary_build_type%253Drelease%252Cmhz_per_cpu%253D2200%252Cnum_cpus%253D8%252Csub_result%253DTotalPointCount%252Ctest%253DBM_Polyline_quad_polyline%252Cunit%253Dns%252C

flutter/flutter#138004

@jonahwilliams jonahwilliams changed the title [Impeller] just crazy enough to work. [Impeller] store all path point data in single buffer. Nov 10, 2023
@jonahwilliams
Copy link
Member Author

We could still combine the contour data into the path data with a little more work. Some additional work would be to add a reasonable "reserve" functionality for use when converting from SkPath.

@jonahwilliams jonahwilliams marked this pull request as ready for review November 10, 2023 19:19
@jonahwilliams
Copy link
Member Author

Friendly ping @dnfield

@@ -57,6 +57,7 @@ Path ToPath(const SkPath& path, Point shift) {

PathBuilder builder;
PathData data;
builder.Reserve(path.countPoints() + 16, path.countVerbs() + 16);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since our storage more closely aligns with the SkPath, we can guestimate more easily...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we're assuming that stays true.

I'd probably leave a 1-line explaining how you came to these numbers for the next shmuck.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a line here

@@ -57,6 +57,7 @@ Path ToPath(const SkPath& path, Point shift) {

PathBuilder builder;
PathData data;
builder.Reserve(path.countPoints() + 16, path.countVerbs() + 16);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we're assuming that stays true.

I'd probably leave a 1-line explaining how you came to these numbers for the next shmuck.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's time to bite the bullet and create a new file (path_unittests.cc)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to path_unittests.cc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came up in another review I was on too. In impeller there is some non-standard organization for tests. It makes a big difference for reviewing if when a file is changed the associated test file is changed too. Thanks for cleaning this up.

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I think the union would clean things up a bit.

break;
}
currentIndex++;
for (auto i = 0u; i < points_.size(); i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI this is where having a linear algrebra library would be nice. This sort of operation would be 10x faster if it was vectorized.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really a bottleneck though!

@@ -246,11 +258,14 @@ Path::Polyline Path::CreatePolyline(
const auto& component = components_[component_i];
switch (component.type) {
case ComponentType::kLinear:
return &linears_[component.index];
return reinterpret_cast<const LinearPathComponent*>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you could use a union here instead of having these casts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A union would require us to align storage to the largest component size, effectively padding out linear components 4x. The cast approach means that we can store points inline/continuously, though we have to rely on the secondary vector of verbs to determine the correct offsets. This is approach is closer to what Skia uses and I think we should too (partially because it makes point/verb reserve work nicely), and partially because its closer to the format we need for compute anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, I think it would? Is that right or wrong. 😆

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, could be. I'm not familiar enough with the code to know if there are less items in the vector to account for the different type. If the counts are the same then you're right.

You could make your own cast with template specialization

case ComponentType::kLinear:
  return point_cast<ComponentType::kLinear>(&points_[component.index]);

That's a wee bit cleaner. I don't have another easy solution.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to punt on this for now.

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 16, 2023
@auto-submit auto-submit bot merged commit f7e5ae4 into flutter:main Nov 16, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 16, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 16, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Nov 16, 2023
…138568)

flutter/engine@22baa83...094a338

2023-11-16 [email protected] Roll Skia from 297049bbfc0d to 4c099aaa259f (5 revisions) (flutter/engine#48138)
2023-11-16 [email protected] Roll Dart SDK from b512191e9612 to 906f23c1cb20 (1 revision) (flutter/engine#48136)
2023-11-16 [email protected] Disable the `runIfNot` clauses in `.ci.yaml`, as they are unsafe. (flutter/engine#48132)
2023-11-16 [email protected] Fix race condition in Unobstructed Platform View Scenario tests (flutter/engine#48096)
2023-11-16 [email protected] [Impeller] store all path point data in single buffer. (flutter/engine#47896)
2023-11-16 [email protected] Roll Skia from b9ead4140f84 to 297049bbfc0d (2 revisions) (flutter/engine#48133)
2023-11-16 [email protected] [macOS] Replace pasteboard mock with fake (flutter/engine#48110)
2023-11-16 [email protected] [Impeller] Fix issue where the lock was not re-acquired when the wait exits on CV. (flutter/engine#48104)
2023-11-16 [email protected] [Impeller] Create a drawable backed TextureMTL. (flutter/engine#48049)
2023-11-16 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Make `flow/embedded_views.h` compatible with `.clang_tidy`." (flutter/engine#48130)
2023-11-16 [email protected] [macOS] Replace fixture subclasses with usings (flutter/engine#48111)
2023-11-16 [email protected] Make `flow/embedded_views.h` compatible with `.clang_tidy`. (flutter/engine#47994)
2023-11-16 [email protected] Make `flow/...` compatible with `.clang_tidy`. (flutter/engine#47995)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App e: impeller
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants