-
Notifications
You must be signed in to change notification settings - Fork 17
Chainable texture filters #67
Conversation
|
This is ready for review |
chinmaygarde
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.
This is great. I left perhaps one too many nits but the mechanics look good.
entity/contents/filter_contents.h
Outdated
| /// | ||
| /// The number of required or optional textures depends on the | ||
| /// particular filter's implementation. | ||
| void SetInputTextures(InputTextures& input_textures); |
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 the pass by reference (because of the &) necessitates an unavoidable copy at the caller and you are now depending on the move ctor of the vector to not trash the container on the off chance the caller wants to reuse it. It doesn't but this pattern is somewhat dangerous nonetheless.
The unavoidable copy is because the caller can't move the vector in even if the wanted to because it has to be by reference. Ideally, you want to avoid vector copies both at the call-site and the implementation. The following signature is allows for that:
void SetInputTextures(InputTextures input_textures);
At the call-site, if the caller wants to move the container, they may do foo.SetInputTextures(std::move(texes)) and you are avoiding the copy in the implementation. OTOH, if the want to keep those textures around for further use, they may just not use the move and incur the copy themselves. They need the container, so they should have to copy it out.
I think in this case, the signature with the least bits and bobs in it is the most elegant.
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.
Whoops! Thanks for the great explanation. Done.
entity/contents/filter_contents.cc
Outdated
| return texture->GetSize(); | ||
| } | ||
| } | ||
| return {0, 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.
Nit: The default ctor zero initializes. So just {} ought to be fine. This is good too.
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.
entity/contents/filter_contents.cc
Outdated
| } | ||
|
|
||
| ISize FilterContents::GetOutputSize() const { | ||
| if (!input_textures_.empty()) { |
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.
Nit: A general note, prefer early returns over nesting. This is fine too for now but may get out of hand in other instances.
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.
Agreed, done.
entity/contents/filter_contents.cc
Outdated
|
|
||
| ISize FilterContents::GetOutputSize() const { | ||
| if (!input_textures_.empty()) { | ||
| if (std::holds_alternative<std::shared_ptr<FilterContents>>( |
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.
Nit: Prefer std::get_if over std::holds_alternative and get. One, its shorter. But, more importantly, you are performing the second get without the check and this may be brittle if we add more variants.
Something like:
if (auto a = std::get_if<FooA>(var)) {
return a->dosomething();
}
if (auto b = std::get_if<FooB>(var)) {
return a->dosomethingelse();
}
FML_UNREACHABLE();
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.
Nice, done.
entity/contents/filter_contents.cc
Outdated
| auto uniform_view = host_buffer.EmplaceUniform(frame_info); | ||
|
|
||
| for (const auto& texture : input_textures) { | ||
| Command cmd; |
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.
Drive by comment: Commands are copyable. So you can create commands that are similar except for some fields outside the for loop and update just the relevant bindings in the loop before adding the command to the pass (don't forget to remove the std::move though).
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.
Nice, moved most of this setup out.
entity/contents/filter_contents.h
Outdated
|
|
||
| FilterContents(); | ||
|
|
||
| ~FilterContents(); |
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.
Nit:: Missing 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.
Done.
Part of flutter/flutter#99521.
FilterContentsclass that take zero or more texture inputs and generates a result texture.impeller::Textureor anotherFilterContentswhich will get resolved at render time.FilterContentsis rendered with an entity, it draws the output texture to the parent pass viaTextureContentsand respects the entity's transform/stencil/path.BlendFilterContentsfilter for simple additive blending/merging textures together.Entity::BlendMode::kPlusblend mode.Right now the test just blends 3 fixtures together. Will make fancier tests once we have less trivial filters to work with.
Usage: