Mobile Development 15 min read

How Impeller Redefines Flutter Rendering to Eliminate Shader Jank

Impeller, Flutter’s new rendering backend, tackles shader compilation jank by offline compiling shaders into shader libraries, introducing a modular architecture with compiler, renderer, and entity components, supporting Metal on iOS/macOS, and promising predictable performance, portability, and concurrency while outlining current limitations and future roadmap.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
How Impeller Redefines Flutter Rendering to Eliminate Shader Jank

Background

Flutter has solved many jank issues, but shader compilation jank remains. Skia uses SkSL (a GLSL variant) which is compiled at runtime, causing hundreds of milliseconds of delay and dozens of dropped frames. The trace shows the jank originates from GrGLProgramBuilder::finalize .

SkSL Pre‑heat Mechanism

Since Flutter 1.20, the GL backend pre‑heats SkSL shaders by collecting used shaders into a JSON file and pre‑compiling them on first app launch, reducing compile time from ~90 ms to ~40 ms on Moto G4 and from ~300 ms to ~80 ms on iPhone 4s. Flutter 2.5 added iOS Metal shader pre‑compilation.

Common Questions

Why not pre‑compile all shaders? The GPU backend generates shaders dynamically based on drawing commands and device parameters, producing a combinatorial explosion that cannot be fully pre‑compiled.

Are captured SkSL shaders portable across devices? There is no guarantee, but tests show reasonable cross‑device compatibility.

Why not create a super‑shader compiled once? Such a shader would be huge, essentially re‑implementing Skia GPU, and would increase compile time, causing more jank.

Impeller Architecture

Impeller is a Flutter‑specific renderer in early prototype stage, currently only implementing a Metal backend for iOS and macOS. It relies on Flutter’s FML and display list, providing a display‑list dispatcher to replace Skia.

Impeller Core Goals

Predictable performance: offline compile all shaders and pre‑build pipeline state objects.

Detectability: track and tag all graphics resources (textures, buffers, pipeline states).

Portability: shaders written once can be converted to any backend.

Modern graphics API usage: leverage features of Metal and Vulkan without being tied to them.

Effective concurrency: dispatch frame work across multiple threads.

Impeller Software Architecture

Impeller consists of several modules: Compiler, Renderer, Entity, Aiks, and core libraries (Geometry, Base).

Compiler

The host‑side tool includes a shader compiler and reflector. It compiles GLSL 4.60 source to SPIR‑V, then to a backend‑specific high‑level language (e.g., Metal SL). The reflector generates C++ shader bindings for fast pipeline‑state creation at runtime.

Renderer

Creates buffers, generates pipeline state objects from shader bindings, sets render passes, manages uniform buffers, tessellation, and executes rendering tasks.

Entity

Builds a 2D renderer containing shaders, shader bindings, and pipeline state objects.

Aiks

Wraps Entity to provide a Skia‑like API for integration with Flutter’s flow subsystem.

Impeller Shader Offline Compilation

The compiler first builds the impellerc binary, then compiles all shader sources under //impeller/entity/shaders/ to SPIR‑V, then to the target backend language (e.g., Metal SL), finally producing a shader library and C++ binding sources that are linked into the Flutter engine.

uniform FrameInfo {</code><code>    mat4 mvp;</code><code>    vec4 color;</code><code>} frame_info;</code><code>in vec2 vertices;</code><code>out vec4 color;</code><code>void main() {</code><code>    gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0);</code><code>    color = frame_info.color;</code><code>}

The generated Metal shader and header files expose structs and binding slots that allow direct memory‑mapped uniform and vertex data.

Shader Bindings

Bindings contain all shader metadata (entry points, input/output structs, buffer slots). At runtime, they enable rapid creation of pipeline state objects without additional compilation.

Impeller Rendering Flow

Impeller implements IOSContextMetalImpeller, IOSSurfaceMetalImpeller, and GPUSurfaceMetalImpeller to connect with Flutter’s flow subsystem. During rasterization, DisplayListCanvasRecorder records drawing commands into a DisplayList containing 73 Ops. The DisplayListDispatcher converts Ops into EntityPass structures, grouping them into hierarchical EntityPass trees. Each Entity maps to a Content (11 types). During the command encoding phase, RenderPass walks the EntityPass tree, creates Command objects that bind pipeline states, vertex/fragment buffers, and finally encodes them into MTLRenderCommandEncoder for execution.

Vertex Generation Example

For a Rect, the pipeline converts it to a Path, tessellates it into vertices, stores them in a host buffer, and uploads them to a GPU buffer during command encoding.

Appendix: Impeller Class Diagram

(Class diagram omitted for brevity.)

Summary

Offline shader compilation to a library dramatically improves first‑frame performance and eliminates shader‑compile jank.

Only Metal backend is currently implemented, supporting iOS and macOS.

Supports 73 Ops and 11 Content types.

Codebase ~18,774 lines, still depends on several Skia data structures.

Early prototype: many features (stroke, color filter, image filter, path effect, etc.) are not yet supported.

Overall effort comparable to rewriting Skia’s GPU functionality.

Flutter’s commitment to solving jank by rebuilding its rendering backend demonstrates a strong drive toward higher performance, and Impeller is poised to elevate Flutter’s rendering capabilities.

FlutterImpellerShader
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.