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

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented Nov 5, 2024

Heap allocation is extremely expensive on Android.

We can speed up the stroke tessellation by allocation a large arena and using that to write vertices. If the vertices would overflow, we switch to a dynamically allocated vector.

@jonahwilliams jonahwilliams marked this pull request as ready for review November 6, 2024 02:13

arc.ToLinearPathComponents(scale, [&vtx_builder, &vtx, forward_normal,
position](const Point& point) {
Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, arc));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

From profiling, calling ToLinearPathComponents with a closure triggers a heap allocation on Android.

Copy link
Member

Choose a reason for hiding this comment

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

Bummer, we could get away with it by eliminating all captures and passing in a pointer to something on the stack. This isn't a request to make that change, but I think it's better to keep the abstraction since it's used in multiple locations.

std::tuple<Foo, Bar, Baz> info = {foo, bar, baz};
arc.ToLinearPathComponents<decltype(info)>(
  scale,
  info, 
  [](const Point"& point, const decltype(info)& info) {
    auto vtx = info.position + point;
    //...
  });

vtx.position = position + (-point * direction).Reflect(middle_normal);
vtx_builder.AppendVertex(vtx.position);
});
CubicPathComponent arc(start_offset, start_handle, middle_handle, middle);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same here,

From profiling, calling ToLinearPathComponents with a closure triggers a heap allocation on Android.


namespace {

template <typename VertexWriter>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed template code as its unused, we only have a single implementation.

@flutter-dashboard

This comment was marked as outdated.

@jonahwilliams jonahwilliams changed the title [Impeller] generate vertices into point arena. [Impeller] generate stroke vertices into point arena. Nov 6, 2024
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, code looks good, I just have some nits on documentation and a suggestion on how to keep the abstraction we already had (up to you if you want to do that though).

Path path = builder.TakePath();
auto geom = Geometry::MakeStrokePath(path, /*stroke_width=*/10);

ContentContext content_context(GetContext(), nullptr);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ContentContext content_context(GetContext(), nullptr);
ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

content_context.GetContext()->GetResourceAllocator());

auto render_target =
allocator.CreateOffscreen(*content_context.GetContext(), {10, 10}, 1);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
allocator.CreateOffscreen(*content_context.GetContext(), {10, 10}, 1);
allocator.CreateOffscreen(*content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 2398 to 2403
EXPECT_NE(*(written_data + kPointArenaSize - 2), Point(0, 0));
EXPECT_NE(*(written_data + kPointArenaSize - 1), Point(0, 0));
EXPECT_NE(*(written_data + kPointArenaSize), Point(0, 0));
EXPECT_NE(*(written_data + kPointArenaSize + 1), Point(0, 0));
EXPECT_NE(*(written_data + kPointArenaSize + 2), Point(0, 0));
EXPECT_NE(*(written_data + kPointArenaSize + 3), Point(0, 0));
Copy link
Member

Choose a reason for hiding this comment

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

Can we switch these to EXPECT_EQ assertions? Not being Point(0,0) leaves a lot of possibilities.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this is stroke tessellation the generated points are floating point values like 43.22132 ...

I could do a CLOSE_TO or something like that though. As long as they are in the ballpark

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}
}

size_t GetUsedSize() const { return offset_; }
Copy link
Member

Choose a reason for hiding this comment

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

It's worth documenting what this is supposed to return in a docstring since it's up to the client of this class to do the correct math with this and the oversized buffer's size.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, we could probably change this to just return offset_ + oversized_buffer_.size() to avoid the weirdness.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need both numbers to split up the memcp correctly

class PositionWriter {
public:
explicit PositionWriter(std::vector<Point>& points)
: points_(points), oversized_(0) {}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
: points_(points), oversized_(0) {}
: points_(points), oversized_() {}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

class PositionWriter {
public:
explicit PositionWriter(std::vector<Point>& points)
: points_(points), oversized_(0) {}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
: points_(points), oversized_(0) {}
: points_(points), oversized_(0) {
FML_DCHECK(points.size() >= kPointArenaSize);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


arc.ToLinearPathComponents(scale, [&vtx_builder, &vtx, forward_normal,
position](const Point& point) {
Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, arc));
Copy link
Member

Choose a reason for hiding this comment

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

Bummer, we could get away with it by eliminating all captures and passing in a pointer to something on the stack. This isn't a request to make that change, but I think it's better to keep the abstraction since it's used in multiple locations.

std::tuple<Foo, Bar, Baz> info = {foo, bar, baz};
arc.ToLinearPathComponents<decltype(info)>(
  scale,
  info, 
  [](const Point"& point, const decltype(info)& info) {
    auto vtx = info.position + point;
    //...
  });

.transform = entity.GetShaderTransform(pass),
.mode = GeometryResult::Mode::kPreventOverdraw};
}
FML_LOG(ERROR) << "Oversized";
Copy link
Member

Choose a reason for hiding this comment

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

Stray log? It's worth keeping a comment here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

const std::vector<Point>& oversized_data =
position_writer.GetOveriszedBuffer();
BufferView buffer_view = host_buffer.Emplace(
nullptr,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
nullptr,
/*buffer=*/nullptr,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

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, thanks!

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 6, 2024
@auto-submit auto-submit bot merged commit 00c22da into flutter:main Nov 6, 2024
30 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 6, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Nov 6, 2024
…158295)

flutter/engine@58ac1da...b36ca33

2024-11-06 [email protected] [skwasm] Fix empty backdrop drawing. (flutter/engine#56385)
2024-11-06 [email protected] [Impeller] generate stroke vertices into point arena. (flutter/engine#56390)
2024-11-06 [email protected] [Impeller] Do not capture the temporary ImpellerMapping struct pointer when storing release callbacks in libImpeller (flutter/engine#56411)
2024-11-06 6844906[email protected] Roll ICU from 9408c6fd4a39 to 4239b1559d11 (2 revisions) (flutter/engine#56407)
2024-11-06 [email protected] iOS,macOS: Add Obj-C cflags to all Obj-C targets (flutter/engine#56386)
2024-11-06 [email protected] Roll Skia from afaed8923682 to cf33c4e96e81 (5 revisions) (flutter/engine#56408)
2024-11-06 [email protected] Manual roll Dart SDK from 1c1d0420539f to d456f613465a (6 revisions) (flutter/engine#56406)
2024-11-06 [email protected] [Impeller] Avoid errors due to triangle fans usage on Molten. (flutter/engine#56321)
2024-11-06 [email protected] Roll Skia from b4df8dda7ffc to afaed8923682 (14 revisions) (flutter/engine#56404)

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] 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
nick9822 pushed a commit to nick9822/flutter that referenced this pull request Dec 18, 2024
…#56390)

Heap allocation is extremely expensive on Android.

We can speed up the stroke tessellation by allocation a large arena and using that to write vertices. If the vertices would overflow, we switch to a dynamically allocated vector.
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

None yet

Development

Successfully merging this pull request may close these issues.

2 participants