Skia & Impeller #

Dua nama ini adalah inti dari bagaimana Flutter mengubah instruksi gambar menjadi piksel di layar. Skia adalah engine yang membesarkan Flutter sejak awal. Impeller adalah penerusnya — dibangun khusus untuk Flutter dan dirancang menyelesaikan masalah fundamental yang tidak bisa dipecahkan Skia. Memahami keduanya berarti memahami mengapa Flutter bisa (dan terkadang tidak bisa) memberikan animasi yang benar-benar smooth.

Konteks: Apa Itu Rendering Engine? #

Sebelum membandingkan keduanya, penting untuk memahami peran rendering engine dalam pipeline Flutter. Rendering engine menerima layer tree dari Framework dan mengeksekusinya menjadi piksel di frame buffer GPU:

Layer Tree (dari Framework)
         |
         v
   Rendering Engine     <-- Skia atau Impeller
   (Raster Thread)
         |
         v
   GPU Draw Calls
         |
         v
   Frame Buffer (piksel)
         |
         v
   Layar

Rendering engine adalah komponen yang paling menentukan seberapa smooth animasi terasa di tangan pengguna.


Skia — Fondasi Awal Flutter #

Skia adalah library grafis 2D open-source yang dikembangkan oleh Google. Ia bukan dibuat khusus untuk Flutter — Skia digunakan di banyak produk Google termasuk Chrome, Android, dan YouTube. Flutter mengadopsinya sejak awal karena sudah matang dan terbukti.

Arsitektur Skia: Immediate Mode Rendering #

Skia menggunakan pendekatan Immediate Mode Rendering (IMR) — setiap drawing command dieksekusi langsung ke GPU saat perintah tersebut diterima:

Frame N dimulai:
  "Gambar rect biru"      --> langsung eksekusi ke GPU
  "Gambar teks 'Halo'"    --> langsung eksekusi ke GPU
  "Gambar lingkaran merah"--> langsung eksekusi ke GPU
Frame N selesai

Frame N+1 dimulai:
  "Gambar rect biru"      --> eksekusi ULANG dari awal
  "Gambar teks 'Halo'"    --> eksekusi ULANG dari awal
  "Gambar lingkaran merah"--> eksekusi ULANG dari awal
Frame N+1 selesai

Setiap frame digambar penuh dari awal — tidak peduli apakah ada sesuatu yang berubah atau tidak.

Bagaimana Skia Menangani Shader #

Shader adalah program kecil yang berjalan di GPU — menentukan warna, gradien, blur, shadow, dan efek visual lainnya. Di Skia, shader dikompilasi menggunakan pendekatan JIT (Just-In-Time):

Pengguna membuka screen baru dengan animasi gradient:

  Frame 1:
    "Butuh shader gradient..."
    Shader belum ada --> COMPILE sekarang (~50-300ms)
    --> JANK! Frame ini butuh jauh lebih dari 16ms
    --> Animasi terlihat patah di frame pertama

  Frame 2:
    Shader sudah di-cache GPU --> eksekusi normal (~5ms)
    --> Smooth

  Frame 3, 4, 5, ...:
    Cache masih ada --> eksekusi normal
    --> Smooth

Inilah yang disebut shader compilation jank — jeda yang hanya terjadi saat shader pertama kali dibutuhkan. Masalahnya: jank ini selalu terjadi di momen yang paling terlihat pengguna, yaitu saat pertama kali membuka screen baru atau menjalankan animasi yang belum pernah berjalan sebelumnya.

Kelebihan Skia #

  • Matang dan battle-tested — digunakan selama belasan tahun di Chrome, Android, YouTube
  • Dukungan platform sangat luas — OpenGL, Vulkan, Metal, Direct3D, software rendering
  • Ekosistem besar — banyak optimasi dan fix yang terakumulasi selama bertahun-tahun
  • Web support — CanvasKit (Skia compiled to WebAssembly) masih menjadi backbone Flutter Web

Kelemahan Skia #

  • Shader compilation jank — masalah fundamental yang tidak bisa diselesaikan tanpa redesign
  • Immediate mode — selalu menggambar ulang seluruh frame meskipun hanya 1 piksel yang berubah
  • Ketergantungan pada OpenGL — OpenGL sedang dideprecate oleh Apple; Skia harus bridging ke Metal
  • Binary size lebih besar — menyertakan infrastruktur shader compilation runtime (~17% ukuran engine)

Mengapa Impeller Diciptakan #

Shader compilation jank bukan bug yang bisa di-patch — ini adalah konsekuensi arsitektur dari pendekatan JIT shader Skia. Tim Flutter menyimpulkan bahwa satu-satunya cara menyelesaikannya secara permanen adalah membangun rendering engine baru dari awal, dengan prinsip desain yang berbeda fundamental.

