Skia & Impeller #
Dua nama ini mewakili komponen mesin grafis (rendering engine) yang memegang kendali penuh atas bagaimana Flutter menerjemahkan instruksi kode Dart kita menjadi jutaan piksel fisik di layar perangkat. Selama bertahun-tahun, Skia telah menjadi fondasi utama yang mendampingi tumbuh kembang Flutter sejak awal peluncurannya. Namun, seiring dengan tuntutan performa antarmuka yang semakin tinggi serta evolusi arsitektur kartu grafis modern, Google mengembangkan Impeller — mesin grafis generasi baru yang dirancang khusus untuk Flutter. Memahami perbedaan fundamental, arsitektur teknis, dan cara kerja dari kedua mesin rendering ini sangat penting bagi kita untuk memahami bagaimana performa visual Flutter dioptimalkan.
Konteks: Apa Itu Rendering Engine? #
Sebelum kita membandingkan Skia dan Impeller secara langsung, kita perlu memahami peran spesifik dari mesin rendering di dalam siklus hidup aplikasi Flutter. Seperti yang telah dibahas pada topik rendering pipeline, setelah UI Thread Dart selesai menyusun hierarki visual aplikasi, ia mengirimkan data terkomposisi berupa objek biner Layer Tree melalui binding dart:ui.
Di sinilah tugas mesin rendering dimulai. Berjalan di atas Raster Thread (thread asinkron C++), mesin rendering bertindak sebagai penerjemah akhir:
flowchart TD
LayerTree["Layer Tree (Hasil UI Thread)"] -->|"1. Kirim via dart:ui"| RenderEngine["Rendering Engine (Raster Thread)"]
RenderEngine -->|"2. Hitung Rasterisasi & Shader"| GPU["GPU Hardware (Metal/Vulkan/GL)"]
GPU -->|"3. Tulis Biner Piksel"| Framebuffer["Framebuffer (VRAM)"]
Framebuffer -->|"4. Swap Buffer pada VSync"| Display["Layar Perangkat"]
style RenderEngine stroke:#0288d1,stroke-width:2px
style GPU stroke:#7b1fa2,stroke-width:2pxMesin rendering bertanggung jawab untuk merasterisasi setiap bentuk vektor, garis, teks, dan gambar bitmap, serta mengeksekusi efek shader (seperti blur, gradien, dan bayangan) menggunakan instruksi biner yang dimengerti langsung oleh kartu grafis perangkat keras (GPU).
Skia — Fondasi Awal Flutter #
Skia adalah pustaka grafis 2D sumber terbuka (open-source) legendaris yang dikembangkan secara aktif oleh Google. Berbeda dengan Impeller, Skia tidak dibangun secara eksklusif untuk Flutter. Skia adalah mesin grafis universal yang digunakan secara luas di berbagai produk raksasa industri seperti peramban web Google Chrome, sistem operasi Android, Mozilla Firefox, hingga video player YouTube.
Arsitektur Skia: Immediate Mode Rendering #
Skia beroperasi menggunakan paradigma Immediate Mode Rendering (IMR). Di bawah model ini, setiap kali instruksi gambar dikirimkan oleh Framework (misalnya: “gambar persegi panjang biru di koordinat X”), Skia langsung mengirimkan perintah menggambar tersebut ke GPU pada saat itu juga.
flowchart TD
subgraph ImmediateMode["Skia Immediate Mode Rendering"]
direction TB
FrameN["Frame N: Render Ulang Semua Elemen Grafis"] -->|"VSync Trigger"| FrameN1["Frame N+1: Render Ulang Semua Elemen Lagi dari Nol"]
FrameN1 -->|"VSync Trigger"| FrameN2["Frame N+2: Render Ulang Semua Elemen Lagi dari Nol"]
endKarakteristik utama IMR adalah kesederhanaannya: Skia tidak melacak status posisi gambar pada frame sebelumnya secara mendalam. Ketika sinyal VSync meminta frame baru, Skia membersihkan kanvas layar secara penuh dan menggambar ulang seluruh elemen visual dari nol. Meskipun sederhana, pendekatan ini sangat membebani GPU karena memerlukan daya komputasi yang besar meskipun hanya ada satu komponen kecil di layar yang bergerak.
Shader JIT Compilation: Penyebab Utama Jank #
Shader adalah program mikro yang dieksekusi secara paralel di dalam GPU untuk menentukan warna dan pencahayaan setiap piksel layar. Skia menulis shader ini dalam bahasa GLSL (OpenGL Shading Language).
Kelemahan terbesar Skia ketika diintegrasikan dengan arsitektur UI deklaratif dinamis Flutter adalah metode kompilasi shadernya yang menggunakan pendekatan JIT (Just-In-Time). Skia tidak tahu shader apa saja yang akan dibutuhkan oleh aplikasi kita sampai aplikasi tersebut berjalan (runtime).
- Pengguna memicu animasi transisi halaman baru yang memiliki efek bayangan (shadow) dan gradien warna kustom.
- Skia menyadari bahwa ia tidak memiliki program shader untuk efek tersebut di dalam memori cache GPU.
- Skia menghentikan sementara proses rendering visual dan mulai menulis serta mengompilasi shader tersebut ke GPU secara dinamis saat itu juga.
- Kompilasi GPU runtime ini memakan waktu berkisar antara 10 hingga 50 milidetik.
- Karena batas waktu rendering frame kita untuk laju 60 FPS adalah 16,6ms, jeda kompilasi ini menyebabkan keterlambatan frame (frame drop), menghasilkan efek patah-patah visual yang mengganggu mata pengguna (shader compilation jank).
Kelebihan Skia #
- Battle-Tested & Sangat Matang: Telah dikembangkan selama belasan tahun dan diuji kestabilannya pada miliaran perangkat aktif di dunia.
- Dukungan Platform Sangat Luas: Mampu berjalan di atas hampir semua driver grafis legasi, termasuk OpenGL, OpenGL ES, Vulkan, Metal, Direct3D, hingga software rendering murni menggunakan CPU.
- Ekosistem Web yang Kuat: CanvasKit (Skia yang dikompilasi ke WebAssembly) masih menjadi mesin rendering Flutter Web yang paling andal untuk menyajikan UI yang identik dengan mobile.
Kelemahan Skia #
- Shader Jank yang Permanen: Masalah shader compilation jank tidak dapat diperbaiki secara total tanpa merombak total struktur internal engine Skia.
- Overhead Bridging API: Karena dirancang di era OpenGL, Skia harus menggunakan lapisan bridging tambahan untuk berkomunikasi dengan API modern seperti Metal milik Apple, yang menambah beban kerja CPU.
- Ukuran Biner Lebih Besar: Harus menyertakan seluruh modul compiler shader runtime (infrastruktur kompilasi GLSL) di dalam paket biner aplikasi kita.
Mengapa Impeller Diciptakan #
Masalah shader compilation jank pada Skia sebenarnya dapat diredakan secara parsial menggunakan teknik pemanasan shader (shader warm-up atau sksl-bundle). Namun, proses ini sangat merepotkan karena pengembang harus merekam animasi secara manual di perangkat fisik, mengekspor berkas konfigurasi .sksl, dan menyertakannya saat melakukan build rilis. Terlebih lagi, berkas konfigurasi tersebut sering kali tidak kompatibel jika dijalankan pada perangkat dengan jenis GPU yang berbeda.
Selain masalah jank, evolusi ekosistem sistem operasi memaksa tim Flutter untuk mengambil keputusan besar. Pada tahun 2018, Apple secara resmi menghentikan dukungan (deprecate) terhadap OpenGL pada iOS dan macOS untuk beralih secara penuh ke Metal API. Karena Skia secara historis berakar pada OpenGL, bridging paksa ke Metal API melahirkan overhead kinerja yang tidak perlu.
Tim Flutter menyimpulkan bahwa satu-satunya solusi permanen untuk menghilangkan shader jank dan memaksimalkan potensi kartu grafis modern adalah dengan membangun mesin rendering baru dari nol yang didesain eksklusif hanya untuk kebutuhan Flutter: Impeller.
Impeller — Rendering Engine Generasi Baru #
Impeller mulai dirancang secara aktif sejak akhir tahun 2021. Berbeda dengan Skia yang harus berkompromi dengan kebutuhan peramban web Chrome atau sistem operasi Android, Impeller dikembangkan dengan satu fokus tunggal: mengeksekusi pipeline UI deklaratif Flutter secepat dan semulus mungkin.
Arsitektur Impeller dibangun di atas empat pilar desain yang berbeda secara fundamental dari Skia:
1. Model Retained Mode Rendering #
Impeller meninggalkan model menggambar ulang semua elemen dari awal milik Skia dan mengadopsi pola Retained Mode Rendering. Di bawah model ini, Impeller melacak dan memelihara status visual setiap lapisan di memori GPU secara aktif.
Ketika frame baru dipicu:
- Impeller melakukan analisis inkremental untuk mendeteksi bagian visual mana saja yang mengalami perubahan posisi atau warna.
- Impeller hanya merasterisasi ulang area yang kotor (dirty tiles).
- Untuk area visual yang statis (seperti gambar latar belakang atau teks judul), Impeller langsung menggunakan kembali cache tekstur GPU yang sudah ada tanpa melakukan rendering ulang.
2. Komposisi Berbasis Ubin (Tile-Based Rendering) #
Untuk meminimalkan beban kerja GPU pada perangkat mobile yang memiliki keterbatasan daya baterai, Impeller membagi layar menjadi kisi-kisi ubin kecil (misalnya berukuran $256 \times 256$ piksel).
flowchart TD
subgraph Grid["Visualisasi Tile-Based Grid"]
direction TB
T1["Tile 1 (Statis)"] --- T2["Tile 2 (Statis)"] --- T3["Tile 3 (Statis)"]
T4["Tile 4 (Statis)"] --- T5["Tile 5 (Dinamis / Berubah)"] --- T6["Tile 6 (Statis)"]
T7["Tile 7 (Statis)"] --- T8["Tile 8 (Statis)"] --- T9["Tile 9 (Statis)"]
end
style T5 stroke:#f44336,stroke-width:2pxJika animasi riak sentuhan air (ink ripple) hanya terjadi di bagian tengah bawah (misalnya di area Tile 5), Impeller menginstruksikan kartu grafis untuk hanya memproses piksel di dalam kotak Tile 5 tersebut, sedangkan ubin lainnya diabaikan dari perhitungan rasterisasi baru. Hal ini menghemat siklus kerja GPU secara signifikan.
3. Kompilasi Shader Ahead-Of-Time (AOT) #
Inilah senjata utama Impeller yang menyelesaikan masalah shader jank secara permanen. Impeller memindahkan seluruh proses kompilasi shader dari fase jalannya aplikasi (runtime) menuju fase pembangunan paket aplikasi (build time).
Ketika kita menjalankan perintah build (seperti flutter build apk atau flutter build ipa), sistem Flutter memicu compiler shader khusus bernama impellerc:
flowchart TD
GLSL["Shader GLSL (Kode Sumber)"] -->|"impellerc (Build Time)"| Compile{"Platform Target?"}
Compile -->|"iOS / macOS"| MetalLib["Metal Shader Library (.metallib)"]
Compile -->|"Android (Vulkan)"| SPIRV["SPIR-V Binary (.spirv)"]
Compile -->|"Legacy OpenGL Fallback"| GLES["OpenGL ES Shader (Compiled)"]
style Compile stroke:#0288d1,stroke-width:2pximpellerc menerjemahkan semua shader GLSL dalam SDK menjadi format pustaka shader biner native yang siap dieksekusi oleh GPU target. Ketika pengguna menginstal dan membuka aplikasi kita untuk pertama kalinya, kartu grafis langsung memuat biner shader tersebut secara instan (0ms delay) tanpa ada proses kompilasi dinamis lagi. Jank hilang sepenuhnya.
4. Pemanfaatan API Grafis Modern Native #
Impeller dibangun khusus untuk langsung menarget API grafis modern generasi baru yang menyediakan kontrol hardware yang lebih granular, overhead CPU driver yang sangat rendah, serta kemampuan eksekusi paralel multi-thread yang luar biasa.
- iOS / macOS: Berkomunikasi langsung dengan Metal API native.
- Android: Berkomunikasi langsung dengan Vulkan API native (pada perangkat Android API level 29 ke atas).
- Android Legacy Fallback: Menggunakan OpenGL ES jika dijalankan pada perangkat Android lama yang belum mendukung Vulkan secara stabil.
Data Perbandingan Performa Nyata #
Berikut adalah matriks perbandingan performa visual antara Skia dan Impeller berdasarkan hasil pengujian resmi pada aplikasi produksi:
| Metrik Evaluasi | Skia Engine | Impeller Engine |
|---|---|---|
| Shader Compilation Jank | Sering terjadi di frame pertama animasi baru. | Bebas jank sepenuhnya karena shader dikompilasi AOT. |
| Beban Komposisi Kliping Kompleks | Lambat (~450ms pada skenario kliping dalam). | Sangat cepat (~11ms) karena dioptimalkan di GPU. |
| Laju Frame Hilang (Dropped Frames) | Baseline standar. | Berkurang hingga >70% pada transisi animasi cepat. |
| Konsumsi Memori RAM | Baseline standar. | Lebih hemat hingga ~100MB pada skenario rendering berat. |
| Ukuran Biner Overhead Engine | Lebih besar karena membawa JIT compiler runtime. | Lebih kecil (~100kb overhead compressed) karena compiler dibuang. |
Status Saat Ini (2025) #
Proses transisi mesin rendering dari Skia menuju Impeller berjalan secara bertahap untuk menjaga stabilitas aplikasi di tingkat produksi. Berikut adalah status adopsi default Impeller pada berbagai target platform:
| Sistem Operasi Target | Status Mesin Default | Backend Grafis Aktif | Catatan Penting |
|---|---|---|---|
| iOS | Impeller (Default) | Metal API | Diaktifkan sejak Flutter 3.10. Mulai Flutter 3.29+, dukungan Skia dihapus secara permanen dari biner iOS. |
| Android (API 29+) | Impeller (Default) | Vulkan API | Diaktifkan secara default mulai Flutter 3.27. |
| Android (API < 29) | Impeller (Default) | OpenGL ES | Melakukan fallback otomatis secara transparan tanpa konfigurasi manual. |
| macOS | Tersedia | Metal API | Dapat diaktifkan secara manual melalui flag runtime. |
| Web | Belum Aktif | CanvasKit (Skia Wasm) | Impeller berbasis Skwasm/WebGPU masih dalam tahap pengembangan aktif. |
| Windows / Linux | Belum Aktif | Skia Engine | Impeller desktop Vulkan masih dalam proses eksplorasi internal. |
Jika kita menemukan isu rendering visual tertentu pada perangkat Android selama masa pengembangan, kita dapat menonaktifkan Impeller secara sementara untuk membandingkan hasilnya dengan Skia menggunakan perintah berikut:
# Menjalankan aplikasi Android dengan memaksa penggunaan engine Skia
flutter run --no-enable-impeller
Yang Tetap Menggunakan Skia/Komponen Skia #
Meskipun Impeller mengambil alih seluruh tugas merasterisasi bentuk vektor dan memproses shader visual, sistem Flutter tidak membuang Skia secara keseluruhan dari biner engine. Hal ini dikarenakan ada dua subsistem yang masih sangat optimal jika dikerjakan oleh pustaka bawaan Skia:
- SkParagraph (Text Layout): Proses analisis tata letak tulisan (text shaping) sangat kompleks karena melibatkan aturan unicode dan tipografi lintas bahasa. Subsistem
SkParagraphmilik Skia sudah sangat matang dan teruji keakuratannya. Oleh karena itu, Flutter tetap menggunakanSkParagraphuntuk melakukan kalkulasi posisi huruf, sementara Impeller bertugas menggambar glyph huruf tersebut ke kanvas visual. - Skia Codecs (Image Decoding): Pustaka decoder gambar bawaan Skia masih digunakan untuk mendekode file biner gambar terkompresi (seperti format JPEG, PNG, dan WebP) menjadi tekstur mentah GPU sebelum diserahkan ke Impeller.
Pemisahan tugas ini berjalan secara transparan dan dikelola penuh di tingkat Engine Layer tanpa memengaruhi kode Dart yang kita tulis.
Impeller dan Masa Depan: Flutter GPU #
Desain arsitektur modern Impeller membuka gerbang baru bagi ekosistem Flutter yang sebelumnya tidak mungkin dicapai ketika menggunakan Skia. Salah satunya adalah diperkenalkannya Flutter GPU API secara eksperimental.
Flutter GPU adalah pustaka binding tingkat rendah (low-level graphics API) yang ditulis dalam bahasa Dart. Pustaka ini memungkinkan kita sebagai pengembang untuk:
- Mengakses jalur pipa rendering kartu grafis secara langsung dari kode Dart (menulis custom render passes).
- Memasukkan file model 3D berformat glTF menggunakan pustaka pembantu
Flutter Scene. - Merender objek-objek 3D berkinerja tinggi, pencahayaan dinamis, serta partikel interaktif langsung di dalam aplikasi Flutter berdampingan dengan widget 2D biasa tanpa memerlukan game engine pihak ketiga.
import 'dart:ui' as ui;
// Visualisasi konseptual merender model 3D menggunakan Flutter GPU API
void renderCustom3DMesh(gpu.RenderPass renderPass, gpu.Buffer vertexBuffer) {
renderPass
..bindPipeline(shader3DPipeline) // Shader GLSL yang dikompilasi AOT oleh impellerc
..bindVertexBuffer(vertexBuffer)
..draw(vertexCount: 36); // Menggambar objek kubus 3D
}
Inovasi ini menempatkan Flutter bukan lagi sekadar sebagai UI SDK biasa, melainkan bertransformasi menjadi platform visual interaktif berkinerja tinggi yang siap menghadapi masa depan rekayasa grafis 3D dan Augmented Reality (AR).
Ringkasan #
- Dua Era Rendering — Skia adalah mesin rendering 2D universal yang matang milik Google, sedangkan Impeller adalah mesin rendering generasi baru yang didesain eksklusif hanya untuk Flutter.
- Shader Jank di Skia — Terjadi akibat pendekatan kompilasi JIT (Just-In-Time) di mana shader GPU baru ditulis dan dikompilasi saat runtime ketika transisi animasi baru muncul.
- Solusi AOT Impeller — Mengompilasi seluruh shader GLSL secara statis menggunakan compiler
impellercsaat build-time (AOT), sehingga shader siap pakai instan saat runtime tanpa memicu jank.- Optimasi Retained Mode — Impeller melacak status memori GPU secara aktif dan hanya merasterisasi ubin layar yang berubah (tile-based rendering) untuk menghemat komisi daya GPU.
- API Modern Tanpa Bridging — Impeller berkomunikasi langsung dengan API grafis native modern Metal (iOS) dan Vulkan (Android) untuk meminimalkan overhead kerja CPU.
- Dukungan iOS & Android — Impeller telah aktif secara default untuk seluruh aplikasi iOS (sejak 3.10) dan perangkat Android API level 29+ (sejak 3.27).
- Pembagian Tugas dengan Skia — Tetap mempertahankan komponen
SkParagraphmilik Skia untuk menangani text layout dan penentuan glyph tulisan kompleks demi kestabilan rendering.- Ekspansi Flutter GPU — Memanfaatkan fondasi shader Impeller untuk menyediakan API grafis 3D native (
Flutter Scene) langsung dari Dart.
← Sebelumnya: Rendering Pipeline Berikutnya: Perbandingan Native →