-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Collapse DrawRects into clear colors optimization #43168
Conversation
8391154 to
1aaec8f
Compare
1aaec8f to
512be0e
Compare
1214c4b to
737ca28
Compare
737ca28 to
640423e
Compare
| } | ||
|
|
||
| void Canvas::DrawPaint(const Paint& paint) { | ||
| if (xformation_stack_.size() == 1 && // If we're recording the root pass, |
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.
@bdero note that I got rid of this criteria. I don't think think it's important that it's the root pass, just that the render target for the render pass is covered. Let me know if there is something I'm missing.
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.
Render() is not recursively called; it only runs for the root pass. So it looks like this PR is only overriding the root pass clear color.
This comment was marked as outdated.
This comment was marked as outdated.
|
This is broken, i'm going to drop it back into draft and look into the failures tomorrow. |
This comment was marked as outdated.
This comment was marked as outdated.
bdero
left a comment
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.
Okay, so I had a big thonk about this... It occurs to me that Aiks won't be able to pack the conditional_clears_ list properly in the future when we start reversing the draw order.
What if instead of relying on Aiks to append items to a list, we push this entire concern into the Entities layer by adding the necessary APIs to perform this conversion internally? I.e.:
- Add
virtual bool Geometry::CoversArea(const Entity& entity, Rect area) constfor determining if the given rect is completely covered by the geometry.- Default implementation just returns
false. - Add an override for
CoverGeometrywhich returnstrueto handle theDrawPaintcase that we're already handling. - Add an override for
RectGeometryto handle the new case we're trying to tackle.
- Default implementation just returns
- Add
virtual std::optional<Color> Contents::AsBackgroundColor(const Entity& entity, ISize target_size) const, which returns aColorif the Contents can safely be replaced with a background color.- Default implementation just returns
std::nullopt. - Add an override for
SolidColorContentsthat returns the color ifgeometry_.CoversArea(entity, Rect::MakeSize(Size(target_size)))returnstrue.
- Default implementation just returns
- Add
std::optional<Color> Entity::AsBackgroundColor(ISize target_size) constas a helper to callContents::AsBackgroundColor(common pattern). - Then, before the render target for a pass is formed in
EntityPass, preprocess the elements up until either a subpass is found orEntity::AsBackgroundColor()returnsstd::nullopt. Set the resulting clear color on the render target. - Pass a
start_elementindex toOnRender()to offset the start of the element iteration.
A design like this would allow us to:
- Make the optimization independent from the
Elementdraw order. - Avoid copying the entire
Elementlist. - Expand this optimization in the future by just adding more
Geometry::CoversArea()andContents::AsBackgroundColor()overrides.
impeller/entity/entity_pass.cc
Outdated
| for (const EntityPass::ConditionalClear& clear : conditional_clears) { | ||
| std::optional<Rect> coverage = clear.entity.GetCoverage(); | ||
| bool should_collapse = | ||
| coverage.has_value() && coverage.value().Contains(render_target_rect); |
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.
Checking if the coverage rect covers the whole pass isn't enough to determine that the transformed geometry covers all fragments in the subpass. Additional restrictions are needed. For example, this check would work if the Entity transform only translates and/or scales the space.
| } | ||
|
|
||
| void Canvas::DrawPaint(const Paint& paint) { | ||
| if (xformation_stack_.size() == 1 && // If we're recording the root pass, |
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.
Render() is not recursively called; it only runs for the root pass. So it looks like this PR is only overriding the root pass clear color.
|
@bdero I'm thinking about it. It may be cleaner in terms of bookkeeping but complicates the API.
This isn't copying the Element list, it's copying references to the elements. It isn't ideal but it isn't as bad as copying the elements. |
|
I think we're going to have to do like brandon suggested and avoid holding the conditional clears separately. There is order information getting lost by having that parallel data structure. |
a9f28ef to
eb0b4c4
Compare
eb0b4c4 to
54ea87b
Compare
|
Transitioning this back from a draft to allow golden image testing since the tests are passing. |
This comment was marked as outdated.
This comment was marked as outdated.
|
@bdero yay, goldens are passing. I'm just going to push one more cleanup then re-request a review. I made the changes you suggested about taking this to the Contents level. |
This comment was marked as outdated.
This comment was marked as outdated.
| } else { | ||
| is_collapsing_clear_colors = false; | ||
| } | ||
| } |
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.
This skip behavior LGTM and will be applied to every EntityPass, but right now the clear color is only being applied to the root EntityPass in this PR (which has it's render target created in Render()).
We also need to set the clear color when constructing subpasses, which happens in GetEntityForElement(). There, you could just use subpass->GetClearColor() to grab it and feed it to the RT creation routine.
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'll do this is a follow up PR since it isn't strictly necessary to get the optimization I want in Gallery. In the gallery the first operation is adjusting the clip actually, although I think it is a noop. It would be nice to get that to collapse too if it's the case.
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.
If you defer this fix to a future PR, I think we'll need to add a mechanism to ensure this skipping behavior only occurs on the root pass, lest some apps will render incorrectly due to the unhandled dropping of entities on subpasses.
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 thought this was just an optimization. This is surprising that it isn't covered in existing tests. How could i make sure to hit this in a test? Would savelayer with a drawrect be enough?
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 just have to be careful to avoid the opacity peephole subpass collapse optimization. Drawing a fullscreen rect in a SaveLayer, but giving that SaveLayer an interesting blend mode like Modulate should work.
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.
Okay done. I used multiply since it was easier to verify, let me know if you think that may be a problem in the future. I think that should be good.
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.
Multiply is even more "interesting" than Modulate, so we should be good. 😄
389e7cd to
5e0c7f8
Compare
bdero
left a comment
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!
|
Golden file changes are available for triage from new commit, Click here to view. |
…129750) flutter/engine@4e49b9d...d5c25ea 2023-06-29 [email protected] [Impeller] Add a missing method to the Context mock (flutter/engine#43326) 2023-06-29 [email protected] [Impeller] Collapse DrawRects into clear colors optimization (flutter/engine#43168) 2023-06-29 [email protected] [Impeller] Add trace events to Vulkan texture and buffer lifecycle events. (flutter/engine#43321) 2023-06-29 [email protected] Roll Dart SDK from 5a59cd06e49d to a7151d73b88d (2 revisions) (flutter/engine#43318) 2023-06-28 [email protected] [Impeller] Fix advanced CPU blend modes (flutter/engine#43294) 2023-06-28 [email protected] Roll Fuchsia Linux SDK from 10hNrVMjnCypybnz2... to fxCNy4QivAngZXkvM... (flutter/engine#43314) 2023-06-28 [email protected] Roll Skia from 0b4f472a8c44 to 26fa4b343fd3 (2 revisions) (flutter/engine#43306) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from 10hNrVMjnCyp to fxCNy4QivAng 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://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
…#43168) design doc: https://docs.google.com/document/d/1Lqf1BRn4uCcUfv9dZlDyAgdSMeQ3FTnPgPjKF9yQ3MI/edit fixes: flutter/flutter#129292 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
design doc: https://docs.google.com/document/d/1Lqf1BRn4uCcUfv9dZlDyAgdSMeQ3FTnPgPjKF9yQ3MI/edit
fixes: flutter/flutter#129292
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.