Akselerasi hardware

Pipeline rendering 2D Android mendukung akselerasi hardware, yang berarti semua operasi gambar yang dilakukan di kanvas menggunakan GPU. Karena perlu resource yang lebih tinggi untuk mengaktifkan akselerasi hardware, aplikasi Anda akan mengonsumsi lebih banyak RAM.

Akselerasi hardware diaktifkan secara default. Jika aplikasi Anda hanya menggunakan composable standar, mengaktifkannya secara global tidak akan menimbulkan efek gambar yang merugikan. Namun, karena akselerasi hardware tidak didukung untuk semua operasi gambar 2D, mengaktifkannya dapat memengaruhi beberapa panggilan gambar kustom Anda. Masalah biasanya bermanifestasi sebagai elemen tak terlihat, pengecualian, atau piksel yang salah dirender. Untuk mengatasinya, Android menyediakan opsi untuk mengaktifkan atau menonaktifkan akselerasi hardware di beberapa tingkat. Lihat Mengontrol akselerasi hardware.

Jika aplikasi Anda menjalankan gambar kustom, uji aplikasi Anda pada hardware sebenarnya dengan akselerasi hardware diaktifkan untuk menemukan masalah. Bagian Dukungan untuk operasi gambar menjelaskan masalah umum terkait akselerasi hardware dan cara mengatasinya.

Lihat juga OpenGL dengan Framework API.

Mengontrol akselerasi hardware

Anda dapat mengontrol akselerasi hardware di tingkat berikut:

  • Aplikasi
  • Aktivitas
  • Jendela
  • Composable

Tingkat aplikasi

Dalam file manifes Android Anda, tambahkan atribut berikut ke tag <application> untuk mengaktifkan akselerasi hardware di seluruh aplikasi Anda:

<application android:hardwareAccelerated="true" ...>

Tingkat aktivitas

Jika aplikasi Anda tidak berperilaku sebagaimana mestinya saat akselerasi hardware diaktifkan secara global, Anda juga dapat mengontrolnya untuk aktivitas tertentu. Untuk mengaktifkan atau menonaktifkan akselerasi hardware di tingkat aktivitas, Anda dapat menggunakan atribut android:hardwareAccelerated untuk elemen <activity>. Contoh berikut mengaktifkan akselerasi hardware untuk keseluruhan aplikasi, tetapi menonaktifkannya untuk satu aktivitas:

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>

Tingkat jendela

Jika memerlukan kontrol yang lebih terperinci, Anda dapat mengaktifkan akselerasi hardware untuk jendela tertentu dengan kode berikut:

window.setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)

Tingkat composable

Di Compose, tidak ada tombol per-composable untuk menonaktifkan akselerasi hardware.

Untuk merender composable ke dalam lapisannya sendiri, gunakan Modifier.graphicsLayer. Hal ini memungkinkan properti transformasi (seperti alpha, scaleX, scaleY, translationX, translationY, rotationX, rotationY, rotationZ, dan transformOrigin) berubah tanpa menjalankan ulang kode gambar composable. Untuk performa terbaik, selalu gunakan bentuk lambda pengubah untuk menyetel properti ini.

Untuk secara eksplisit memaksa buffer di luar layar untuk operasi gambar lanjutan, seperti pembauran kustom dalam lapisan, gunakan CompositingStrategy.Offscreen. Untuk mengetahui informasi selengkapnya, lihat Pengubah grafis.

Jika Anda memiliki operasi gambar kustom yang benar-benar memerlukan rendering software, Anda dapat menghosting View lama menggunakan AndroidView dan memanggil setLayerType(View.LAYER_TYPE_SOFTWARE, null) pada tampilan tersebut.

Dukungan untuk operasi gambar

Jika akselerasi hardware diaktifkan, pipeline rendering 2D mendukung operasi gambar Canvas yang paling umum digunakan, serta banyak operasi lain yang jarang digunakan. Semua operasi gambar yang digunakan untuk merender aplikasi yang disertakan dengan Android, composable standar, dan efek visual lanjutan yang umum seperti pantulan dan tekstur berubin didukung.

Tabel berikut menjelaskan tingkat dukungan berbagai operasi di tingkat API:

Level API pertama yang didukung
Canvas
drawBitmapMesh() (array warna) 18
drawPicture() 23
drawPosText() 16
drawTextOnPath() 16
drawVertices() 29
setDrawFilter() 16
clipPath() 18
clipRegion() 18
clipRect(Region.Op.XOR) 18
clipRect(Region.Op.Difference) 18
clipRect(Region.Op.ReverseDifference) 18
clipRect() dengan rotasi/perspektif 18
Paint
setAntiAlias() (untuk teks) 18
setAntiAlias() (untuk garis) 16
setFilterBitmap() 17
setLinearText()
setMaskFilter()
setPathEffect() (untuk garis) 28
setShadowLayer() (selain teks) 28
setStrokeCap() (untuk garis) 18
setStrokeCap() (untuk titik) 19
setSubpixelText() 28
Xfermode
PorterDuff.Mode.DARKEN (framebuffer) 28
PorterDuff.Mode.LIGHTEN (framebuffer) 28
PorterDuff.Mode.OVERLAY (framebuffer) 28
Shader
ComposeShader di dalam ComposeShader 28
Shader jenis yang sama di dalam ComposeShader 28
Matriks lokal di ComposeShader 18

