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

add non-rendering operation culling to DisplayListBuilder #41463

Merged
merged 8 commits into from
May 14, 2023

Conversation

flar
Copy link
Contributor

@flar flar commented Apr 24, 2023

This optimization avoids recording unnecessary render operations that will not affect the output and also eliminates the need for "draw detection" mechanisms like DlOpSpy and CanvasSpy by remembering if any non-transparent operations were included. The DlOpSpy unit tests were updated to check if the results from that object match the new DisplayList::affects_transparent_surface() method.

Fixes flutter/flutter#125338

In addition, this change will unblock some other Issues:

@flar flar requested review from cyanglaz and jonahwilliams April 24, 2023 23:10
Copy link
Member

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

This is probably related to or necessary for the changes I was thinking of, though from a different direction?

If I understand this PR, what you are doing is detecting operations that have no effect when they are added. However, with platform views what I was thinking of was more along the lines of adding operations that make previous operations irrelevant.

For example, I could draw a solid color rectangle, and then a drawPaint with src blend mode and fully transparent - I would want to no-op the entire display list. Today impeller gets these commands one at a time in the order they are added, so its extra hard to detect that there should be no rendering done.

@flar
Copy link
Contributor Author

flar commented Apr 24, 2023

This is probably related to or necessary for the changes I was thinking of, though from a different direction?

If I understand this PR, what you are doing is detecting operations that have no effect when they are added. However, with platform views what I was thinking of was more along the lines of adding operations that make previous operations irrelevant.

For example, I could draw a solid color rectangle, and then a drawPaint with src blend mode and fully transparent - I would want to no-op the entire display list. Today impeller gets these commands one at a time in the order they are added, so its extra hard to detect that there should be no rendering done.

Is there an issue filed for that? Certainly the issue flutter/flutter#125318 that I was targetting said nothing about HSR.

@jonahwilliams
Copy link
Member

Do you mean HSR as in hidden surface removal ? It doesn't have anything to do with that, just with the machinery by which the engine currently "splits up" a display list when there are platform views involved.

@jonahwilliams
Copy link
Member

The example I gave in that bug was adding a difference clip and the resulting display list will render nothing as there isn't anything inside the difference clip.

@flar
Copy link
Contributor Author

flar commented Apr 25, 2023

The example I gave in that bug was adding a difference clip and the resulting display list will render nothing as there isn't anything inside the difference clip.

That is an example that I understood from the issue that I linked to, but the description in your comment above talks about rendering operations that are covered by future operations which is an entirely different animal and which is essentially HSR on a per-operation basis.

If you are talking about clips and transparent rendering, this PR will eliminate many of those.

A difference clip might not be detected, though, as the clip is only tracked by bounds and so only specific types of clip operations are tracked. If a diff clip spans the horizontal or vertical extents of the current clip bounds, then it might reduce the tracked clip bounds, but more complicated diff clips are not going to be analyzed geometrically to see if they block out future rendering operations.

@jonahwilliams
Copy link
Member

I don't have an opinion on the implementation, but my feature request is for a display list (specifically one created in the presence of platform views) to be able to tell me whether or not it renders anything.

@flar
Copy link
Contributor Author

flar commented Apr 25, 2023

I don't have an opinion on the implementation, but my feature request is for a display list (specifically one created in the presence of platform views) to be able to tell me whether or not it renders anything.

That's a goal that can be approximated with increasing degrees of accuracy, but it can never be solved completely for many reasons. What kinds of operations do you want it to detect?

  • blending plus source colors produce no effect?
  • conservative estimates of op bounds do not intersect conservative estimates of clips?
    • how conservative an estimate?
    • under what transform? Remember that touching a pixel might touch different amounts of distance past the theoretical bounds of a given operation depending on the transform
  • analyzing the filters and how they interact with each other to produce pixels that might not have an impact?
  • analyzing custom color sources that are written as shaders?

This PR performs a number of operations with a fairly unobtrusive performance impact and with a moderate degree of accuracy to try to prevent forwarding operations which are provably invisible. It goes well beyond the scope of the existing mechanisms that had been used to track whether rendering is happening in various inter-embedding gaps.

@flar flar force-pushed the DL-builder-detect-nop branch from 89e4620 to c1cc59c Compare April 25, 2023 20:04
@flar
Copy link
Contributor Author