Impeller mulai dikembangkan secara serius sejak 2021 dengan satu tujuan utama: menghilangkan shader compilation jank sepenuhnya, bukan meminimalkannya.


Impeller — Rendering Engine Generasi Baru #

Impeller adalah rendering engine yang dibangun khusus untuk Flutter — tidak digunakan oleh produk Google lain. Ini berarti Impeller bisa dioptimalkan sepenuhnya untuk kebutuhan spesifik Flutter tanpa harus berkompromi dengan use case lain.

Arsitektur Impeller: Tile-Based Retained Rendering #

Impeller menggunakan dua pendekatan berbeda dari Skia sekaligus:

Retained Mode Rendering:

Frame N dimulai:
  Impeller membandingkan dengan frame sebelumnya
  Hanya elemen yang BERUBAH yang digambar ulang
  Elemen yang SAMA di-reuse dari GPU buffer cache
Frame N selesai

Frame N+1 dimulai:
  Hanya perubahan incremental yang diproses
  --> Jauh lebih efisien dari IMR
Frame N+1 selesai

Tile-Based Rendering:

Frame dibagi menjadi tile (misal 256x256 piksel):

  +--------+--------+--------+
  | Tile 1 | Tile 2 | Tile 3 |
  +--------+--------+--------+
  | Tile 4 | Tile 5 | Tile 6 |
  +--------+--------+--------+
  | Tile 7 | Tile 8 | Tile 9 |
  +--------+--------+--------+

Jika animasi hanya terjadi di Tile 5:
  --> Hanya Tile 5 yang di-rasterisasi ulang
  --> Tile lain di-reuse dari cache GPU
  --> Efisiensi GPU meningkat drastis

Tile-based rendering sangat cocok untuk tiling GPU yang digunakan di hampir semua perangkat mobile modern (ARM Mali, Apple GPU, Qualcomm Adreno).

AOT Shader Compilation — Solusi Jank #

Inilah perbedaan paling signifikan Impeller dari Skia:

SKIA (JIT Shader):
  flutter build ios
       |
       v
  App dikemas --> Shader BELUM dikompilasi
       |
       v
  User buka app --> Jalankan frame pertama
       |
       v
  Shader dibutuhkan --> Compile SEKARANG --> JANK

------------------------------------------------------

IMPELLER (AOT Shader):
  flutter build ios
       |
       v
  impellerc mengkompilasi SEMUA shader
  (selama proses build, bukan saat runtime)
       |
       v
  App dikemas --> Shader SUDAH dikompilasi
       |
       v
  User buka app --> Shader langsung tersedia
       |
       v
  Tidak ada kompilasi saat runtime --> TIDAK ADA JANK

Impeller menggunakan tool bernama impellerc — Impeller Shader Compiler — yang berjalan saat flutter build. Ia mengkompilasi shader GLSL menjadi format spesifik platform:

GLSL Shader Source
       |
       v
  impellerc (saat build time)
       |
       +-- Metal Shader Library (.metallib) --> untuk iOS/macOS
       +-- SPIR-V Binary                    --> untuk Vulkan (Android)
       +-- OpenGL ES Shader (compiled)      --> untuk fallback

Backend GPU Modern: Metal dan Vulkan #

Impeller dirancang sejak awal untuk modern graphics API — bukan OpenGL yang sudah aging:

SKIA:
  Utamanya OpenGL --> bridging ke Metal/Vulkan
  (Apple mendeprecate OpenGL di iOS sejak 2018)

IMPELLER:
  iOS/macOS --> Metal (langsung, native)
  Android   --> Vulkan (langsung, native)
  Fallback  --> OpenGL ES (untuk device lama)

Modern API seperti Metal dan Vulkan memberikan:

  • Kontrol GPU yang lebih langsung dan granular
  • Overhead driver yang lebih rendah
  • Paralelisme yang lebih baik (multi-thread GPU command submission)
  • Prediktabilitas performa yang lebih tinggi

Concurrency — Multi-Thread Frame Rendering #

Impeller dapat mendistribusikan pekerjaan satu frame ke beberapa CPU thread:

Single frame rendering dengan Impeller:

  Thread 1: Proses layer tree atas
  Thread 2: Proses layer tree bawah      --> paralel
  Thread 3: Encode GPU commands
                |
                v
           GPU eksekusi semua sekaligus

Ini sangat efektif di perangkat dengan banyak core CPU seperti iPhone dan Android flagship modern.

Data Performa Nyata #

Beberapa angka yang dilaporkan dari aplikasi produksi dan pengujian resmi:

