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_str
danpt_value_str
di timeline untuk membuat hasil debug lebih mudah dibaca. - Terapkan fill
driver_data
untuk memberikan perpustakaan ruang pengguna, seperti perpustakaan GL, akses ke data timeline pribadi, jika diinginkan.data_driver
memungkinkan vendor menyampaikan informasi tentangsync_fence
dansync_pts
yang 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_fence
secara 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_sync
danEGL_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_pt
ke 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_sync
menyediakan cara untuk membungkus atau membuat deskriptor file pagar Android asli di objekEGLSyncKHR
. -
EGL_ANDROID_wait_sync
memungkinkan GPU-side stall daripada CPU-side, membuat GPU menungguEGLSyncKHR
. EkstensiEGL_ANDROID_wait_sync
sama 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
setLayerBuffer
dansetClientTarget
. 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
presentDisplay
menggunakan 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,presentDisplay
mengembalikan 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.