The Future of Flutter: Impeller & Beyond
[!NOTE] Impeller is now the default rendering engine on iOS for Flutter 3.10+ and is available for preview on Android.
The Problem: Early-Onset Jank
For years, Flutter developers have battled a specific kind of performance issue known as "shader compilation jank." This occurred because the Skia graphics engine (which Flutter used previously) compiled shaders just-in-time (JIT) as they were needed. If an animation required a complex shader that hadn't been seen before, the frame would drop while the GPU driver compiled it.
This led to the dreaded first-run jank: animations would stutter the first time they played, but run smoothly afterwards.
Enter Impeller: A Radical Shift
Impeller is a complete rewrite of Flutter's rendering layer. Unlike Skia, Impeller leans heavily into Ahead-Of-Time (AOT) compilation for shaders. Instead of compiling shaders on the device during runtime, Impeller compiles all necessary shaders at build time.
Core Philosophy
- Predictable Performance: By moving expensive compilation to build time, runtime performance becomes consistent. No more surprise frame drops.
- Instrumentation: Impeller is built with modern graphics APIs (Metal and Vulkan) in mind, allowing for deep profiling and debugging.
- Portability: While currently focused on mobile, Impeller's architecture is designed to be platform-agnostic at its core.
Deep Dive: How It Works
Impeller replaces the Skia rendering backend with a custom-built renderer tailored specifically for Flutter's needs.
The Rendering Pipeline
When you run flutter build, the Impeller compiler (impellerc) processes your shaders:
# Conceptual build process
flutter build ios --release --enable-impeller
# -> Compiles Dart code to AOT machine code
# -> Compiles Shaders (.frag, .vert) to SPIR-V -> Metal Shading Language (MSL)At runtime, the engine simply loads these precompiled binaries.
Architecture Overview
| Layer | Responsibility | Technology |
|---|---|---|
| Framework | Widgets, Elements, RenderObjects | Dart |
| Engine | Compositing, Rasterization | C++ |
| Impeller | GPU Command Encoding | Metal / Vulkan |
| GPU | Execution | Hardware |
Performance Benchmarks
In early tests, Impeller has shown dramatic improvements in worst-case frame times.
99th Percentile Frame Times (iPhone 13)
- Skia: ~18ms (occasional dropped frames)
- Impeller: ~4ms (consistent 120Hz)
"The difference is night and day. Complex lottie animations that used to stutter on first load now play instantly." — Senior Flutter Engineer
Migrating to Impeller
iOS Implementation
Impeller is enabled by default on iOS in recent Flutter versions. To verify or force-enable it:
<!-- Info.plist -->
<key>FLTEnableImpeller</key>
<true/>To disable it (fallback to Skia):
flutter run --no-enable-impellerAndroid Preview
On Android, Impeller uses Vulkan. It is currently in preview but becoming stable rapidly. To try it out:
flutter run --enable-impellerOr add this to your AndroidManifest.xml:
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="true" />Creating Custom Shaders
With Impeller, writing custom shaders in GLSL is fully supported. Here is a simple example of a fragment shader that creates a gradient effect:
// shaders/gradient.frag
#version 460 core
precision mediump float;
#include <flutter/runtime_effect.glsl>
uniform vec2 uSize;
uniform vec4 uColorStart;
uniform vec4 uColorEnd;
out vec4 fragColor;
void main() {
vec2 uv = FlutterFragCoord().xy / uSize;
fragColor = mix(uColorStart, uColorEnd, uv.x);
}You can then load this in your Flutter code:
class GradientShader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ShaderBuilder(
assetKey: 'shaders/gradient.frag',
child: Container(width: 200, height: 200),
(context, shader, child) {
return CustomPaint(
painter: ShaderPainter(shader),
child: child,
);
},
);
}
}Known Limitations & Roadmap
While Impeller is the future, it is still maturing.
- Android Compatibility: Older Android devices without Vulkan support will fall back to OpenGL (and potentially Skia for now).
- Memory Usage: Impeller can sometimes use slightly more memory than Skia due to precompiled assets, though optimization is ongoing.
- Platform Support: Web and Desktop support for Impeller is in early R&D stages.
Conclusion
Impeller is not just an incremental update; it defines the next decade of Flutter development. By solving the jank problem at the root — the compilation model itself — Flutter is positioned to be the premier choice for high-fidelity, high-performance cross-platform applications.
If you haven't tested your app with Impeller yet, now is the time. The smoothness is real.