-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] round up subpass coverage when it is close to (and smaller) than root pass size. #49925
Conversation
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. |
Golden file changes are available for triage from new commit, Click here to view. |
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 "@test-exemption-reviewer" in the #hackers channel in Chat (don't just cc them here, they won't see it! Use Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
Golden file changes are available for triage from new commit, Click here to view. |
Taking a look at this. |
impeller/entity/entity_pass.cc
Outdated
(0.1 * subpass_size.width) && | ||
root_pass_size.height - subpass_size.height <= | ||
(0.1 * subpass_size.height)) { | ||
subpass_size = root_pass_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs more changes to make it safe.
I think the clear color optimization will always work out to be safe even thought it uses the root pass size, since it should fill up to the next largest clip anyhow.
Something that's not safe is the SaveLayer bounds hint. We simply use the bounds hint to limit the subpass, relying on the root pass to clip content outside of the bounds. So when a bounds hint is supplied we need to insert a clip to keep the behavior consistent with Skia.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case I'm concerned about, the bounds hint is actually the same size as the root pass size. So it sounds like I can handle this by only rounding up if I don't round up past the bounds hint, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a golden case that creates a SaveLayer with the bounds limit supplied and tries to draw stuff outside all the edges of the subpass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry, it's 2024 and GitHub isn't ajax yet, so I didn't see your last message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bounds hint is in local space, but the output of GetSubpassCoverage
(used to determine the size of the texture) is in screen space. So I think you could safely check this for your case by subpass.bounds_limit_->TransformBounds(subpass.transform_).GetSize() >= subpass_size
. GetSubpassCoverage
does this to work out the screen space bounds for clamping the texture, so to avoid float issues I'd make sure both places use the exact same rectangle (by sharing the same code path or computed output).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or if you happen to know that the bounds hint will never be supplied for the zoom page transition layers, just check that it's nullopt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a bounds hint, its just the same as the root pass size. I'll need to check if its smaller than the root pass size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done...ish
|
||
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd(); | ||
++it) { | ||
EXPECT_EQ(it->texture->GetTextureDescriptor().size, ISize(95, 95)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, one if these is 100,100, need to make the expection more specific.
impeller/entity/entity_pass.cc
Outdated
// conditionally inserted clips/scissor instead. | ||
if (bounds_limit.has_value()) { | ||
auto user_bounds_size = | ||
bounds_limit->TransformBounds(subpass_transform).GetSize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind adding a method like std::optional<Rect> EntityPass::GetTransformedBoundsLimit()
? GetSubpassCoverage
can use it directly and we can pass in transformed_bounds_limit
for this static method instead of passing in bounds_limit
+ subpass_transform
. Just to make it easier to not screw this up later on during refactors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have recommended we just apply the transform immediately when the bounds limit is set, but unfortunately the transform might end up getting modified if this EntityPass
is appended to another EntityPass
via DrawPicture...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're need to remove drawPicture support soon, it doesn't actually work and was added for an aiks canvas API that didn't work out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…nd smaller) than root pass size. (flutter/engine#49925)
…142202) flutter/engine@4880592...499ed00 2024-01-25 skia-flutter-autoroll@skia.org Roll Skia from 3b7accdf8ed8 to 571873c31056 (1 revision) (flutter/engine#50026) 2024-01-25 jonahwilliams@google.com [Impeller] round up subpass coverage when it is close to (and smaller) than root pass size. (flutter/engine#49925) 2024-01-25 mzhou620@gmail.com Adding DDC module system targets to web SDK artifacts. (flutter/engine#47783) 2024-01-25 hasan@hasali.dev [Windows] Set cursor immediately when framework requests update (flutter/engine#49784) 2024-01-25 737941+loic-sharma@users.noreply.github.com [Windows] Introduce `egl::Surface` and `egl::WindowSurface` (flutter/engine#49983) 2024-01-25 skia-flutter-autoroll@skia.org Roll Skia from 588caf1ceddd to 3b7accdf8ed8 (1 revision) (flutter/engine#50025) 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 jacksongardner@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://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
… smaller) than root pass size." (#50041) Reverts #49925 This did not improve benchmarks: https://flutter-flutter-perf.skia.org/e/?queries=device_type%3DPixel_7_Pro%26sub_result%3D90th_percentile_frame_rasterizer_time_millis%26sub_result%3D99th_percentile_frame_rasterizer_time_millis%26sub_result%3Daverage_frame_rasterizer_time_millis%26sub_result%3Dworst_frame_rasterizer_time_millis%26test%3Dnew_gallery_impeller_old_zoom__transition_perf&selected=commit%3D38910%26name%3D%252Carch%253Dintel%252Cbranch%253Dmaster%252Cconfig%253Ddefault%252Cdevice_type%253DPixel_7_Pro%252Cdevice_version%253Dnone%252Chost_type%253Dlinux%252Csub_result%253D99th_percentile_frame_rasterizer_time_millis%252Ctest%253Dnew_gallery_impeller_old_zoom__transition_perf%252C From follow up investigation: some of the routes hit this optimization, while some did not as the the bounds size seems to depend on the exact contents.
Work towards flutter/flutter#136510
generally speaking, we try to size subpasses as small as we possibly can as an optimization for memory usage and fragment load. Though with specific blend modes and/or filters we are required us to flood to a larger size. However in some cases, this optimization is counter productive - as we can only recycle textures that are exactly the same size.
In scenario where a large subpass slightly changes sizes every frame (such as for the android zoom page transition), the tight sizing is maximally inefficient as we discard and recreate large textures each frame.
This PR adds a heuristic which (at least locally) improves this by rounding up subpass size that is within 10% of the root pass size.