flar commented Apr 25, 2023

One issue that might arise is that CanvasSpy and DlOpSpy don't count an operation that is DrawColor(transparent, Src) which represents clearing the surface to transparent. When you are evaluating if creating a surface, rendering a DL to it, and then compositing that surface onto a scene, that operation shouldn't be "counted". But, when evaluating if a DL can modify a destination, it should be counted because there may have been pixels there that needed to be cleared away and the DL will do exactly that.

So, the new render culling created here can't distinguish that kind of operation. Perhaps we can count the number of non-clear ops and return that?

Copy link
Member

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

LGTM

@chinmaygarde
Copy link
Member

Can we land this? Seems good to go on all fronts.

@chinmaygarde
Copy link
Member

Update: @flar noticed a tiny regression in build times that he is still investigating.

@flar
Copy link
Contributor Author

flar commented May 12, 2023

I was seeing about a 5-10% performance degradation running A/B tests for the (old) gallery transition perf, but @jonahwilliams suggested it might be due to lack of LTO on my local builds. I rebuilt my engine with LTO (profile) and the performance difference is negligible:

══╡ ••• Formatted summary for "/Users/jimgraham/Development/flutter/dev/devicelab/ABresults1.json" ••• ╞══

                   Score                     Average A (noise) Average B (noise) Speed-up
average_frame_build_time_millis                   1.72 (0.77%)      1.73 (1.03%)  0.99x  
worst_frame_build_time_millis                    51.56 (4.25%)     50.20 (3.94%)  1.03x  
90th_percentile_frame_build_time_millis           2.26 (2.02%)      2.30 (1.87%)  0.98x  
99th_percentile_frame_build_time_millis          17.19 (2.22%)     17.82 (1.23%)  0.96x  
average_frame_rasterizer_time_millis              5.66 (0.85%)      5.57 (0.96%)  1.02x  
worst_frame_rasterizer_time_millis               43.50 (0.79%)     42.81 (4.41%)  1.02x  
90th_percentile_frame_rasterizer_time_millis      7.30 (0.58%)      7.32 (0.18%)  1.00x  
99th_percentile_frame_rasterizer_time_millis     10.49 (7.50%)     10.70 (5.46%)  0.98x  

@flar flar force-pushed the DL-builder-detect-nop branch from 74236d6 to 8ceae56 Compare May 12, 2023 03:25
@jonahwilliams
Copy link
Member

Thank you for looking into the performance more. Still LGTM!

@flar flar added the autosubmit Merge PR when tree becomes green via auto submit App label May 14, 2023
@auto-submit auto-submit bot merged commit fb703b1 into flutter:main May 14, 2023
XilaiZhang added a commit that referenced this pull request May 17, 2023
auto-submit bot pushed a commit that referenced this pull request May 17, 2023
…uilder" (#42097)

temporary revert of #41463

