-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Impeller] add mechanism for sharing bdf inputs. #55701
base: main
Are you sure you want to change the base?
Conversation
This code isn't ready for review yet, but adding @flar and @gaaclarke for high level input. This is the doc that I said I was going to write that I dragged my feet on... |
Also I notice in the video that there is a slight pixel shift when switching modes... |
Currently the transforms are incorrect if the same bdf id is used in different save layers. |
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.
Just reviewed the first half - the front end - on this pass.
One thought - why 64-bit signed integer for ID? Do we anticipate having this many BDFs? An optional value feels more appropriate at the Dart level than a magic value (or declaring that valid IDs must be positive). Making the parameter nullable at the Dart level seems simple. std::optional seems like overkill at the C++ level, but these don't get used all that much compared to all of the other work going on.
FML_UNREACHABLE(); | ||
} | ||
|
||
virtual void saveLayer(const DlRect& bounds, | ||
const SaveLayerOptions& options, | ||
uint32_t total_content_depth, | ||
DlBlendMode max_content_blend_mode, | ||
const DlImageFilter* backdrop = nullptr) { | ||
const DlImageFilter* backdrop = nullptr, |
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.
These are implementations, aren't they? Do they need the default values?
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 all of these virtual
tags?)
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.
These are not overrides so I think they need the default values. overrides of a virtual method don't need to re-specify them.
display_list/dl_builder.h
Outdated
@@ -51,7 +51,8 @@ class DisplayListBuilder final : public virtual DlCanvas, | |||
// |DlCanvas| | |||
void SaveLayer(const SkRect* bounds, | |||
const DlPaint* paint = nullptr, | |||
const DlImageFilter* backdrop = nullptr) override; | |||
const DlImageFilter* backdrop = nullptr, | |||
int64_t backdrop_id = -1) override; |
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.
Ditto - default values probably unnecessary.
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.
Actually, in this case there is a lot of code calling directly to a DlBuilder not through the DlCanvas interface so perhaps it needs them for ease of use. That need would disappear if we did something more like Flutter and Skia and have the Builder simply represent the recording process and provide an actual DlCanvas implementation via a getter rather than via direct implementation...?
display_list/dl_op_receiver.h
Outdated
@@ -143,15 +141,17 @@ class DlOpReceiver { | |||
// layer before further rendering happens. | |||
virtual void saveLayer(const DlRect& bounds, | |||
const SaveLayerOptions options, | |||
const DlImageFilter* backdrop = nullptr) = 0; | |||
const DlImageFilter* backdrop = nullptr, | |||
int64_t backdrop_id = -1) = 0; |
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 used to be the front end and back end for DLs. Now that it is just the backend I think all default values throughout this interface are obsolete. But, maybe there are a couple of unit tests that still call these directly? I'll watch for this as I de-skiafy...
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 DlOp records used during dispatch shouldn't need any defaults for the calls they make.)
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 filed flutter/flutter#156617 to remind me to clean this up.
display_list/skia/dl_sk_canvas.h
Outdated
@@ -32,7 +32,8 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { | |||
void Save() override; | |||
void SaveLayer(const SkRect* bounds, | |||
const DlPaint* paint = nullptr, | |||
const DlImageFilter* backdrop = nullptr) override; | |||
const DlImageFilter* backdrop = nullptr, | |||
int64_t backdrop_id = -1) override; |
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.
Do we use this directly (as in on an instance of this class as opposed to casting it to a DlCanvas where the defaults already exist)? Actually we might in the embedders or other platform code.
Re: the 64 bit integer. Dart ints are 64 bits and signed, so using a smaller int means we'd need to do a runtime check or throw an error (folks could reasonably use Dart max int has an input). We could remove the -1 and make it nullable instead, I need to look into how to pass that through dart::ffi. |
@@ -571,7 +572,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList( | |||
MetalHelper helper(Ceiling() - CurrentComplexityScore()); | |||
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { | |||
auto bounds = display_list->GetBounds(); | |||
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr); | |||
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); |
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.
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); | |
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, /*backdrop_id=*/-1); |
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
@@ -627,7 +628,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList( | |||
GLHelper helper(Ceiling() - CurrentComplexityScore()); | |||
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { | |||
auto bounds = display_list->GetBounds(); | |||
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr); | |||
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); |
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.
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, -1); | |
helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr, /*backdrop_id=*/-1); |
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
const DlImageFilter* backdrop = nullptr, | ||
std::optional<int64_t> backdrop_id = std::nullopt) = 0; |
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.
Instead of making this a separate argument, does it make more sense to have this be a property of the backdrop itself?
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 backdrop filter argument is a DlImageFilter, which is a mirror of the dart:ui ImageFilter object. It doesn't make sense for the backdrop id to be a property of the image filter as 1) a single filter object can be used in multiple places in the same scene and 2) can be used in contexts for which the backdropId propety doesn't make sense like image filters.
I think instead it would make more sense to refactor saveLayer to group both the backdrop image filter and the backdrop id into one BackdropData struct.
callback(), // | ||
SkIRect::MakeWH(render_target.GetRenderTargetSize().width, | ||
render_target.GetRenderTargetSize().height), // | ||
true // |
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.
true // | |
/*reset_host_buffer=*/true // |
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
@@ -97,7 +97,8 @@ static std::shared_ptr<Texture> FlipBackdrop( | |||
std::vector<LazyRenderingConfig>& render_passes, | |||
Point global_pass_position, | |||
EntityPassClipStack& clip_coverage_stack, | |||
ContentContext& renderer) { | |||
ContentContext& renderer, | |||
bool should_remove_texture = 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.
Add docstring.
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
impeller/display_list/canvas.cc
Outdated
bool will_cache_texture = false; | ||
BackdropData* data = nullptr; | ||
if (backdrop_id.has_value()) { | ||
const auto& backdrop_data = backdrop_keys_.find(backdrop_id.value()); |
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.
const auto& backdrop_data = backdrop_keys_.find(backdrop_id.value()); | |
const auto& backdrop_data_it = backdrop_keys_.find(backdrop_id.value()); |
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
impeller/display_list/canvas.cc
Outdated
} | ||
} | ||
|
||
if (!will_cache_texture || (will_cache_texture && !data->texture_slot)) { |
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.
Data is potentially nullptr here no? It's hard to read this code in github with comments.
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.
will_cache_texture is only true if backdrop_data wasn't nullptr, so we'd only take the first part of the OR branch here.
impeller/display_list/canvas.cc
Outdated
@@ -1084,6 +1116,42 @@ void Canvas::SaveLayer(const Paint& paint, | |||
transform_stack_.back().transform.HasTranslation() | |||
? Entity::RenderingMode::kSubpassPrependSnapshotTransform | |||
: Entity::RenderingMode::kSubpassAppendSnapshotTransform); | |||
|
|||
if (will_cache_texture) { |
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.
will_cache_texture
is so generic, but it specifically works with BackdropData
, can't it be named more appropriate for what it's used for, backdrop filters?
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.
will_cache_backdrop_texture?
impeller/display_list/canvas.cc
Outdated
backdrop_filter_contents->RenderToSnapshot(renderer_, {}); | ||
} | ||
|
||
auto maybe_snapshot = data->filtered_input_slot; |
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.
Remove auto please.
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
impeller/display_list/canvas.cc
Outdated
|
||
backdrop_entity.Render( | ||
renderer_, | ||
*render_passes_.back().inline_pass_context->GetRenderPass(0).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.
Holy moley, maybe we can break this chain up. It's quite a bit.
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.
Yeah its bad
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.
Added a helper
Since we didn't end up writing a design doc, I know we talked about it that one day over gvc but can you write down (or link to someplace where it is already written) why we needed to have users specify this explicitly and we couldn't come up with a heuristic to do this automatically? |
|
Did you consider making the Dart API look like this instead of specifying an integer? This captures a scope more succinctly and doesn't require managing ids. The downside is that it is impossible to mix and match the blur layer across the code (though that makes the code easier to follow). Under the covers you could keep the implementation the same if you wanted. Widget build(BuildContext context) {
return BackdropGroup(
children:[
BackdropFilter(...),
BackdropFilter(...),
]
);
} |
I discussed this a bit with @flar and we both like the idea of separating the Backdrop widget from a backdrop-reading widget. So something like:
But that is all Dart API that would be constructed at the framework layer. The implementation should look almost identical. |
Introduces a mechanism to allow backdrop filters to 1) share backdrop inputs and 2) fuse filter applications for faster blurs.
This is a proposed solution to flutter/flutter#131568
Implemented:
TBD:
Suggestions: applying a bdf should be a distinct operation from a save layer in the DL builder/dispatcher. The saveLayer implmenentation in the impeller dispatcher is super convoluted because it needs to handle both.
Video
Video starts with normal bdf then I hot reload to specify that the bdfs share inputs/filters. This is running on a pixel 8 pro
Change to the macrobenchmark app is just:
demo.mp4
Requires framework changes in https://github.com/jonahwilliams/flutter/pull/new/backdrop_id