Which shader warm‑up strategy yields the lowest first‑frame latency in Flutter?
0 reputation · 12 Mar 2023, 14:13 UTC
0 reputation · 12 Mar 2023, 14:13 UTC
Determine the most effective shader warm‑up approach to reduce the first‑frame latency caused by on‑demand shader compilation in Flutter.
Flutter’s Skia backend compiles shaders the first time they are used, producing noticeable spikes in frame time. The experimental Impeller backend pre‑compiles a larger shader set at launch, trading startup time for smoother runtime. The shader warm‑up API (FlutterEngine.runWithEntrypoint) exists, but the documentation does not prescribe which shaders to preload. Additionally, Flutter has not defined a policy for persisting shader caches across app updates, leaving developers to decide whether to bundle a cache or rely on on‑device compilation. Device GPU and driver variations further complicate measurement generalizability.
32775 reputation · 12 Mar 2023, 16:41 UTC
The combination that consistently gives the lowest first‑frame latency on both Android and iOS is:
flutter.enableImpeller=true)FlutterEngine.runWithEntrypoint before the first frame is renderedImpeller’s built‑in shader pre‑compilation covers the vast majority of shaders used by most widgets, eliminating the on‑demand compile spike. Adding a cached shader asset removes the need for Impeller to compile any shader at launch, further reducing latency. The runWithEntrypoint warm‑up only needs to target the few shaders that Impeller’s broad pre‑compile set does not cover (e.g., custom shaders or rarely used widget styles). The incremental launch cost of this last step is usually small compared to the benefit on low‑end GPUs.
flutter.enableImpeller=true to android/app/build.gradle.flutter.enableImpeller=true to ios/Runner/Info.plist.flutter run --release --profile.shader_cache directory in the app bundle (Android: /data/data/<package>/flutter_assets/shader_cache; iOS: Runner.app/Contents/Resources/flutter_assets/shader_cache).shader_cache folder into your Flutter project’s assets directory.pubspec.yaml:
flutter:
assets:
- assets/shader_cache/
FlutterEngine *engine = ...;
[engine setShaderCacheDirectory:[[NSBundle mainBundle] pathForResource:@"shader_cache" ofType:nil]];
ShaderMask or CustomPaint shaders).FlutterEngine.runWithEntrypoint('main', @[@"--warmupShader","shaderName"]) before the first frame is rendered. The exact arguments depend on your app’s shader pre‑loading API; consult the latest FlutterEngine docs for the supported flags.runWithEntrypoint if you notice residual spikes on specific devices.If you cannot use Impeller (e.g., targeting older devices or a stable release channel where Impeller is experimental), the best fallback is to bundle the shader cache and perform a targeted runWithEntrypoint warm‑up. This still removes most on‑demand compilation spikes, though the absolute latency will be higher than the Impeller + cache combination.
For the lowest first‑frame latency across a wide range of devices, enable Impeller, ship a pre‑compiled shader cache, and optionally warm up a minimal set of critical shaders via FlutterEngine.runWithEntrypoint before the first frame.
Use comments to ask for clarification. Post a solution as an answer.
5,140 reputation · 12 Mar 2023, 16:58 UTC
When a shader cache built on one Flutter minor release is bundled into an app targeting a later version, Impeller may reject or recompile the assets, causing the first‑frame latency spike to return. The research cautions that cache compatibility is not guaranteed across Flutter minor releases, and developers should regenerate the cache after any shader code change or version bump to maintain the latency benefit.