skip to content

In Flutter 3.47, which graphics backend does the renderer use on each platform, and where does Skia still render?

level: middleimportance: should knowfreq 35%

answer

  1. Metal on Apple platforms
  2. Vulkan first on Android 29+
  3. Impeller OpenGL ES fallback
  4. below API 29: Skia OpenGL ES
  5. web stays on Skia

basics

~10 s

iOS and macOS: Impeller on Metal. Android API 29+: Impeller on Vulkan, else Impeller's OpenGL ES backend; below API 29, Skia on OpenGL ES. Windows and Linux: Impeller since 3.47, over OpenGL. Web: Skia.

solid answer

~40 s

Impeller is portable across graphics APIs, so the backend depends on the platform. On **iOS** Impeller is the only renderer, on **Metal**; **macOS** also uses Metal and defaults to Impeller since 3.47. On **Android**, the engine selects Impeller for API 29 and newer and then tries **Vulkan** (1.1 with the required extensions), falling back to Impeller's **OpenGL ES** backend on emulators, on known-bad drivers and chipsets, or when a Vulkan context cannot be created; below API 29 (and on Vivante GPUs) it uses the legacy **Skia OpenGL ES** renderer. **Windows** and **Linux** default to Impeller since 3.47 and render through OpenGL surfaces (ANGLE on Windows). The **web** still renders with Skia. On Android you can read which backend was chosen from logcat, which prints `Using the Impeller rendering backend (Vulkan).` or `(OpenGLES).`

go deeper

for a junior

Recall the short version: Apple platforms use Metal, Android prefers Vulkan, and the web still uses Skia.

for a middle

Explain Android's selection: API 29 floor, Vulkan first, Impeller OpenGL ES fallback, Skia below 29, and how to read the chosen backend from logcat.

for a senior

Use backend knowledge when triaging device-specific rendering bugs, include backend and chipset in reports, and treat emulators and pre-Android-10 devices as separate cases.

for a principal

Factor the renderer matrix into the device support policy, deciding how long to keep testing legacy Skia paths for older Android devices.

## Renderer vs backend Two separate choices decide how a Flutter frame reaches the GPU: - the **renderer**: Impeller or the legacy Skia path, which turns the scene into drawing operations; - the **backend**: the graphics API the renderer talks to, such as **Metal**, **Vulkan** or **OpenGL ES**. Impeller was designed to be portable: its shaders are written once and compiled at engine build time into each backend's format (Metal libraries, Vulkan SPIR-V archives, OpenGL ES shader archives). So one renderer runs on several APIs. ## The platform table for Flutter 3.47 | Platform | Default renderer | Backend | |---|---|---| | iOS | Impeller (the only option) | Metal | | macOS | Impeller (default since 3.47) | Metal | | Android API 29+ | Impeller | Vulkan when usable, otherwise Impeller's OpenGL ES | | Android below API 29 | legacy Skia | OpenGL ES | | Windows | Impeller (default since 3.47) | OpenGL ES, through ANGLE | | Linux | Impeller (default since 3.47) | OpenGL | | Web | Skia | the browser's graphics stack | The web renderers themselves are a separate topic; here it is enough that Impeller is not used there yet. ## How Android chooses Android has the most varied hardware, and the engine's selection is explicit in its source: 1. If Impeller is enabled and the device runs **API 29 or newer** (and is not a Vivante GPU), the engine picks **Impeller** with automatic backend selection. Otherwise it uses **Skia on OpenGL ES**. 2. Within Impeller, it avoids Vulkan on **emulators**, on some vendors and chipsets whose Vulkan drivers are known to misbehave, and on older MediaTek devices. 3. Otherwise it tries to create a **Vulkan** context (Vulkan 1.1 with the extensions needed for platform views). If that fails, it falls back to Impeller's **OpenGL ES** backend. API 29 is the floor because Android 10 provides `HardwareBuffer` support that Impeller relies on for platform views. The public docs summarize the fallback as "the legacy OpenGL renderer" for non-Vulkan devices; the engine source distinguishes the two cases: below API 29 it is Skia, while on API 29+ without usable Vulkan it is Impeller's own OpenGL ES backend. ## Finding out what a device is using - **Android logcat** prints `Using the Impeller rendering backend (Vulkan).` or `Using the Impeller rendering backend (OpenGLES).` at startup. No such line means the Skia path. - For testing, debug and profile builds accept an `io.flutter.embedding.android.ImpellerBackend` manifest entry with the value `opengles` to force the OpenGL ES backend; this does not work in release builds. - On iOS there is nothing to check: Impeller on Metal is the only path. ## Why the backend matters to an app developer - **Bug reports need the backend.** A visual glitch that appears only on some Android phones is often backend-specific (Vulkan vs OpenGL ES) or driver-specific. The Impeller issue template asks for the device and chip. - **Emulators are not representative.** An Android emulator avoids Vulkan, so it renders through a different backend from most real devices. - **Old Android devices still behave like the Skia era.** An app with a large installed base on Android 9 and lower can still see first-run shader-compilation stutter there. - **Skia is not gone from the binary.** Under Impeller, text layout (SkParagraph) and image codecs still come from Skia components. ## Interview traps - Saying Impeller "is Vulkan": Impeller is a renderer; Vulkan is one of its backends, and iOS never uses it. - Saying non-Vulkan Android phones fall back to Skia: on API 29 and newer the engine stays in Impeller and uses its OpenGL ES backend. - Forgetting desktop: Impeller has been the default on macOS, Windows and Linux only since 3.47, so older answers that describe desktop as Skia-only are out of date. - Treating the web as part of this picture: web rendering is a separate, Skia-based design. ## Summary - Apple platforms: Impeller on Metal. - Android: Impeller on Vulkan, with Impeller OpenGL ES as the fallback on API 29+, and Skia OpenGL ES below 29. - Desktop: Impeller by default since 3.47. - Web: Skia.

  • Why does an Android emulator not tell you how a Vulkan-capable phone renders?
    The engine deliberately avoids Vulkan on known emulators, so Impeller runs on its OpenGL ES backend there. Most modern phones use Vulkan, so a glitch or performance profile seen on an emulator may not match real devices. Check logcat's backend line and test on hardware.
  • An app still supports Android 9 devices. What renderer-related difference should the team expect on them?
    Below API 29 the engine uses the legacy Skia renderer on OpenGL ES, not Impeller. Those devices can still show the old first-run shader-compilation stutter and may render some effects slightly differently. Treat them as a separate test target.

saying these in an interview costs you the question

  • Impeller uses Vulkan on iOS.
  • Every Android device renders with Impeller on Vulkan.
  • An Android phone without Vulkan falls back to Skia even on API 29 or newer.
  • Flutter web switched to Impeller in 3.47.
  • The Android emulator uses the same backend as most real phones.