Skip to content

ImageFilterLayer for simple matrix transforms leads to unnecessary render target switches #97987

@ds84182

Description

@ds84182

Due to Skia's implementation of SkMatrixImageFilter, the filterQuality parameter on the Transform widget is actually very inefficient. This can be verified by taking a capture of a Flutter application with RenderDoc.

https://github.com/google/skia/blob/main/src/core/SkMatrixImageFilter.cpp#L65

Skia's implementation creates an offscreen surface to render the transformed image into. This can be simplified greatly, especially since the source image comes from the raster cache.

In the worst case scenario, Flutter rasterizer caches the child layer, then takes the rasterizer cached image and draws it onto a new SkSurface with the transform, and then draws it to the final canvas during compositing. In the best case scenario, the child layer is already cached.

This extra copy makes the transform extremely expensive, even for static content. ImageFilterLayer is supposed to be a way to efficiently transform and scale static content without tons of raster cache misses, but it unfortunately isn't worthwhile as it doesn't scale due to this issue. It also forcefully caches itself if the filter doesn't change, which is terrible for animations because the raster cache drops the child content if the animation is still for a certain number of frames.

When using a lot of layers, performance suffers compared to using a canvas with transforms & drawImage. The only reason why the canvas solution isn't viable is because Picture.toImage is async, which gives a frame of delay before the image can be used for drawing. The raster cache doesn't have this issue.

I would love to be able to tell TransformLayer to rasterize it's child with one matrix (to add a scale factor to the cache entry's resolution) and then draw the raster cached content with another matrix. This would also be very helpful for ScaleTransition, as you could avoid thrashing the raster cache when scaling something up or down.

cc @flar

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projectc: performanceRelates to speed or footprint issues (see "perf:" labels)engineflutter/engine related. See also e: labels.perf: speedPerformance issues related to (mostly rendering) speedteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions