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

Conversation

@flar
Copy link
Contributor

@flar flar commented Nov 5, 2020

Fixes flutter/flutter#69552 by moving layer culling to the Paint() phase.

Also, now all children are culled, not just Clip layers.

Also, preroll can be avoided on retained layers. (No longer seeing this as a goal or a possibility.)

The tests are all botched by this change as this is a WIP. I'm seeking feedback on the general approach before I modify the layer tests to match the new preroll/paint rules. (Tests now updated.)

The test case in the issue runs correctly with this change and it runs fine in DEBUG mode which means the FML_DCHECK(false) I inserted in the old Layer::needs_painting() method is not being triggered during a run of a simple app. (old method removed entirely in favor of new methods)

@flar flar added the Work in progress (WIP) Not ready (yet) for review! label Nov 5, 2020
@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@flar
Copy link
Contributor Author

flar commented Nov 5, 2020

@fredlee12345678 thoughts?

void set_paint_bounds(const SkRect& paint_bounds) {
paint_bounds_ = paint_bounds;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's take this opportunity to add some documentations to Layer::paint_bounds. Before retained layers are introduced, Layer::paint_bounds is simple as each layer only exists for one frame with a single context. After retained layers, we need to explicitly document that Layer::paint_bounds must be independent of its parent context as the layer subtree can be retained and used in another context.

As it's context-independent, I wonder if Preroll is the best place to compute paint_bounds since there's aPrerollContext, and one might be tempted to use it. Shall we compute the paint bounds during the layer construction phase? For example, during SceneBuilder phase, when all children layers are added, call a method such as Layer::finalize to notify that no more children are expected to be added, and the paint_bounds can now be computed in a context-independent way.

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've been discussing these issues over on the issue page linked above.

I think we are pretty much good to go on pre-computing the bounds at scene construction time, but there is still the issue of the shadow bounds depending on device pixel ratio which I think might be a bug. I briefly played with pre-computing the bounds as a variation of this PR, but decided we can do that in a separate operation - the main objective here is to get rid of the pre-mature culling while not breaking anything else.

I'll add some comments to paint_bounds().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated the comments in the recent commit.

@flar
Copy link
Contributor Author

flar commented Nov 10, 2020

(Please ignore my previous comment about performance - I was graphing the wrong A/B results.)

It looks like the statistics on the rasterizer times and the profile of the timings is nearly identical (see attached graph image).

Screen Shot 2020-11-09 at 6 11 54 PM

const float frame_device_pixel_ratio;

bool needs_painting(const SkRect& paint_bounds) {
return !internal_nodes_canvas->quickReject(paint_bounds);
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the difference between the paint_bounds argument, and the paint_bounds_ member variable? I thought they should agree with each other?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method was on PaintContext so it needed to have it passed in.

I've since moved the method back to Layer so it is now "needs_painting(PaintContext& context);"

This code is obsolete.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

New code that now has Layer::needs_painting(PaintContext& context) pushed.

The new code also has Layer::is_empty() because there were 2 or 3 places that wanted to ask if the layer (usually the root) needed to be painted but they hadn't constructed a full PaintContext yet. So, those places will now depend solely on whether the layer is empty.

@flar flar force-pushed the no-paint-bounds-culling-in-preroll branch from e029837 to e7f9ee7 Compare November 12, 2020 18:01
@flar flar changed the title WIP: prototype to fix the problem of clip layers preventing child caching Move layer culling against clips to the Paint() method to avoid interfering with child caching Nov 12, 2020
@flar flar removed the Work in progress (WIP) Not ready (yet) for review! label Nov 12, 2020
@flar
Copy link
Contributor Author

flar commented Nov 12, 2020

Here are the AB comparison graphs of rasterizer times for the gallery_transitions_perf benchmark running on a Moto G4:
gallery_transitions_ABresults_average_frame_rasterizer_time_millisgallery_transitions_ABresults_90th_percentile_frame_rasterizer_time_millis
gallery_transitions_ABresults_99th_percentile_frame_rasterizer_time_millisgallery_transitions_ABresults_worst_frame_rasterizer_time_millis

@flar flar changed the title Move layer culling against clips to the Paint() method to avoid interfering with child caching Move layer clip culling to Paint() method to fix child caching Nov 12, 2020
layer->Add(mock_layer);

preroll_context()->cull_rect = kEmptyRect; // Cull everything
preroll_context()->cull_rect = distant_bounds; // Cull everything
Copy link
Contributor

Choose a reason for hiding this comment

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

Is // Cull everything still accurate? Is seems that everything in this test still falls outside of the cull_rect, but it's not as obvious as an empty rect. I'm also curious what motivates the replacement of the empty rect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It culls "everything in this test". I'll update the comment. Or maybe split it into two tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed this to // Cull these children in latest push

// is initially handed to a layer's Paint() method. By the time the
// layer calls PaintChildren(), though, it may have modified the
// PaintContext so we can no longer double-check the culling.
// FML_DCHECK(needs_painting(context));
Copy link
Contributor

Choose a reason for hiding this comment

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

We prefer removing the code instead of just commenting it out. You can still leave the comment here with something like Don't FML_DCHECK(needs_painting(context)) here! needs_painting(context) is only valid ....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

new comment pushed

needs_system_composite_ = value;
}

// Returns the unclipped paint bounds in the layer's local coordinate
Copy link
Contributor

Choose a reason for hiding this comment

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

unclipped seems inaccurate. The paint bounds should consider all clips in the layer subtree, but ignore all clips or cull rects of its ancestors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

new comment pushed.


void TextureLayer::Paint(PaintContext& context) const {
TRACE_EVENT0("flutter", "TextureLayer::Paint");
// FML_DCHECK(needs_painting(context));
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove the line that's commented out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Read above for my history on this. Note that the line wasn't actually there before. I added it when I started, realized that the tests were broken and commented it out pending investigation. I've now figured out why it was causing problems and working on fixing it rather than removing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've now fixed the tests (new commits pending) and will restore this line.

Copy link
Contributor Author

@flar flar Nov 12, 2020

Choose a reason for hiding this comment

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

Fixes now committed (pushed).

@flar
Copy link
Contributor Author

flar commented Nov 12, 2020

I believe the current code should meet all review feedback so far.

@flar flar mentioned this pull request Nov 12, 2020
9 tasks
Copy link
Contributor

@liyuqian liyuqian left a comment

Choose a reason for hiding this comment

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

LGTM

@flar flar force-pushed the no-paint-bounds-culling-in-preroll branch from 9159986 to 4b6bee8 Compare November 13, 2020 22:22
@flar flar added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Nov 13, 2020
@fluttergithubbot fluttergithubbot merged commit ecfe5ae into flutter:master Nov 13, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 15, 2020
chaselatta pushed a commit to chaselatta/engine that referenced this pull request Nov 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ClipRect with RepaintBoundary makes child widget to disappear

5 participants