SkenarioSkiaImpeller
Complex clipping frame time~450ms~11ms
Shader compilation jankAda (first frame)Tidak ada
Dropped frames (animasi hero)BaselineBerkurang >70%
Memory usage (kondisi tertentu)Baseline~100MB lebih rendah
Power usage (animasi berat)BaselineJauh lebih efisien

Status Saat Ini (2025) #

Platform         Engine Default    Catatan
-------          -------------     -------
iOS              Impeller          Default sejak Flutter 3.10
                                   Tidak bisa kembali ke Skia (3.29+)

Android API 29+  Impeller          Default sejak Flutter 3.27
                                   Backend: Vulkan

Android < API 29 Impeller          Fallback otomatis ke OpenGL ES
                                   (tidak perlu konfigurasi manual)

macOS            Impeller          Tersedia, behind flag
Web              Skia (CanvasKit)  Impeller/Wasm dalam pengembangan
Windows/Linux    Skia              Impeller masih dalam eksplorasi

Cara Menonaktifkan Impeller (untuk Debugging) #

# Nonaktifkan Impeller saat debugging (jika ada rendering bug)
flutter run --no-enable-impeller

# iOS: tidak bisa dinonaktifkan sejak Flutter 3.29

Yang Tetap Menggunakan Skia/Komponen Skia #

Meski Impeller mengambil alih rendering utama, beberapa komponen masih menggunakan Skia:

Impeller menggantikan Skia untuk:
  [X] 2D rendering (rect, circle, path, dll.)
  [X] Shader execution (gradient, blur, shadow)
  [X] Compositing dan layer management
  [X] GPU resource management

Masih menggunakan komponen Skia:
  [ ] SkParagraph --> text shaping dan layout
  [ ] Skia codecs --> image decoding (JPEG, PNG, WebP)

Flutter Web masih sepenuhnya menggunakan:
  [ ] CanvasKit (Skia compiled to WebAssembly)

Mengapa text shaping masih pakai SkParagraph?

Text shaping adalah proses yang sangat kompleks — melibatkan ligatur, kerning, BiDi (bidirectional text), dan aturan tipografi yang berbeda-beda per bahasa. SkParagraph sudah sangat matang dan akurat untuk ini. Membangun ulang text shaping dari nol di Impeller akan membutuhkan waktu bertahun-tahun dan berisiko memperkenalkan regresi yang sulit ditemukan. Tim Flutter memutuskan untuk tetap menggunakan SkParagraph sampai ada alternatif yang sama matangnya.


Impeller dan Masa Depan: Flutter GPU #

Impeller membuka pintu untuk sesuatu yang tidak bisa dilakukan Skia: rendering 3D dari Dart.

// Flutter GPU API (eksperimental, 2025)
// Memungkinkan developer menulis shader kustom dan rendering 3D
// langsung dari kode Dart

import 'dart:ui' as ui;

// Render 3D mesh dengan custom shader
void render3DScene(gpu.RenderPass renderPass) {
  renderPass
    ..bindPipeline(myMeshPipeline)
    ..bindVertexBuffer(meshVertices)
    ..bindUniform('mvpMatrix', modelViewProjection)
    ..draw(vertexCount: mesh.vertexCount);
}

Di atas Flutter GPU, tim Flutter sedang membangun Flutter Scene — library untuk mengimpor dan merender model 3D dalam format glTF. Ini akan membuka kemungkinan game, visualisasi data 3D, dan augmented reality yang sebelumnya tidak mungkin dilakukan di Flutter.


Ringkasan #

  • Skia adalah rendering engine 2D yang matang dan battle-tested — digunakan Flutter sejak awal tapi punya masalah fundamental: shader compilation jank.
  • Shader compilation jank terjadi karena Skia mengkompilasi shader JIT saat runtime — menghasilkan jeda di frame pertama setiap animasi baru.
  • Impeller adalah rendering engine baru khusus Flutter — menggunakan tile-based retained rendering dan AOT shader compilation untuk menghilangkan jank sepenuhnya.
  • Impeller menarget Metal (iOS/macOS) dan Vulkan (Android) secara langsung — bukan melalui bridging OpenGL seperti Skia.
  • Impeller adalah default di iOS (sejak Flutter 3.10, wajib sejak 3.29) dan Android API 29+ (sejak Flutter 3.27).
  • Text shaping dan image decoding masih menggunakan komponen Skia (SkParagraph, Skia codecs) — Impeller hanya menggantikan rendering grafis.
  • Flutter GPU API yang dibangun di atas Impeller membuka kemungkinan rendering 3D dan shader kustom langsung dari Dart — sesuatu yang tidak pernah bisa dilakukan Skia.

← Sebelumnya: Rendering Pipeline   Berikutnya: Perbandingan Native →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact