Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] add basic culling checks during text frame dispatcher. #55168

Merged
merged 12 commits into from
Sep 24, 2024

Conversation

jonahwilliams
Copy link
Member

@jonahwilliams jonahwilliams commented Sep 13, 2024

Fixes flutter/flutter#155133

Dl dispatching still relies on cull rects computed during that dispatch process. Make sure that the text frame dispatcher doesn't populate text frames that are way offscreen.

This culling is more conservative than the rendering dispatcher. We'd need to do some refactoring so the logic isn't repeated multiple times.

@jonahwilliams jonahwilliams marked this pull request as ready for review September 13, 2024 16:22
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

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

Just a quick look while I'm OOO, but I had a couple of thoughts to consider...

const ContentContext& renderer_;
Matrix matrix_;
std::vector<Matrix> stack_;
std::vector<Rect> cull_rect_state_;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need a stack. At least not yet. SaveLayer bounds culling already happened so using a stack so that you can incorporate that into the culling of DL dispatching isn't likely to benefit much.

DL already culled - by failing to record - anything that was distinctly outside of a clip set in the DL stream, including the bounds of SaveLayers. So trying to intersect the cull_rect as you read through the current one isn't likely to improve the culling much compared to just culling against the (inverse transformed) frame bounds. If you remove the code in SaveLayer does it change the results much for your test case? If not then you don't really need a stack here until we do a full clip-based culling and even that would be icing on the cake rather than a critical step in the process.

Copy link
Member Author

Choose a reason for hiding this comment

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

We do still need to account for image filters, which aren't captured in the transform state. The locally transformed device bounds may be too small in some cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure? I don't think regular display list culling takes those into account. It just forwards the inverse-mapped clip bounds to the new Dispatch call.

Keep in mind that the bounds recorded in the RTree include any expansion due the filters applied to them, even including every filter on every saveLayer that they are inside of. That kind of inverts the responsibility there, but I'd have to look at it more to be sure this is right. If it is wrong then maybe we're doing the rendering side of culling wrong as well...

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 sure the culling takes that into account, but this is more of a problem with the cull rect computation right? (assuming no other canvas ops) Suppose I have a NxM device rect and a saveLayer with a 2x scaling image filter on it. If I need to dispatch to a sub display list inside of that savelayer, It wouldn't be correct to use the NxM cull rect, I'd need a 2Nx2M cull rect.

For other transforms I can invert the transform matrix but we don't track the image filter transforms easily yet.

Copy link
Contributor

Choose a reason for hiding this comment

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

Within a display list that has already been taken care of by the way that the RTree rects are accumulated, but I think you are correct that it is as if there is an additional "transform" that goes on when you hit a saveLayer that has a filter. So, just as you have to take the original cull rect and un-transform it by the CTM, you also have to un-transform it by the actions of the SaveLayers for similar reasons.

So, yes, it is still an issue that this code punts on the filter un-transform of the savelayers as you mentioned in the code.

context->GetContentContext(), //
impeller::Matrix(), //
impeller::Rect::MakeSize(render_target_size) //
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern of "first dispatch to a TFD and then to a DlDispatcher" happens in a number of places. It feels like a convenience method might be nice.

Copy link
Member Author

Choose a reason for hiding this comment

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

In #55019 I refactored this dispatching into a reusable static method.

}