Penskalaan kanvas

Pipeline rendering 2D dengan akselerasi hardware mula-mula dibuat untuk mendukung gambar yang tidak diskalakan, karena beberapa operasi gambar mengalami penurunan kualitas secara signifikan pada nilai skala lebih tinggi. Operasi ini diimplementasikan saat tekstur yang digambar pada skala 1.0 diubah oleh GPU. Mulai level API 28, semua operasi gambar dapat diskalakan tanpa masalah.

Tabel berikut menunjukkan kapan implementasi diubah untuk menangani skala besar dengan benar:

Operasi gambar yang akan diskalakan Level API pertama yang didukung
drawText() 18
drawPosText() 28
drawTextOnPath() 28
Bentuk Sederhana 17
Bentuk Kompleks 28
drawPath() 28
Lapisan bayangan 28

Jika operasi gambar yang Anda andalkan tidak diakselerasi hardware, render gambar yang terpengaruh ke Bitmap (atau ImageBitmap) software di luar layar dan gambar hasilnya. Bagian UI lainnya tetap menggunakan jalur yang diakselerasi hardware.

Tips dan trik

Peralihan ke grafis 2D dengan akselerasi hardware dapat meningkatkan performa dengan seketika, tetapi Anda tetap harus mendesain aplikasi agar menggunakan GPU secara efektif dengan mengikuti rekomendasi berikut:

Meminimalkan kompleksitas tata letak dan rekomposisi
Jaga agar pohon tata letak tetap dangkal, dan batasi jumlah rekomposisi. Tunda pembacaan status ke cakupan tersempit, sehingga perubahan menggambar ulang wilayah sekecil mungkin. Misalnya, baca status animasi di dalam Modifier.graphicsLayer { }, bukan di isi composable. Untuk mengetahui informasi selengkapnya, lihat Performa Jetpack Compose.
Hindari overdraw
Jangan menggambar terlalu banyak lapisan yang bertumpuk satu di atas yang lain. Hapus elemen UI yang sepenuhnya terhalang oleh elemen buram lainnya di atasnya. Jika Anda perlu menggambar beberapa lapisan yang dipadukan satu di atas yang lain, pertimbangkan untuk menggabungkannya menjadi satu lapisan. Salah satu aturan praktis terkait hardware saat ini adalah jangan menggambar lebih dari 2,5 kali lipat jumlah piksel di layar per frame (piksel transparan dalam jumlah bitmap!).
Jangan membuat objek render dalam metode gambar
Kesalahan yang umum adalah membuat Paint baru atau Path baru setiap kali metode rendering dipanggil. Hal ini memaksa pembersih sampah memori untuk berjalan lebih sering dan juga mengabaikan cache dan pengoptimalan di pipeline hardware. Untuk menghindarinya, gunakan kembali dan ubah objek Anda:
  • Gunakan metode standar: Metode DrawScope standar (seperti drawRect dan drawCircle) sudah menggunakan kembali objek Paint secara internal tanpa memerlukan alokasi developer.
  • Lakukan mutasi, bukan mengalokasikan ulang: Saat menulis logika kustom, gunakan path.rewind untuk menghapus Path yang ada, bukan membuat instance Path baru.
  • Menyimpan status secara efisien: Di dalam composable, alokasikan objek satu kali menggunakan remember { Path() }. Jika Anda membuat ekstensi pengubah kustom yang dapat digunakan kembali, terapkan Modifier.Node kustom menggunakan DrawModifierNode untuk mengalokasikan dan menggunakan kembali objek tanpa menyebabkan alokasi heap baru.
Jangan terlalu sering mengubah bentuk
Bentuk, jalur, dan lingkaran yang kompleks, misalnya, dirender menggunakan mask tekstur. Setiap kali Anda membuat atau mengubah jalur, pipeline hardware akan membuat mask baru, dan ini dapat memerlukan banyak biaya.
Jangan terlalu sering mengubah bitmap
Setiap kali Anda mengubah konten bitmap, bitmap akan diupload lagi sebagai tekstur GPU saat Anda menggambarnya lagi.
Gunakan alfa dengan hati-hati
Saat Anda membuat composable transparan menggunakan Modifier.alpha atau API animasi Compose, composable tersebut biasanya dirender di buffer luar-layar yang menggandakan rasio pengisian yang diperlukan. Untuk menghindari overhead buffer di luar layar untuk konten yang tidak tumpang-tindih, tetapkan CompositingStrategy.ModulateAlpha. Untuk panggilan gambar individual, terapkan alfa langsung ke perintah gambar (seperti dengan color = Color.Red.copy(alpha = 0.5f)) tanpa membuat lapisan.

Referensi lainnya

Melihat konten