Retained rendering in Fuchsia PhysicalShapeLayer#6558
Retained rendering in Fuchsia PhysicalShapeLayer#6558liyuqian merged 3 commits intoflutter:masterfrom
Conversation
flow/layers/physical_shape_layer.cc
Outdated
| FML_DCHECK(needs_system_composite()); | ||
|
|
||
| if (entity_node_ != nullptr) { | ||
| if (entity_node_->session() && context.top_entity()) { |
There was a problem hiding this comment.
Nit: Just add an assertion for this condition and add the child node as normal.
|
Can you land this please? |
|
Oops, I was waiting for the framework change to land first. Mark this as wip. |
|
@chinmaygarde @mikejurka : Please have a look at this PR again as I now changed EntityNode to be stored as unique_ptr according to https://fuchsia-review.googlesource.com/c/garnet/+/224197 See also FL-53 about the performance difference with or without this retained rendering. Here's a short summary: Before retained rendering, After retained rendering, |
flow/layers/physical_shape_layer.h
Outdated
|
|
||
| #if defined(OS_FUCHSIA) | ||
| std::unique_ptr<scenic::EntityNode> entity_node_ptr_; | ||
| mutable bool fuchsia_painted_ = false; |
There was a problem hiding this comment.
I'm not sure I understand this variable, could you add a comment?
flow/layers/physical_shape_layer.cc
Outdated
| FML_DCHECK(needs_painting()); | ||
|
|
||
| #if defined(OS_FUCHSIA) | ||
| if (fuchsia_painted_) { |
There was a problem hiding this comment.
what is the difference between fuchsia_painted_ and needs_painting() ? When/why do their values diverge?
There was a problem hiding this comment.
needs_painting check whether the paint_bounds is empty and it applies to all Flutter platforms.
fuchsia_painted is for Fuchsia only because Fuchsia always allocates a buffer for a PhysicalShapeLayer. Even if the paint_bounds is not empty, we can still use this to optimize performance by only paint the same PhysicalShapeLayer once within Fuchsia.
flow/layers/physical_shape_layer.h
Outdated
| std::unique_ptr<scenic::EntityNode> entity_node_ptr_; | ||
|
|
||
| // Whether the Fuchsia scenic::EntityNode of this exact same layer has already | ||
| // been painted in previous frames. If so, we can skip the Paint phase and |
There was a problem hiding this comment.
has been painted in a previous frame. This means that the content below the EntityNode has already been rasterized.
"and let Scenic re-use the same Entity nodes."
eaf2663 to
dc90dc0
Compare
|
@chinmaygarde @mikejurka : please check the updated PR that (I think) correctly manages the scenic resources: (1) only SubmitSurface when the surface is no longer used in retained rendering; (2) let the SurfaceProducer own surfaces and entity nodes so they'll get destructed in the right thread. |
flow/layers/layer_tree.cc
Outdated
| frame.AddPaintedLayer(root_layer_.get()); | ||
| } | ||
| container.AddChild(transform.entity_node()); | ||
| frame.Finalize(); |
There was a problem hiding this comment.
Can this happen in the frame's destructor?
There was a problem hiding this comment.
I actually found a way to remove Finalize() and do everything in the destructor :)
mikejurka
left a comment
There was a problem hiding this comment.
Could we keep using unique_ptrs, but have them be moved onto a "used" list somehow?
Alternatively, could we use shared_ptrs and have the SurfaceProducer use custom deleters to take further action when something is no longer referenced?
flow/layers/physical_shape_layer.cc
Outdated
|
|
||
| UpdateSceneChildren(context); | ||
|
|
||
| context.SetRetainedSurface(key, frame.Finalize()); |
There was a problem hiding this comment.
Nevermind, I see why you had to create a Finalize()
There was a problem hiding this comment.
Nevermind, I found a way to remove Finalize()
flow/scene_update_context.cc
Outdated
| SceneUpdateContext::Frame::~Frame() { | ||
| context().CreateFrame(entity_node(), rrect_, color_, paint_bounds_, | ||
| std::move(paint_layers_)); | ||
| SceneUpdateContext::SurfaceProducerSurface* |
There was a problem hiding this comment.
Can we keep the destructor, and have it call Finalize if Finalize() was not already called?
Also, can we add a boolean to make sure we're finalized only once?
There was a problem hiding this comment.
I just removed Finalize() and restored the destructor.
flow/layers/physical_shape_layer.cc
Outdated
| // won't call PhysicalShapeLayer::Paint. | ||
| LayerRasterCacheKey key( | ||
| this, SkMatrix::MakeScale(context.ScaleX(), context.ScaleY())); | ||
| SceneUpdateContext::SurfaceProducerSurface* retained_surface = |
There was a problem hiding this comment.
Could we keep unique_ptrs to surfaces, and then just place them in a Used struct somewhere?
There was a problem hiding this comment.
Sure, I just removed all raw pointers and restore the unique_ptr everywhere.
flow/layers/physical_shape_layer.cc
Outdated
| return; | ||
| } | ||
|
|
||
| SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_); |
There was a problem hiding this comment.
Add a comment: "If we can't find an existing retained surface, create one.
| FML_DCHECK(needs_system_composite()); | ||
|
|
||
| // Retained rendering: speedup by reusing a retained entity node if possible. | ||
| // When an entity node is reused, no paint layer is added to the frame so we |
There was a problem hiding this comment.
"When a entity node is resued, no paint layer is added to the frame"
I guess I'm still confused as to how the Layers work here, but: Does this mean that the contents of it haven't changed?
There was a problem hiding this comment.
Right, all engine layers (flow::Layer descendents) are currently immutable once constructed from the SceneBuilder. Unfortunately, the fields of those layers don't seem to be immutable due to set field methods. But we only call those set field methods in SceneBuilder. I'll change those fields to "const" in the future and update the SceneBuilder accordingly to reduce the confusion.
flow/layers/layer_tree.cc
Outdated
| frame.AddPaintedLayer(root_layer_.get()); | ||
| } | ||
| container.AddChild(transform.entity_node()); | ||
| frame.Finalize(); |
liyuqian
left a comment
There was a problem hiding this comment.
Thanks @mikejurka for your helpful comments! Now I found a way to preserve all the std::unique_ptrs and ~Frame. I hope that this makes the change safer and easier to understand.
| FML_DCHECK(needs_system_composite()); | ||
|
|
||
| // Retained rendering: speedup by reusing a retained entity node if possible. | ||
| // When an entity node is reused, no paint layer is added to the frame so we |
There was a problem hiding this comment.
Right, all engine layers (flow::Layer descendents) are currently immutable once constructed from the SceneBuilder. Unfortunately, the fields of those layers don't seem to be immutable due to set field methods. But we only call those set field methods in SceneBuilder. I'll change those fields to "const" in the future and update the SceneBuilder accordingly to reduce the confusion.
flow/layers/layer_tree.cc
Outdated
| frame.AddPaintedLayer(root_layer_.get()); | ||
| } | ||
| container.AddChild(transform.entity_node()); | ||
| frame.Finalize(); |
There was a problem hiding this comment.
I actually found a way to remove Finalize() and do everything in the destructor :)
flow/layers/physical_shape_layer.cc
Outdated
| // won't call PhysicalShapeLayer::Paint. | ||
| LayerRasterCacheKey key( | ||
| this, SkMatrix::MakeScale(context.ScaleX(), context.ScaleY())); | ||
| SceneUpdateContext::SurfaceProducerSurface* retained_surface = |
There was a problem hiding this comment.
Sure, I just removed all raw pointers and restore the unique_ptr everywhere.
flow/layers/physical_shape_layer.cc
Outdated
| return; | ||
| } | ||
|
|
||
| SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_); |
flow/layers/physical_shape_layer.cc
Outdated
|
|
||
| UpdateSceneChildren(context); | ||
|
|
||
| context.SetRetainedSurface(key, frame.Finalize()); |
There was a problem hiding this comment.
Nevermind, I found a way to remove Finalize()
flow/scene_update_context.cc
Outdated
| SceneUpdateContext::Frame::~Frame() { | ||
| context().CreateFrame(entity_node(), rrect_, color_, paint_bounds_, | ||
| std::move(paint_layers_)); | ||
| SceneUpdateContext::SurfaceProducerSurface* |
There was a problem hiding this comment.
I just removed Finalize() and restored the destructor.
|
LGTM |
flutter/engine@85492c3...4812a2a git log 85492c3..4812a2a --no-merges --oneline 4812a2a DCHECK that clip layer's behavior isn't none (flutter/engine#7659) eaae8a6 Retained rendering in Fuchsia PhysicalShapeLayer (flutter/engine#6558) 1946082 Move Brightness definition to dart:ui (#27479) (flutter/engine#7678) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff ([email protected]), and stop the roller if necessary.
flutter/engine@85492c3...4812a2a git log 85492c3..4812a2a --no-merges --oneline 4812a2a DCHECK that clip layer&flutter#39;s behavior isn&flutter#39;t none (flutter/engine#7659) eaae8a6 Retained rendering in Fuchsia PhysicalShapeLayer (flutter/engine#6558) 1946082 Move Brightness definition to dart:ui (flutter#27479) (flutter/engine#7678) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff ([email protected]), and stop the roller if necessary.
For flutter/flutter#23535
When this lands/rolls into Fuchsia, a manual roll with https://fuchsia-review.googlesource.com/c/topaz/+/241557 is needed.