-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Consider an application that uses ColorFiltered which a single image child.
ColorFiltered(
filter: ColorFilter.mode(....),
child: Image.asset(...)
)Based on the blend mode, we end up with following operations:
For pipeline blends:
- Convert child to a snapshot (free for some images).
- Pipeline blends: Draw texture into subpass, draw color into subpass
- Draw subpass texture into parent.
For advanced blends:
- Convert child to a snapshot (free for some images).
- Advanced Blends: Draw snapshot with special shader into 2nd subpass
- Composite 2nd subpass into 1st subpass.
- Composite 1st subpass into parent.
Compared to just drawing the image, this has roughly 2x the texture fetches for pipeline blends and 3x for advanced blends. Compared to Skia this performs quite poorly and on the next gen ui test app (which features multiple full screen images) the framerate is choppy especially on high frame rate devices.
Now, previously I added a special carveout for color filters applied directly to an image. These skip the at least one of the subpasses, but in general we can't rely on folks using this. Its not clear to developers why a color filter applied to an image is faster than nesting an image under a ColorFiltered - and generally our API encourages this sort of composition.
Image.asset(..., colorBlendMode: ..., color: ...);Some observations:
- For Advanced blends, we could reduce the subpass count by at least 1x. Rather than rendering into a 2nd subpass and then returning an Entity from a snapshot, we could create an entity directly.
- For Advanced blends, we could remove the requirement for subpasses by inlining directly into the parent. The advanced blend shaders can be used to render the input snapshot and foreground color.
- For certain pipeline blends, we could inline directly into the parent. Requires certain blend modes and non-opaque color.
- For all pipeline blends, we could create a generic blending shader and use that to inline into the parent, performance TBD.
In cases where we'd like to inline into the parent pass, its not clear how we can express this with the current Filter API. This may be a more general limitation.
In this particular case, the color filter is expressed via a save layer - so we have a chance to insert an entity pass delegate that handles the inlining.