context: b/283038609
XilaiZhang added a commit to XilaiZhang/engine that referenced this pull request May 18, 2023
XilaiZhang added a commit that referenced this pull request May 18, 2023
…o DisplayListB… (#42122)

…uilder" (#42097)

temporary revert of #41463

context: b/283038609

this revert is cherry picked into release branch, since engine ->
framework autoroller is currently blocked.
CaseyHillers pushed a commit to CaseyHillers/flutter that referenced this pull request May 24, 2023
…lutter#126758)

flutter/engine@96bd553...fb703b1

2023-05-14 flar@google.com add non-rendering operation culling to DisplayListBuilder (flutter/engine#41463)
2023-05-14 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from wxolyLvEWZ9IMOCU_... to hXcPXU_V5nVeGkEbt... (flutter/engine#42020)

Also rolling transitive DEPS:
  fuchsia/sdk/core/mac-amd64 from wxolyLvEWZ9I to hXcPXU_V5nVe

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 aaclarke@google.com,rmistry@google.com,zra@google.com 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://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
flar added a commit to flar/engine that referenced this pull request May 25, 2023
auto-submit bot pushed a commit that referenced this pull request Jun 1, 2023
…41463) (#42330)

The original PR caused some golden test failures down the line, likely due to bad analysis of when the combined BlendMode and color would result in a NOP situation.

This PR adds tests that go through every BlandMode and pair it with a variety of colors and Color/ImageFilters to verify that the operations are only omitted when they actually produce no change in the output. It also checks the validity of the "modifies_transparent_black" property of DisplayLists which can be used in place of the current CanvasSpy/DlOpSpy classes.

The description from the [previous PR](#41463) updated with the new name of the DL property:

---------------------------------
This optimization avoids recording unnecessary render operations that will not affect the output and also eliminates the need for "draw detection" mechanisms like `DlOpSpy` and `CanvasSpy` by remembering if any non-transparent operations were included. The `DlOpSpy` unit tests were updated to check if the results from that object match the new `DisplayList::modifies_transparent_black()` method.

Fixes flutter/flutter#125338

In addition, this change will unblock some other Issues:

- flutter/flutter#125318
- flutter/flutter#125403
flar added a commit that referenced this pull request Jun 2, 2023
auto-submit bot pushed a commit that referenced this pull request Jun 2, 2023
…lder" (#41463)" (#42525)

Reverts #42330

Some golden failures down the line were discovered in internal testing. See b/285539451
flar added a commit to flar/engine that referenced this pull request Jun 5, 2023
auto-submit bot pushed a commit that referenced this pull request Jun 11, 2023
…41463) (#42584)

This reverts commit 2553def.

Fixes flutter/flutter#125338

This PR should fix the blendmode/color analysis that caused failures for #41463 as well as the bounds failures for inverted rectangles that caused failures for #42330 (incorporating the fix from #42556).

The description from the [previous PR](#41463) updated with the new name of the DL property:

---------------------------------
This optimization avoids recording unnecessary render operations that will not affect the output and also eliminates the need for "draw detection" mechanisms like `DlOpSpy` and `CanvasSpy` by remembering if any non-transparent operations were included. The `DlOpSpy` unit tests were updated to check if the results from that object match the new `DisplayList::modifies_transparent_black()` method.

Fixes flutter/flutter#125338

In addition, this change will unblock some other Issues:

- flutter/flutter#125318
- flutter/flutter#125403
bdero added a commit that referenced this pull request Jun 30, 2023
bdero added a commit that referenced this pull request Jun 30, 2023
…lder" (#41463)" (#43358)

Reverts #42584. (Thanks to @jonahwilliams for bisecting)

With this change, layers are getting clipped incorrectly when rendering
platform views in Wondrous.
kjlubick pushed a commit to kjlubick/engine that referenced this pull request Jul 14, 2023
…lder" (flutter#41463)" (flutter#43358)

Reverts flutter#42584. (Thanks to @jonahwilliams for bisecting)

With this change, layers are getting clipped incorrectly when rendering
platform views in Wondrous.
flar added a commit to flar/engine that referenced this pull request Jul 14, 2023
flar added a commit to flar/engine that referenced this pull request Jul 14, 2023
auto-submit bot pushed a commit that referenced this pull request Jul 14, 2023
…41463) (#43698)

Fixes flutter/flutter#129862

This reverts commit fc9fc93.

These changes were exposing an underlying bug in the DisplayListMatrixClipTracker that has now been fixed independently (#43664). There are no changes to the commit being relanded here, it has been tested on the Wondrous app which demonstrated the regression before the NOP culling feature was reverted and it now works fine due to the fix of the underlying cause.
zanderso added a commit that referenced this pull request Jul 15, 2023
auto-submit bot pushed a commit that referenced this pull request Jul 15, 2023
…lder" (#41463)" (#43721)

Reverts #43698

A framework tree test started failing on the engine roll with this PR: flutter/flutter#130643

The test failure is in https://ci.chromium.org/ui/p/flutter/builders/prod/Linux_android%20hybrid_android_views_integration_test/8517/overview

```
[2023-07-14 19:33:21.980926] [STDOUT] stdout: [   +6 ms] I/PlatformViewsController( 9988): Using hybrid composition for platform view: 5
[2023-07-14 19:33:22.767236] [STDOUT] stdout: [ +786 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: Flutter surface with hybrid composition Uses FlutterImageView when Android view is on the screen �[1m�[31m[E]�[0m�[0m
[2023-07-14 19:33:22.767765] [STDOUT] stdout: [        ]   Expected: '|-FlutterView\n'
[2023-07-14 19:33:22.767815] [STDOUT] stdout: [        ]               '  |-FlutterSurfaceView\n'
[2023-07-14 19:33:22.767924] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768084] [STDOUT] stdout: [        ]               '  |-ViewGroup\n'
[2023-07-14 19:33:22.768162] [STDOUT] stdout: [        ]               '    |-ViewGroup\n'
[2023-07-14 19:33:22.768800] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768835] [STDOUT] stdout: [        ]               ''
[2023-07-14 19:33:22.768853] [STDOUT] stdout: [        ]     Actual: '|-FlutterView\n'
[2023-07-14 19:33:22.768882] [STDOUT] stdout: [        ]               '  |-FlutterSurfaceView\n'
[2023-07-14 19:33:22.768900] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768917] [STDOUT] stdout: [        ]               '  |-ViewGroup\n'
[2023-07-14 19:33:22.768956] [STDOUT] stdout: [        ]               '    |-ViewGroup\n'
[2023-07-14 19:33:22.769119] [STDOUT] stdout: [        ]               ''
[2023-07-14 19:33:22.769156] [STDOUT] stdout: [        ]      Which: is different. Both strings start the same, but the actual value is missing the following trailing characters:   |-Flutte ...
[2023-07-14 19:33:22.779280] [STDOUT] stdout: [  +10 ms]   package:matcher/src/expect/expect.dart 149:31     fail
[2023-07-14 19:33:22.779326] [STDOUT] stdout: [        ]   package:matcher/src/expect/expect.dart 144:3      _expect
[2023-07-14 19:33:22.780315] [STDOUT] stdout: [        ]   package:matcher/src/expect/expect.dart 56:3       expect
[2023-07-14 19:33:22.780345] [STDOUT] stdout: [        ]   test_driver/main_test.dart 124:7                  main.<fn>.<fn>
[2023-07-14 19:33:22.780356] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780365] [STDOUT] stdout: [        ]   package:test_api/src/backend/declarer.dart 215:9  Declarer.test.<fn>.<fn>
[2023-07-14 19:33:22.780376] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780385] [STDOUT] stdout: [        ]   package:test_api/src/backend/declarer.dart 213:7  Declarer.test.<fn>
[2023-07-14 19:33:22.780395] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780405] [STDOUT] stdout: [        ]   package:test_api/src/backend/invoker.dart 258:9   Invoker._waitForOutstandingCallbacks.<fn>
[2023-07-14 19:33:22.780415] [STDOUT] stdout: [        ] 00:19 �[32m+4�[0m�[31m -1�[0m: Flutter surface with hybrid composition (tearDownAll)�[0m
[2023-07-14 19:33:22.907295] [STDOUT] stdout: [ +126 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: (tearDownAll)�[0m
[2023-07-14 19:33:22.947855] [STDOUT] stdout: [  +41 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: �[31mSome tests failed.�[0m
```

This change in that roll looks like it may be related.
flar added a commit to flar/engine that referenced this pull request Jul 19, 2023
auto-submit bot pushed a commit that referenced this pull request Jul 19, 2023
…41463) (#43831)

Fixes: flutter/flutter#129862

This reverts commit 886a14e.

The framework test that was blocking the previous reland has been [fixed](flutter/flutter#130751) to not rely on non-visible (cullable) operations.
harryterkelsen pushed a commit to harryterkelsen/engine that referenced this pull request Jul 20, 2023
…lutter#41463) (flutter#43698)

Fixes flutter/flutter#129862

This reverts commit fc9fc93.

These changes were exposing an underlying bug in the DisplayListMatrixClipTracker that has now been fixed independently (flutter#43664). There are no changes to the commit being relanded here, it has been tested on the Wondrous app which demonstrated the regression before the NOP culling feature was reverted and it now works fine due to the fix of the underlying cause.
harryterkelsen pushed a commit to harryterkelsen/engine that referenced this pull request Jul 20, 2023
…lder" (flutter#41463)" (flutter#43721)

Reverts flutter#43698

A framework tree test started failing on the engine roll with this PR: flutter/flutter#130643

The test failure is in https://ci.chromium.org/ui/p/flutter/builders/prod/Linux_android%20hybrid_android_views_integration_test/8517/overview

```
[2023-07-14 19:33:21.980926] [STDOUT] stdout: [   +6 ms] I/PlatformViewsController( 9988): Using hybrid composition for platform view: 5
[2023-07-14 19:33:22.767236] [STDOUT] stdout: [ +786 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: Flutter surface with hybrid composition Uses FlutterImageView when Android view is on the screen �[1m�[31m[E]�[0m�[0m
[2023-07-14 19:33:22.767765] [STDOUT] stdout: [        ]   Expected: '|-FlutterView\n'
[2023-07-14 19:33:22.767815] [STDOUT] stdout: [        ]               '  |-FlutterSurfaceView\n'
[2023-07-14 19:33:22.767924] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768084] [STDOUT] stdout: [        ]               '  |-ViewGroup\n'
[2023-07-14 19:33:22.768162] [STDOUT] stdout: [        ]               '    |-ViewGroup\n'
[2023-07-14 19:33:22.768800] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768835] [STDOUT] stdout: [        ]               ''
[2023-07-14 19:33:22.768853] [STDOUT] stdout: [        ]     Actual: '|-FlutterView\n'
[2023-07-14 19:33:22.768882] [STDOUT] stdout: [        ]               '  |-FlutterSurfaceView\n'
[2023-07-14 19:33:22.768900] [STDOUT] stdout: [        ]               '  |-FlutterImageView\n'
[2023-07-14 19:33:22.768917] [STDOUT] stdout: [        ]               '  |-ViewGroup\n'
[2023-07-14 19:33:22.768956] [STDOUT] stdout: [        ]               '    |-ViewGroup\n'
[2023-07-14 19:33:22.769119] [STDOUT] stdout: [        ]               ''
[2023-07-14 19:33:22.769156] [STDOUT] stdout: [        ]      Which: is different. Both strings start the same, but the actual value is missing the following trailing characters:   |-Flutte ...
[2023-07-14 19:33:22.779280] [STDOUT] stdout: [  +10 ms]   package:matcher/src/expect/expect.dart 149:31     fail
[2023-07-14 19:33:22.779326] [STDOUT] stdout: [        ]   package:matcher/src/expect/expect.dart 144:3      _expect
[2023-07-14 19:33:22.780315] [STDOUT] stdout: [        ]   package:matcher/src/expect/expect.dart 56:3       expect
[2023-07-14 19:33:22.780345] [STDOUT] stdout: [        ]   test_driver/main_test.dart 124:7                  main.<fn>.<fn>
[2023-07-14 19:33:22.780356] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780365] [STDOUT] stdout: [        ]   package:test_api/src/backend/declarer.dart 215:9  Declarer.test.<fn>.<fn>
[2023-07-14 19:33:22.780376] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780385] [STDOUT] stdout: [        ]   package:test_api/src/backend/declarer.dart 213:7  Declarer.test.<fn>
[2023-07-14 19:33:22.780395] [STDOUT] stdout: [        ]   ===== asynchronous gap ===========================
[2023-07-14 19:33:22.780405] [STDOUT] stdout: [        ]   package:test_api/src/backend/invoker.dart 258:9   Invoker._waitForOutstandingCallbacks.<fn>
[2023-07-14 19:33:22.780415] [STDOUT] stdout: [        ] 00:19 �[32m+4�[0m�[31m -1�[0m: Flutter surface with hybrid composition (tearDownAll)�[0m
[2023-07-14 19:33:22.907295] [STDOUT] stdout: [ +126 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: (tearDownAll)�[0m
[2023-07-14 19:33:22.947855] [STDOUT] stdout: [  +41 ms] 00:19 �[32m+4�[0m�[31m -1�[0m: �[31mSome tests failed.�[0m
```

This change in that roll looks like it may be related.
harryterkelsen pushed a commit to harryterkelsen/engine that referenced this pull request Jul 20, 2023
…lutter#41463) (flutter#43831)

Fixes: flutter/flutter#129862

This reverts commit 886a14e.

The framework test that was blocking the previous reland has been [fixed](flutter/flutter#130751) to not rely on non-visible (cullable) operations.
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DisplayList] Improve DisplayList detection of non-operations
3 participants