void TextFrameDispatcher::saveLayer(const DlRect& bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) {
save();

Copy link
Contributor

Choose a reason for hiding this comment

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

bounds here are in local coordinates, I think you need to transform them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, your cull rect state doesn't look balanced. You always pop it in restore, but you push_back here. If save() doesn't push_back then restore will unbalance it. If save() does do a stack dup, then this code will over balance it...

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding was that the cull rect always need to be in local (to the display list) coordinate space. So I need to transform the cull rect into local space and then intersect with the bounds.

if (paint_.image_filter) {
cull_rect_state_.push_back(bounds);
} else {
auto new_cull_rect = GetCurrentLocalCullingBounds().Intersection(bounds);
Copy link
Contributor

Choose a reason for hiding this comment

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

Reverse this - transform bounds - use raw device cull bounds

Copy link
Member Author

Choose a reason for hiding this comment

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

but bounds is in the local coordinate space, so I need the device cull rect transformed into local coordinates?

Copy link
Contributor

Choose a reason for hiding this comment

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

You need them both in the same coordinate space. The state rect is in device coordinates. You thus need to compute an answer in device coordinates. But, you transform the state rect into local coordinates to do the math and then push its result without transforming it back. Even if you transformed it back, it is less efficient then transforming the bounds to device coords and doing the math there - naturally ending up with an answer already in the desired answer's coordinate space.

}

void TextFrameDispatcher::saveLayer(const DlRect& bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) {
save();

// This dispatcher does not track enough state to accurately compute
// cull rects with image filters.
Copy link
Contributor

Choose a reason for hiding this comment

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

For this, and other reasons, I think saveLayer should be a NOP.

  • First, DL has already done culling against things that appeared within the DL stream when it did the recording. So, the bounds you see here don't necessarily add any new information. The DL dispatch method is already culling things against the cull bounds that were provided in the initial dispatch call. DlBuilder already culled things against the bounds of save layers and clips when it did the recording. So, how is this particular enhancement really adding any value - other than some rare interactions where something might intersect the bounds here and also intersect the cull rect, but somehow not intersect the intersection of the two? If we were testing full geometries then strange cases like that might fall through the holes and we might be able to catch them with some more diligence here, but we are just testing bounds of the geometries, making it less likely to catch a corner case.
  • You could more easily do this same kind of calculation in the clip*() methods which don't have the fuzzy issues of saveLayer. Why choose saveLayer to enforce its possibly-fuzzily-potentially clipping when we aren't instrumenting the actual clip calls?
  • Really the important thing to track is how the filter manipulates the transform, but we aren't doing that. If anything, we should be setting the cull rect state to MaxRect here (like we have done in the non-experimental AIKS canvas) if there is a filter present, but that is not what the code here is doing...

I'd rather see this method just do:

  if (filter) {
    cull_rect_state.back() = Maximum;
  }

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed this to set to max cull rect if an image filter is encountered.

@jonahwilliams
Copy link
Member Author

Okay, updated to use global coordinate space and to check for kMaxCullRect when dispatching.

Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

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

LGTM - suggestions...

stack_.emplace_back(matrix_);
if (push_cull_rect) {
cull_rect_state_.push_back(cull_rect_state_.back());
Copy link
Contributor

Choose a reason for hiding this comment

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

An easier way to do this would be to have Save() always push it, and then SL replaces the value on ToS (.back() = foo) when it updates it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done. Testing now

has_image_filter_ = false;

auto local_cull_bounds = GetCurrentLocalCullingBounds();
if (!local_cull_bounds.IsMaximum()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

if IsEmpty then skip it...?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 24, 2024
@auto-submit auto-submit bot merged commit 11d36ff into flutter:main Sep 24, 2024
30 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Sep 25, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Sep 25, 2024
…155648)

flutter/engine@559f2ff...746ce61

2024-09-25 [email protected] Roll Dart SDK from 7af8c4882e07 to eda9ae15367e (2 revisions) (flutter/engine#55417)
2024-09-25 [email protected] [Flutter GPU] Add CullMode. (flutter/engine#55409)
2024-09-25 [email protected] Roll Skia from 2e92f0b443f4 to 3541cdf2fae6 (1 revision) (flutter/engine#55412)
2024-09-24 [email protected] [Impeller] fix Impeller on windows. (flutter/engine#55323)
2024-09-24 [email protected] [Impeller] add basic culling checks during text frame dispatcher. (flutter/engine#55168)
2024-09-24 [email protected] Move each dart GN rule to a standalone file. (flutter/engine#55404)
2024-09-24 [email protected] Roll Skia from 118914b760cb to 2e92f0b443f4 (1 revision) (flutter/engine#55406)
2024-09-24 [email protected] [Impeller] Pack impeller:Path into 2 vecs instead of 3. (flutter/engine#55028)
2024-09-24 [email protected] Disallow time traveling frame times (flutter/engine#55310)
2024-09-24 [email protected] [Impeller] Delete command pools held by the CommandPoolRecyclerVK after decoding an image on the IO thread (flutter/engine#55398)
2024-09-24 [email protected] Roll Skia from cf28f9dd411d to 118914b760cb (1 revision) (flutter/engine#55405)
2024-09-24 [email protected] [Flutter GPU] Add pipeline stencil config. (flutter/engine#55272)
2024-09-24 [email protected] Roll Skia from 6e5ff9253147 to cf28f9dd411d (1 revision) (flutter/engine#55399)
2024-09-24 [email protected] [Impeller] delete expensive trace event. (flutter/engine#55400)

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
thejitenpatel pushed a commit to thejitenpatel/flutter that referenced this pull request Sep 26, 2024
…lutter#155648)

flutter/engine@559f2ff...746ce61

2024-09-25 [email protected] Roll Dart SDK from 7af8c4882e07 to eda9ae15367e (2 revisions) (flutter/engine#55417)
2024-09-25 [email protected] [Flutter GPU] Add CullMode. (flutter/engine#55409)
2024-09-25 [email protected] Roll Skia from 2e92f0b443f4 to 3541cdf2fae6 (1 revision) (flutter/engine#55412)
2024-09-24 [email protected] [Impeller] fix Impeller on windows. (flutter/engine#55323)
2024-09-24 [email protected] [Impeller] add basic culling checks during text frame dispatcher. (flutter/engine#55168)
2024-09-24 [email protected] Move each dart GN rule to a standalone file. (flutter/engine#55404)
2024-09-24 [email protected] Roll Skia from 118914b760cb to 2e92f0b443f4 (1 revision) (flutter/engine#55406)
2024-09-24 [email protected] [Impeller] Pack impeller:Path into 2 vecs instead of 3. (flutter/engine#55028)
2024-09-24 [email protected] Disallow time traveling frame times (flutter/engine#55310)
2024-09-24 [email protected] [Impeller] Delete command pools held by the CommandPoolRecyclerVK after decoding an image on the IO thread (flutter/engine#55398)
2024-09-24 [email protected] Roll Skia from cf28f9dd411d to 118914b760cb (1 revision) (flutter/engine#55405)
2024-09-24 [email protected] [Flutter GPU] Add pipeline stencil config. (flutter/engine#55272)
2024-09-24 [email protected] Roll Skia from 6e5ff9253147 to cf28f9dd411d (1 revision) (flutter/engine#55399)
2024-09-24 [email protected] [Impeller] delete expensive trace event. (flutter/engine#55400)

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
thejitenpatel pushed a commit to thejitenpatel/flutter that referenced this pull request Sep 26, 2024
…lutter#155648)

flutter/engine@559f2ff...746ce61

2024-09-25 [email protected] Roll Dart SDK from 7af8c4882e07 to eda9ae15367e (2 revisions) (flutter/engine#55417)
2024-09-25 [email protected] [Flutter GPU] Add CullMode. (flutter/engine#55409)
2024-09-25 [email protected] Roll Skia from 2e92f0b443f4 to 3541cdf2fae6 (1 revision) (flutter/engine#55412)
2024-09-24 [email protected] [Impeller] fix Impeller on windows. (flutter/engine#55323)
2024-09-24 [email protected] [Impeller] add basic culling checks during text frame dispatcher. (flutter/engine#55168)
2024-09-24 [email protected] Move each dart GN rule to a standalone file. (flutter/engine#55404)
2024-09-24 [email protected] Roll Skia from 118914b760cb to 2e92f0b443f4 (1 revision) (flutter/engine#55406)
2024-09-24 [email protected] [Impeller] Pack impeller:Path into 2 vecs instead of 3. (flutter/engine#55028)
2024-09-24 [email protected] Disallow time traveling frame times (flutter/engine#55310)
2024-09-24 [email protected] [Impeller] Delete command pools held by the CommandPoolRecyclerVK after decoding an image on the IO thread (flutter/engine#55398)
2024-09-24 [email protected] Roll Skia from cf28f9dd411d to 118914b760cb (1 revision) (flutter/engine#55405)
2024-09-24 [email protected] [Flutter GPU] Add pipeline stencil config. (flutter/engine#55272)
2024-09-24 [email protected] Roll Skia from 6e5ff9253147 to cf28f9dd411d (1 revision) (flutter/engine#55399)
2024-09-24 [email protected] [Impeller] delete expensive trace event. (flutter/engine#55400)

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
thejitenpatel pushed a commit to thejitenpatel/flutter that referenced this pull request Sep 27, 2024
…lutter#155648)

flutter/engine@559f2ff...746ce61

2024-09-25 [email protected] Roll Dart SDK from 7af8c4882e07 to eda9ae15367e (2 revisions) (flutter/engine#55417)
2024-09-25 [email protected] [Flutter GPU] Add CullMode. (flutter/engine#55409)
2024-09-25 [email protected] Roll Skia from 2e92f0b443f4 to 3541cdf2fae6 (1 revision) (flutter/engine#55412)
2024-09-24 [email protected] [Impeller] fix Impeller on windows. (flutter/engine#55323)
2024-09-24 [email protected] [Impeller] add basic culling checks during text frame dispatcher. (flutter/engine#55168)
2024-09-24 [email protected] Move each dart GN rule to a standalone file. (flutter/engine#55404)
2024-09-24 [email protected] Roll Skia from 118914b760cb to 2e92f0b443f4 (1 revision) (flutter/engine#55406)
2024-09-24 [email protected] [Impeller] Pack impeller:Path into 2 vecs instead of 3. (flutter/engine#55028)
2024-09-24 [email protected] Disallow time traveling frame times (flutter/engine#55310)
2024-09-24 [email protected] [Impeller] Delete command pools held by the CommandPoolRecyclerVK after decoding an image on the IO thread (flutter/engine#55398)
2024-09-24 [email protected] Roll Skia from cf28f9dd411d to 118914b760cb (1 revision) (flutter/engine#55405)
2024-09-24 [email protected] [Flutter GPU] Add pipeline stencil config. (flutter/engine#55272)
2024-09-24 [email protected] Roll Skia from 6e5ff9253147 to cf28f9dd411d (1 revision) (flutter/engine#55399)
2024-09-24 [email protected] [Impeller] delete expensive trace event. (flutter/engine#55400)

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
thejitenpatel pushed a commit to thejitenpatel/flutter that referenced this pull request Sep 27, 2024
…lutter#155648)

flutter/engine@559f2ff...746ce61

2024-09-25 [email protected] Roll Dart SDK from 7af8c4882e07 to eda9ae15367e (2 revisions) (flutter/engine#55417)
2024-09-25 [email protected] [Flutter GPU] Add CullMode. (flutter/engine#55409)
2024-09-25 [email protected] Roll Skia from 2e92f0b443f4 to 3541cdf2fae6 (1 revision) (flutter/engine#55412)
2024-09-24 [email protected] [Impeller] fix Impeller on windows. (flutter/engine#55323)
2024-09-24 [email protected] [Impeller] add basic culling checks during text frame dispatcher. (flutter/engine#55168)
2024-09-24 [email protected] Move each dart GN rule to a standalone file. (flutter/engine#55404)
2024-09-24 [email protected] Roll Skia from 118914b760cb to 2e92f0b443f4 (1 revision) (flutter/engine#55406)
2024-09-24 [email protected] [Impeller] Pack impeller:Path into 2 vecs instead of 3. (flutter/engine#55028)
2024-09-24 [email protected] Disallow time traveling frame times (flutter/engine#55310)
2024-09-24 [email protected] [Impeller] Delete command pools held by the CommandPoolRecyclerVK after decoding an image on the IO thread (flutter/engine#55398)
2024-09-24 [email protected] Roll Skia from cf28f9dd411d to 118914b760cb (1 revision) (flutter/engine#55405)
2024-09-24 [email protected] [Flutter GPU] Add pipeline stencil config. (flutter/engine#55272)
2024-09-24 [email protected] Roll Skia from 6e5ff9253147 to cf28f9dd411d (1 revision) (flutter/engine#55399)
2024-09-24 [email protected] [Impeller] delete expensive trace event. (flutter/engine#55400)

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 join this conversation on GitHub. Already have an account? Sign in to comment
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.

[Impeller] dl dispatch culling still depends on canvas computed cull rects.
2 participants