-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Change Renderer utility to pass RenderTarget to callback; render non-pipeline blend modes #32982
[Impeller] Change Renderer utility to pass RenderTarget to callback; render non-pipeline blend modes #32982
Conversation
ef06683
to
5b8156e
Compare
Alright, I think this PR is in a pretty good spot for review. Advanced blends require binding the "current" pass resolve texture and rendering the result to an intermediate texture. And so the active render pass (which attaches the backdrop texture in question for writing) needs to execute before the blend pass (which binds the backdrop texture for reading), and then subsequent writes to the texture need to happen in a new To make this possible, I changed the Rendering all elements of the There is a small fanout of other problems I've noticed along the way that can be best addressed in follow-up PRs. These are the ones relevant to advanced blends (and are visible in the test below):
Fancy new color wheel blend test for Aiks (compare with https://fiddle.skia.org/c/@BlendModes): Screen.Recording.2022-05-02.at.10.10.27.PM.mov |
Awesome. I'll take a stab at reviewing this today! |
698c878
to
424e1f2
Compare
Rebased this past the GLES 2 changes. I plan to address problems with the blend filter itself in a follow-up. |
if (@available(macOS 10.13, *)) { | ||
// When calling nextDrawable, wait for the texture to become available | ||
// indefinitely. | ||
data_->metal_layer.allowsNextDrawableTimeout = NO; |
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 two layer properties were needed to make the surface textures readily bindable. Both of them are enabled in the iOS Flutter embedder, which enables Skia to do the same thing. framebufferOnly
makes the surface textures readable. Without allowsNextDrawableTimeout
, multi-pass rendering seemed to result in the texture being presented before all of the passes finish executing.
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 do set framebufferOnly in the Skia renderer but allowsNextDrawableTimeout is definitely not being set. I think we should investigate the need for setting this.
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.
Removed this in favor of just rendering to a third texture in this situation.
This also makes collapsed passes create a new command buffer/ |
Can we schedule some time tomorrow to go over this PR, have a few thoughts to clarify. |
@@ -61,7 +61,8 @@ | |||
color0_resolve_tex_desc.format = color_format; | |||
color0_resolve_tex_desc.size = color0_tex_desc.size; | |||
color0_resolve_tex_desc.usage = | |||
static_cast<uint64_t>(TextureUsage::kRenderTarget); | |||
static_cast<uint64_t>(TextureUsage::kRenderTarget) | |
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.
Like the color_format
var above, I think we should read this from current_drawable.texture.usage
instead of making it match in two places. Then, a validation can be added here saying the texture could not be read from.
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 suppose I am not sure why the usage of the resolve texture matters. Shouldn't it be on the usage flags of the color0_tex_desc descriptor?
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.
Changed this to not read from the surface texture.
impeller/renderer/surface.h
Outdated
@@ -26,7 +26,7 @@ class Surface { | |||
|
|||
bool IsValid() const; | |||
|
|||
const RenderTarget& GetTargetRenderPassDescriptor() const; | |||
RenderTarget& GetTargetRenderPassDescriptor(); |
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 perplexing. How would mutating the render target of a surface 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.
Discussed offline -- this was my (overly) aggressive aversion to copying striking again. ;)
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/entity/entity_pass.cc
Outdated
// input ("source"), writing the result to an intermediate texture, and | ||
// finally copying the data from the intermediate texture back to the | ||
// render target texture. And so all of the commands that have written to | ||
// the render target texture so far need to execute before it's binded for |
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: Bound
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.
@chinmaygarde I rewrote this to render the root I'm probably overthinking it since this'll only happen once per frame (and only if advanced blends are used on the root pass specifically), so maybe just rolling with a raster pipeline for the final blit is fine for now. |
Do you really need glBlitFramebuffer if you can approximate its behavior with a draw call by sampling from the source? Speaking of glBlitFramebuffer, I don't think there is an equivalent way to do this in renderer framework. I think we should add this feature now (and implement it using a draw in ES2 perhaps). |
3276bfe
to
ac90180
Compare
Yeah, this is what I meant by using a raster pipeline. We don't need blits, but was hoping we'd support it at some point. I changed this implementation to render to a third texture when any advanced blends are used in the root EntityPass. This is good to review again! |
Fix validation failures Allow for multiple passes against the on screen target Add fancy color wheel blend test Tweak test Fix compare URL Improve comments
ac90180
to
367ba1e
Compare
…llback; render non-pipeline blend modes (flutter/engine#32982)
Attach blend filters on the fly to support rendering with "advanced" (non-pipeline) blend modes. Advanced blends manipulate color, and behave like
kSourceOver
alpha-wise. They require sampling the source/destination textures as inputs and rendering to an intermediate texture, whereas the "pipeline" blends are simple Porter-Duff alpha compositing operations that can be performed by configuring builtin pipeline blend options.