Kerangka kerja sinkronisasi secara eksplisit menjelaskan dependensi antara berbagai operasi asinkron dalam sistem grafis Android. Kerangka kerja menyediakan API yang memungkinkan komponen untuk menunjukkan kapan buffer dilepaskan. Kerangka kerja ini juga memungkinkan primitif sinkronisasi untuk diteruskan antara driver dari kernel ke ruang pengguna dan antara proses ruang pengguna itu sendiri.
Misalnya, aplikasi mungkin mengantrekan pekerjaan untuk dilakukan di GPU. GPU mulai menggambar gambar itu. Meskipun gambar belum ditarik ke dalam memori, pointer buffer diteruskan ke compositor jendela bersama dengan pagar yang menunjukkan kapan pekerjaan GPU akan selesai. Penggabung jendela mulai memproses sebelumnya dan meneruskan pekerjaan ke pengontrol tampilan. Dengan cara yang sama, pekerjaan CPU dilakukan sebelumnya. Setelah GPU selesai, pengontrol tampilan segera menampilkan gambar.
Kerangka kerja sinkronisasi juga memungkinkan pelaksana memanfaatkan sumber daya sinkronisasi dalam komponen perangkat keras mereka sendiri. Terakhir, framework menyediakan visibilitas ke dalam pipeline grafis untuk membantu proses debug.
Sinkronisasi eksplisit
Sinkronisasi eksplisit memungkinkan produsen dan konsumen buffer grafis untuk memberi sinyal ketika mereka selesai menggunakan buffer. Sinkronisasi eksplisit diimplementasikan di ruang kernel.
Manfaat sinkronisasi eksplisit meliputi:
- Lebih sedikit variasi perilaku antar perangkat
- Dukungan debugging yang lebih baik
- Metrik pengujian yang ditingkatkan
Kerangka kerja sinkronisasi memiliki tiga jenis objek:
-
sync_timeline -
sync_pt -
sync_fence
sync_timeline
sync_timeline adalah garis waktu yang meningkat secara monoton yang harus diterapkan vendor untuk setiap instans driver, seperti konteks GL, pengontrol tampilan, atau blitter 2D. sync_timeline menghitung pekerjaan yang dikirimkan ke kernel untuk perangkat keras tertentu. sync_timeline memberikan jaminan tentang urutan operasi dan memungkinkan implementasi khusus perangkat keras.
Ikuti panduan ini saat menerapkan sync_timeline :
- Berikan nama yang berguna untuk semua driver, garis waktu, dan pagar untuk menyederhanakan proses debug.
- Implementasikan operator
timeline_value_strdanpt_value_strdi timeline untuk membuat hasil debug lebih mudah dibaca. - Terapkan fill
driver_datauntuk memberikan perpustakaan ruang pengguna, seperti perpustakaan GL, akses ke data timeline pribadi, jika diinginkan.data_drivermemungkinkan vendor menyampaikan informasi tentangsync_fencedansync_ptsyang tidak dapat diubah untuk membuat baris perintah berdasarkan mereka. - Jangan izinkan ruang pengguna membuat atau memberi sinyal pagar secara eksplisit. Membuat sinyal/pagar secara eksplisit menghasilkan serangan penolakan layanan yang menghentikan fungsionalitas pipa.
- Jangan mengakses
sync_timeline,sync_pt, atausync_fencesecara eksplisit. API menyediakan semua fungsi yang diperlukan.
sync_pt
sync_pt adalah nilai atau titik tunggal pada sync_timeline . Sebuah titik memiliki tiga status: aktif, bersinyal, dan error. Poin dimulai dalam status aktif dan transisi ke status bersinyal atau kesalahan. Misalnya, ketika konsumen gambar tidak lagi membutuhkan buffer, sync_pt diberi sinyal sehingga produser gambar tahu bahwa tidak apa-apa untuk menulis ke buffer lagi.
sinkronisasi_pagar
sync_fence adalah kumpulan nilai sync_pt yang sering kali memiliki sync_timeline yang berbeda (seperti untuk pengontrol tampilan dan GPU). sync_fence , sync_pt , dan sync_timeline adalah primitif utama yang digunakan driver dan ruang pengguna untuk mengomunikasikan dependensi mereka. Ketika sebuah pagar diberi sinyal, semua perintah yang dikeluarkan sebelum pagar dijamin lengkap karena driver kernel atau blok perangkat keras mengeksekusi perintah secara berurutan.
Kerangka sinkronisasi memungkinkan banyak konsumen atau produsen untuk memberi sinyal ketika mereka selesai menggunakan buffer, mengkomunikasikan informasi ketergantungan dengan satu parameter fungsi. Pagar didukung oleh deskriptor file dan diteruskan dari ruang kernel ke ruang pengguna. Misalnya, sebuah pagar dapat berisi dua nilai sync_pt yang menandakan ketika dua konsumen gambar terpisah selesai membaca buffer. Saat pagar diberi isyarat, produsen gambar tahu bahwa kedua konsumen sudah selesai mengkonsumsi.
Pagar, seperti nilai sync_pt , mulai aktif dan ubah status berdasarkan status poinnya. Jika semua nilai sync_pt menjadi sinyal, sync_fence menjadi sinyal. Jika satu sync_pt mengalami status kesalahan, seluruh sync_fence memiliki status kesalahan.
Keanggotaan dalam sync_fence tidak dapat diubah setelah pagar dibuat. Untuk mendapatkan lebih dari satu titik dalam sebuah pagar, dilakukan penggabungan dimana titik-titik dari dua pagar yang berbeda ditambahkan ke dalam pagar ketiga. Jika salah satu titik tersebut diberi sinyal di pagar asal dan yang lainnya tidak, pagar ketiga juga tidak akan dalam keadaan bersinyal.
Untuk menerapkan sinkronisasi eksplisit, berikan hal berikut:
- Subsistem ruang kernel yang mengimplementasikan kerangka kerja sinkronisasi untuk driver perangkat keras tertentu. Driver yang perlu diwaspadai umumnya adalah segala sesuatu yang mengakses atau berkomunikasi dengan Komposer Perangkat Keras. File kunci termasuk:
- Implementasi inti:
-
kernel/common/include/linux/sync.h -
kernel/common/drivers/base/sync.c
-
- Dokumentasi di
kernel/common/Documentation/sync.txt - Pustaka untuk berkomunikasi dengan ruang kernel di
platform/system/core/libsync
- Implementasi inti:
- Vendor harus menyediakan pagar sinkronisasi yang sesuai sebagai parameter ke
validateDisplay()danpresentDisplay()di HAL. - Dua ekstensi GL terkait pagar (
EGL_ANDROID_native_fence_syncdanEGL_ANDROID_wait_sync) dan dukungan pagar di driver grafis.
Studi kasus: Menerapkan driver tampilan
Untuk menggunakan API yang mendukung fungsi sinkronisasi, kembangkan driver tampilan yang memiliki fungsi buffer tampilan. Sebelum kerangka sinkronisasi ada, fungsi ini akan menerima objek dma-buf , menempatkan buffer tersebut di layar, dan memblokir saat buffer terlihat. Sebagai contoh:
/* * assumes buffer is ready to be displayed. returns when buffer is no longer on * screen. */ void display_buffer(struct dma_buf *buffer);
Dengan kerangka sinkronisasi, fungsi display_buffer menjadi lebih kompleks. Saat meletakkan buffer di layar, buffer dikaitkan dengan pagar yang menunjukkan kapan buffer akan siap. Anda dapat mengantri dan memulai pekerjaan setelah pagar dibersihkan.
Antrian dan memulai pekerjaan setelah pagar dibersihkan tidak menghalangi apa pun. Anda segera mengembalikan pagar Anda sendiri, yang menjamin saat buffer akan mati dari tampilan. Saat Anda mengantri buffer, kernel mencantumkan dependensi dengan kerangka sinkronisasi:
/* * displays buffer when fence is signaled. returns immediately with a fence * that signals when buffer is no longer displayed. */ struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence *fence);
Sinkronkan integrasi
Bagian ini menjelaskan cara mengintegrasikan kerangka sinkronisasi ruang kernel dengan bagian ruang pengguna kerangka kerja Android dan driver yang harus berkomunikasi satu sama lain. Objek ruang kernel direpresentasikan sebagai deskriptor file di ruang pengguna.
Konvensi integrasi
Ikuti konvensi antarmuka Android HAL:
- Jika API menyediakan deskriptor file yang merujuk ke
sync_pt, driver vendor atau HAL yang menggunakan API harus menutup deskriptor file. - Jika driver vendor atau HAL melewati deskriptor file yang berisi
sync_ptke fungsi API, driver vendor atau HAL tidak boleh menutup deskriptor file. - Untuk terus menggunakan deskriptor file pagar, driver vendor atau HAL harus menduplikasi deskriptor.
Objek pagar diganti namanya setiap kali melewati BufferQueue. Dukungan pagar kernel memungkinkan pagar memiliki string untuk nama, sehingga kerangka sinkronisasi menggunakan nama jendela dan indeks buffer yang sedang antri untuk memberi nama pagar, seperti SurfaceView:0 . Ini berguna dalam debugging untuk mengidentifikasi sumber kebuntuan ketika nama-nama muncul di keluaran /d/sync dan laporan bug.
Integrasi ANativeWindow
ANativeWindow sadar akan pagar. dequeueBuffer , queueBuffer , dan cancelBuffer memiliki parameter pagar.
Integrasi OpenGL ES
Integrasi sinkronisasi OpenGL ES bergantung pada dua ekstensi EGL:
-
EGL_ANDROID_native_fence_syncmenyediakan cara untuk membungkus atau membuat deskriptor file pagar Android asli di objekEGLSyncKHR. -
EGL_ANDROID_wait_syncmemungkinkan GPU-side stall daripada CPU-side, membuat GPU menungguEGLSyncKHR. EkstensiEGL_ANDROID_wait_syncsama dengan ekstensiEGL_KHR_wait_sync.
Untuk menggunakan ekstensi ini secara independen, terapkan ekstensi EGL_ANDROID_native_fence_sync bersama dengan dukungan kernel terkait. Selanjutnya, aktifkan ekstensi EGL_ANDROID_wait_sync di driver Anda. Ekstensi EGL_ANDROID_native_fence_sync terdiri dari tipe objek EGLSyncKHR pagar asli yang berbeda. Akibatnya, ekstensi yang berlaku untuk jenis objek EGLSyncKHR yang ada tidak selalu berlaku untuk objek EGL_ANDROID_native_fence , menghindari interaksi yang tidak diinginkan.
Ekstensi EGL_ANDROID_native_fence_sync menggunakan atribut deskriptor file pagar asli yang sesuai yang dapat disetel hanya pada waktu pembuatan dan tidak dapat langsung ditanyakan dari objek sinkronisasi yang ada. Atribut ini dapat diatur ke salah satu dari dua mode:
- Deskriptor file pagar yang valid membungkus deskriptor file pagar Android asli yang ada dalam objek
EGLSyncKHR. - -1 membuat deskriptor file pagar Android asli dari objek
EGLSyncKHR.
Gunakan panggilan fungsi DupNativeFenceFD() untuk mengekstrak objek EGLSyncKHR dari deskriptor file pagar Android asli. Ini memiliki hasil yang sama dengan menanyakan atribut set, tetapi mematuhi konvensi bahwa penerima menutup pagar (karenanya operasi duplikat). Terakhir, menghancurkan objek EGLSyncKHR akan menutup atribut pagar internal.
Integrasi Komposer Perangkat Keras
Komposer Perangkat Keras menangani tiga jenis pagar sinkronisasi:
- Pagar akuisisi diteruskan bersama dengan buffer input ke panggilan
setLayerBufferdansetClientTarget. Ini mewakili penulisan yang tertunda ke buffer dan harus memberi sinyal sebelum SurfaceFlinger atau HWC mencoba membaca dari buffer terkait untuk melakukan komposisi. - Pagar rilis diambil setelah panggilan ke
presentDisplaymenggunakan panggilangetReleaseFences. Ini mewakili pembacaan tertunda dari buffer sebelumnya pada lapisan yang sama. Pagar pelepas memberi sinyal saat HWC tidak lagi menggunakan buffer sebelumnya karena buffer saat ini telah menggantikan buffer sebelumnya pada tampilan. Pagar rilis diteruskan kembali ke aplikasi bersama dengan buffer sebelumnya yang akan diganti selama komposisi saat ini. Aplikasi harus menunggu hingga sinyal pagar rilis sebelum menulis konten baru ke dalam buffer yang dikembalikan kepada mereka. - Pagar saat ini dikembalikan, satu per bingkai, sebagai bagian dari panggilan ke
presentDisplay. Pagar masa kini merepresentasikan bila komposisi rangka ini telah selesai, atau bergantian, bila hasil komposisi rangka sebelumnya tidak diperlukan lagi. Untuk tampilan fisik,presentDisplaymengembalikan pagar saat ini ketika bingkai saat ini muncul di layar. Setelah pagar yang ada dikembalikan, aman untuk menulis ke buffer target SurfaceFlinger lagi, jika berlaku. Untuk tampilan virtual, pagar saat ini dikembalikan saat aman untuk dibaca dari buffer output.