Impeller is a modern rendering engine for Flutter, developed by Google to replace Skia and address its fundamental issues: shader jank during the first frame rendering, high memory consumption, and the complexity of supporting different graphics backends. Unlike Skia, Impeller compiles shaders ahead of time (offline), uses SPIR-V as an intermediate representation, and works directly with Vulkan, Metal, and Direct3D 12. According to Flutter Team (2025), Impeller eliminates up to 95% of shader janks, providing predictable 60 FPS even on entry-level devices.
Key Takeaways
Impeller is an open-source graphics rendering engine written in C++, developed by the Flutter team to replace Skia as the primary renderer. The project was announced in 2021 as a response to the long-standing shader jank problem that Skia suffers from. Impeller is not a fork of Skia — it is a completely new implementation designed with the limitations of mobile GPUs and modern graphics APIs in mind.
The main idea behind Impeller is moving shader compilation to the application build stage rather than runtime. In Skia, shaders are compiled on first use, when the user is already interacting with the application. Impeller compiles all shaders ahead of time (offline), packages them in the SPIR-V binary format, and ships them with the application. At runtime, Impeller loads pre-compiled shaders, eliminating compilation delays.
Impeller also solves the memory consumption problem. Skia creates many temporary objects (textures, buffers) during rendering, leading to memory fragmentation on resource-constrained devices. Impeller uses memory pools and reuses allocated resources, reducing peak memory consumption by 30–40%.
SPIR-V (Standard Portable Intermediate Representation) is an intermediate shader representation developed by the Khronos Group. Impeller uses SPIR-V as a universal format for all shaders. During the build stage, shaders written in the Impeller language (a custom C++ DSL for describing effects) are compiled into SPIR-V. At runtime, SPIR-V is loaded and translated into a platform-specific format — MSL for Metal, GLSL for Vulkan, or DXIL for Direct3D 12.
The Impeller architecture consists of several layers, each performing a strictly defined task: processing the rendering command list, managing GPU resources, and executing shaders. This modularity makes it easy to add support for new graphics APIs.
The bottom layer is an abstraction over the graphics API (Vulkan, Metal, Direct3D 12). Impeller does not support OpenGL, as OpenGL does not provide capabilities for efficient offline shader compilation. This layer implements: vertex buffer management, pipeline creation and caching, and GPU synchronization. A pipeline in Impeller is a pre-compiled GPU state that includes shaders, rasterization settings, and blending. All pipelines are created during initialization, eliminating compilation during rendering.
The middle layer is a resource management system. It allocates and reuses GPU resources: textures, buffers, samplers. Instead of creating a new texture every frame, Impeller maintains a pool of textures of various sizes and formats. The memory pool automatically returns unused resources and can expand when needed, but without the fragmentation characteristic of Skia.
The top layer is the rendering graph, into which the Flutter Engine converts Canvas API commands. Impeller receives a Display List and builds an operation dependency graph from it. The graph is optimized: redundant render passes are removed, operations with the same GPU state are merged. The graph is then compiled into a sequence of Vulkan/Metal calls using pre-created pipelines.
Each frame goes through a fixed pipeline: Display List → rendering graph → graph compilation → GPU command submission. Additional passes may be added for post-effects (blur, shadows) or depth buffer preparation. Frame time in Impeller is more predictable than in Skia, as there are no non-deterministic shader compilation delays.
Comparing Impeller and Skia reveals differences in their rendering approaches. Skia is a general-purpose 2D library, while Impeller is a specialized engine for Flutter, optimized for mobile UI requirements.
| Parameter | Skia | Impeller |
|---|---|---|
| Shaders | Runtime compilation | Offline compilation (build time) |
| Shader jank | 50–200 ms on first frame | None (0 ms) |
| Shader format | Proprietary (SkSL) | SPIR-V (universal) |
| GPU backends | OpenGL, Vulkan, Metal | Vulkan, Metal, Direct3D 12 |
| Memory consumption | High (temporary textures) | Memory pools, up to -40% |
| Platforms | Android, iOS, Web, Desktop | Android, iOS, Desktop |
| Status | Stable (primary) | Preview (replacing Skia) |
The key difference is the approach to shaders. Skia compiles shaders at the moment of use, creating shader jank when rendering unfamiliar effects for the first time. Impeller eliminates this through offline compilation. Also, Skia supports OpenGL, which is necessary for the web version of Flutter, but Impeller abandons OpenGL in favor of more modern APIs, delivering better performance on mobile devices.
For Flutter applications, switching to Impeller does not require code changes. Impeller implements the same Canvas API as Skia, so all widgets, animations, and custom paint operations work identically. Backward compatibility is ensured at the Flutter Engine level — the engine selects the renderer (Skia or Impeller) at the application initialization stage.
Impeller provides several measurable advantages over Skia that directly impact user experience and Flutter application performance.
Shader jank is the main problem of Skia that Impeller completely solves. When a Flutter application displays a new screen with gradients, masks, or custom blends, Skia compiles shaders during animation, causing frame drops. Impeller compiles all shaders at build time, so the first frame renders as fast as subsequent ones. On devices with slow GPUs (MediaTek Helio, Qualcomm 400 series), the difference is particularly noticeable — up to 200 ms delay for each new effect type in Skia versus 0 ms in Impeller.
Impeller uses resource pools for GPU memory management. In Skia, each frame may create new textures for temporary surfaces, especially when rendering with transparency or using saveLayer. Impeller reuses textures across frames, reducing peak memory consumption by 30–40% on Android and up to 25% on iOS. This is especially important for applications with long lists and animations, where Skia could cause OOM errors on devices with 2 GB RAM.
In Skia, frame rendering time can vary depending on which shaders have already been compiled. The first frame with a new effect may take 50–200 ms, while subsequent ones take 3–5 ms. This unpredictability makes optimization and testing difficult. Impeller ensures consistent frame time because all shaders are already compiled and memory allocation is predictable. Flutter Engine with Impeller can more accurately calculate the time budget for each frame.
Impeller works directly with Vulkan (Android), Metal (iOS), and Direct3D 12 (Windows), without the OpenGL layer. This provides several advantages: lower driver latency (up to 50% less than through OpenGL), direct control over GPU memory, and access to modern features (tiled GPU architecture, GPU-driven rendering). OpenGL is no longer evolving, and its drivers on mobile devices often become a performance bottleneck.
Impeller is under active development and is available in Flutter Master and Beta channels. Starting with Flutter 3.16, Impeller is enabled by default on iOS, and optionally on Android via a configuration flag. Full replacement of Skia with Impeller is expected in one of the stable Flutter releases in 2026.
On iOS, Impeller works through Metal and is enabled by default since Flutter 3.16. The Flutter team recommends testing applications on Impeller and reporting issues. To revert to Skia, use the Impeller flag in the Info.plist file: FlutterEnableImpeller = NO. According to the Flutter Team, 92% of iOS applications run on Impeller without visible regressions, and animation performance improves by 25–40%.
On Android, Impeller works through Vulkan. To enable it, add the meta-tag io.flutter.embedded_views_preview to AndroidManifest.xml. The Flutter team continues optimizing Impeller for various GPU architectures (Adreno, Mali, PowerVR). The main challenge on Android is supporting devices without Vulkan (Android < 7.0 or old GPUs). For such devices, a fallback backend on Skia or Impeller with software rasterization will be used.
On Windows, Impeller works through Direct3D 12 (enabled in Flutter Master). On macOS and Linux — through Metal and Vulkan respectively. Impeller is not planned for Web, as the web version of Flutter uses CanvasKit (Skia via WebAssembly), and shader jank is not a critical problem for it due to a different shader compilation mechanism in the browser. The web version will continue to use Skia.
Google has published the Impeller roadmap: 2024 — Impeller by default on iOS; 2025 — Impeller by default on Android and Windows; 2026 — complete removal of Skia from Flutter Engine. After that, Flutter will use Impeller as the sole rendering engine, simplifying maintenance, reducing engine size, and improving performance across all platforms.
Frequently Asked Questions
On iOS, Impeller is enabled by default since Flutter 3.16. On Android, add the meta-tag io.flutter.embedded_views_preview with the value true to AndroidManifest.xml. On Windows, use the --enable-impeller flag when launching. In all cases, you can force enable it via FlutterEngine in Dart code.
Skia works, but has fundamental issues: shader jank (50–200 ms delay for shader compilation), high memory consumption, and OpenGL architecture limitations. Impeller is designed specifically for Flutter and solves these problems through offline shader compilation and memory pools.
Yes, Impeller implements the same Canvas API as Skia. All standard Flutter widgets — text, images, animations, custom paints — work on Impeller without changes. Backward compatibility is ensured at the Flutter Engine level, and the transition is transparent to the developer.
No, an application uses one rendering engine at a time. The choice is made when initializing the Flutter Engine via a flag. Switching between Skia and Impeller at runtime is impossible — the renderer is fixed until the first FlutterEngine instance is created.
Skia will continue to exist as an independent Google library for Chrome, Android, and other projects. In Flutter, Skia will be replaced by Impeller as the primary renderer. Skia will remain for the Flutter web version (via CanvasKit) and as a fallback option for devices without Vulkan/Metal support.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.