Framework sinkronisasi secara eksplisit menjelaskan dependensi antara berbagai operasi asinkron dalam sistem grafis Android. Framework menyediakan API yang memungkinkan komponen menunjukkan kapan buffer dilepaskan. Framework ini juga memungkinkan primitif sinkronisasi diteruskan antar-driver dari kernel ke ruang pengguna dan antar-proses ruang pengguna itu sendiri.
Misalnya, aplikasi dapat mengantrekan tugas yang akan dilakukan di GPU. GPU mulai menggambar gambar tersebut. Meskipun gambar belum digambar ke dalam memori, pointer buffer diteruskan ke komposer jendela bersama dengan penghalang yang menunjukkan kapan pekerjaan GPU akan selesai. Kompositor jendela mulai memproses lebih awal dan meneruskan pekerjaan ke pengontrol layar. Dengan cara yang serupa, tugas CPU dilakukan lebih awal. Setelah GPU selesai, pengontrol layar akan langsung menampilkan gambar.
Framework sinkronisasi juga memungkinkan penerap memanfaatkan resource sinkronisasi dalam komponen hardware mereka sendiri. Terakhir, framework ini memberikan visibilitas ke dalam pipeline grafis untuk membantu proses penelusuran bug.
Sinkronisasi eksplisit
Sinkronisasi eksplisit memungkinkan produsen dan konsumen buffer grafis untuk memberi sinyal saat mereka selesai menggunakan buffer. Sinkronisasi eksplisit diimplementasikan di ruang kernel.
Manfaat sinkronisasi eksplisit meliputi:
- Lebih sedikit variasi perilaku antarperangkat
- Dukungan proses debug yang lebih baik
- Metrik pengujian yang ditingkatkan
Framework sinkronisasi memiliki tiga jenis objek:
sync_timeline
sync_pt
sync_fence
sync_timeline
sync_timeline
adalah linimasa yang meningkat secara monoton yang harus diterapkan vendor untuk setiap instance driver, seperti konteks GL, pengontrol layar, atau blitter 2D. sync_timeline
menghitung
tugas yang dikirimkan ke kernel untuk hardware tertentu.
sync_timeline
memberikan jaminan tentang urutan operasi
dan memungkinkan implementasi khusus hardware.
Ikuti panduan berikut saat menerapkan sync_timeline
:
- Berikan nama yang berguna untuk semua driver, linimasa, dan batas untuk menyederhanakan pen-debug-an.
- Terapkan operator
timeline_value_str
danpt_value_str
di linimasa untuk membuat output proses debug lebih mudah dibaca. - Terapkan pengisian
driver_data
untuk memberikan akses ke data linimasa pribadi kepada library ruang pengguna, seperti library GL, jika diinginkan.data_driver
memungkinkan vendor meneruskan informasi tentangsync_fence
dansync_pts
yang tidak dapat diubah untuk membuat command line berdasarkan informasi tersebut. - Jangan izinkan userspace membuat atau memberi sinyal pagar secara eksplisit. Membuat sinyal/penghalang secara eksplisit akan menyebabkan serangan penolakan layanan yang menghentikan fungsi pipeline.
- Jangan mengakses elemen
sync_timeline
,sync_pt
, atausync_fence
secara eksplisit. API ini menyediakan semua fungsi yang diperlukan.
sync_pt
sync_pt
adalah nilai atau titik tunggal pada
sync_timeline
. Titik memiliki tiga status: aktif, diberi sinyal, dan error. Titik dimulai dalam status aktif
dan bertransisi ke status yang diberi sinyal atau error. Misalnya, saat konsumen gambar tidak lagi memerlukan buffer, sync_pt
akan diberi sinyal
sehingga produsen gambar tahu bahwa ia boleh menulis ke dalam buffer lagi.
sync_fence
sync_fence
adalah kumpulan nilai sync_pt
yang sering kali memiliki induk sync_timeline
yang berbeda (seperti untuk pengontrol layar dan GPU). sync_fence
, sync_pt
, dan
sync_timeline
adalah primitif utama yang digunakan driver dan userspace
untuk mengomunikasikan dependensinya. Saat pagar diberi sinyal, semua perintah yang dikeluarkan sebelum pagar dijamin selesai karena driver kernel atau blok hardware menjalankan perintah secara berurutan.
Framework sinkronisasi memungkinkan beberapa konsumen atau produsen memberi sinyal saat mereka selesai menggunakan buffer, dengan mengomunikasikan informasi dependensi dengan satu parameter fungsi. Fence didukung oleh deskriptor file dan diteruskan dari
ruang kernel ke ruang pengguna. Misalnya, pagar dapat berisi dua nilai
sync_pt
yang menandakan kapan dua konsumen gambar yang terpisah selesai
membaca buffer. Saat pagar diberi sinyal, produsen gambar mengetahui bahwa kedua konsumen telah selesai menggunakan.
Pagar, seperti nilai sync_pt
, mulai aktif dan mengubah status berdasarkan status titiknya. Jika semua nilai sync_pt
diberi sinyal, sync_fence
akan diberi sinyal. Jika satu sync_pt
mengalami
status error, seluruh sync_fence
akan mengalami status error.
Keanggotaan dalam sync_fence
tidak dapat diubah setelah pagar
dibuat. Untuk mendapatkan lebih dari satu titik dalam pagar, penggabungan dilakukan dengan menambahkan titik dari dua pagar yang berbeda ke pagar ketiga.
Jika salah satu titik tersebut diberi sinyal di pagar asal dan yang lainnya tidak,
pagar ketiga juga tidak akan diberi sinyal.
Untuk menerapkan sinkronisasi eksplisit, berikan hal berikut:
- Subsistem ruang kernel yang menerapkan framework sinkronisasi
untuk driver hardware tertentu. Driver yang perlu mengetahui batas umumnya adalah apa pun yang mengakses atau berkomunikasi dengan Hardware Composer.
File utama meliputi:
- Penerapan inti:
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
- Dokumentasi di
kernel/common/Documentation/sync.txt
- Library untuk berkomunikasi dengan ruang kernel di
platform/system/core/libsync
- Penerapan inti:
- Vendor harus menyediakan pagar sinkronisasi yang sesuai sebagai parameter ke fungsi
validateDisplay()
danpresentDisplay()
di HAL. - Dua ekstensi GL terkait pagar (
EGL_ANDROID_native_fence_sync
danEGL_ANDROID_wait_sync
) serta 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 framework sinkronisasi ada, fungsi ini akan menerima objek dma-buf
, menempatkan buffer tersebut di layar, dan memblokir saat buffer terlihat. Contoh:
/* * assumes buffer is ready to be displayed. returns when buffer is no longer on * screen. */ void display_buffer(struct dma_buf *buffer);
Dengan framework sinkronisasi, fungsi display_buffer
menjadi lebih kompleks. Saat menampilkan buffer, buffer dikaitkan dengan pagar yang menunjukkan kapan buffer akan siap. Anda dapat mengantrekan
dan memulai tugas setelah pagar dibersihkan.
Mengantrekan dan memulai pekerjaan setelah pagar dibersihkan tidak akan memblokir apa pun. Anda segera mengembalikan pagar Anda sendiri, yang menjamin kapan buffer akan keluar dari layar. Saat Anda mengantrekan buffer, kernel akan mencantumkan dependensi dengan framework 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);
Integrasi sinkronisasi
Bagian ini menjelaskan cara mengintegrasikan framework sinkronisasi ruang kernel dengan bagian ruang pengguna framework Android dan driver yang harus berkomunikasi satu sama lain. Objek ruang kernel direpresentasikan sebagai deskriptor file di ruang pengguna.
Konvensi integrasi
Ikuti konvensi antarmuka HAL Android:
- 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 meneruskan 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 penghalang kernel memungkinkan penghalang memiliki string untuk nama, sehingga framework sinkronisasi menggunakan nama jendela dan indeks buffer yang sedang diantrekan untuk memberi nama penghalang, seperti SurfaceView:0
. Hal ini
berguna dalam proses debug untuk mengidentifikasi sumber kebuntuan karena nama muncul
dalam output /d/sync
dan laporan bug.
Integrasi ANativeWindow
ANativeWindow mendukung penghalang. dequeueBuffer
,
queueBuffer
, dan cancelBuffer
memiliki parameter pagar.
Integrasi OpenGL ES
Integrasi sinkronisasi OpenGL ES mengandalkan dua ekstensi EGL:
EGL_ANDROID_native_fence_sync
menyediakan cara untuk membungkus atau membuat deskriptor file pagar Android native dalam objekEGLSyncKHR
.EGL_ANDROID_wait_sync
memungkinkan jeda sisi GPU, bukan sisi CPU, sehingga GPU menungguEGLSyncKHR
. EkstensiEGL_ANDROID_wait_sync
sama dengan ekstensiEGL_KHR_wait_sync
.
Untuk menggunakan ekstensi ini secara terpisah, 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 jenis objek EGLSyncKHR
pagar native yang berbeda. Akibatnya, ekstensi yang berlaku untuk jenis objek EGLSyncKHR
yang ada tidak selalu berlaku untuk objek EGL_ANDROID_native_fence
, sehingga menghindari interaksi yang tidak diinginkan.
Ekstensi EGL_ANDROID_native_fence_sync
menggunakan atribut deskriptor file native yang sesuai yang hanya dapat ditetapkan pada waktu pembuatan dan tidak dapat dikueri secara langsung dari objek sinkronisasi yang ada. Atribut ini
dapat ditetapkan ke salah satu dari dua mode:
- Deskriptor file pagar yang valid membungkus deskriptor file pagar Android native yang ada dalam objek
EGLSyncKHR
. - -1 membuat deskriptor file pagar Android native dari objek
EGLSyncKHR
.
Gunakan panggilan fungsi DupNativeFenceFD()
untuk mengekstrak objek
EGLSyncKHR
dari deskriptor file pagar Android native.
Hal ini memiliki hasil yang sama dengan membuat kueri atribut setel, tetapi mematuhi
konvensi bahwa penerima menutup batas (sehingga operasi duplikat). Terakhir, menghancurkan objek EGLSyncKHR
akan menutup atribut batas internal.
Integrasi Hardware Composer
Hardware Composer menangani tiga jenis pagar sinkronisasi:
- Acquire fences diteruskan bersama dengan buffer input ke
panggilan
setLayerBuffer
dansetClientTarget
. Ini mewakili penulisan yang tertunda ke dalam buffer dan harus memberi sinyal sebelum SurfaceFlinger atau HWC mencoba membaca dari buffer terkait untuk melakukan komposisi. - Release fence diambil setelah panggilan ke
presentDisplay
menggunakan panggilangetReleaseFences
. Ini mewakili pembacaan tertunda dari buffer sebelumnya pada lapisan yang sama. Penghalang pelepasan memberi sinyal saat HWC tidak lagi menggunakan buffer sebelumnya karena buffer saat ini telah menggantikan buffer sebelumnya di layar. Penghalang pelepasan dikirim kembali ke aplikasi bersama dengan buffer sebelumnya yang akan diganti selama komposisi saat ini. Aplikasi harus menunggu hingga sinyal penghalang rilis sebelum menulis konten baru ke dalam buffer yang dikembalikan kepadanya. - Present fences ditampilkan, satu per frame, sebagai bagian dari
panggilan ke
presentDisplay
. Penghalang present menunjukkan kapan komposisi frame ini telah selesai, atau sebagai alternatif, kapan hasil komposisi frame sebelumnya tidak lagi diperlukan. Untuk tampilan fisik,presentDisplay
menampilkan pagar yang ada saat frame saat ini muncul di layar. Setelah pagar yang ada ditampilkan, Anda dapat menulis ke buffer target SurfaceFlinger lagi dengan aman, jika berlaku. Untuk tampilan virtual, pagar present ditampilkan saat aman untuk dibaca dari buffer output.