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 dirilis. Kerangka kerja ini juga memungkinkan primitif sinkronisasi untuk diteruskan di antara {i>driver<i} dari {i>kernel<i} ke ruang pengguna dan di antara proses ruang pengguna itu sendiri.
Misalnya, aplikasi dapat mengantrekan pekerjaan yang harus dilakukan di GPU. GPU mulai menggambar gambar tersebut. Meskipun gambar belum dibuat ke dalam memori, pointer buffer diteruskan ke jendela beserta pagar yang menunjukkan kapan pekerjaan GPU akan hingga akhir. {i>Window compositor<i} mulai memproses terlebih dahulu dan meneruskan pekerjaan ke pengontrol tampilan. Dengan cara yang sama, CPU bekerja dilakukan sebelumnya. Setelah GPU selesai, pengontrol tampilan langsung menampilkan gambar.
Framework sinkronisasi juga memungkinkan pengimplementasi memanfaatkan sinkronisasi sumber daya dalam komponen perangkat kerasnya sendiri. Terakhir, memberikan visibilitas ke pipeline grafis untuk membantu proses debug.
Sinkronisasi eksplisit
Sinkronisasi eksplisit memungkinkan produser dan konsumen buffer grafis untuk memberi sinyal ketika mereka selesai menggunakan {i>buffer<i}. Sinkronisasi eksplisit adalah diimplementasikan dalam kernel-space.
Manfaat sinkronisasi eksplisit meliputi:
- Lebih sedikit variasi perilaku antar-perangkat
- Dukungan proses debug yang lebih baik
- Peningkatan metrik pengujian
Framework sinkronisasi memiliki tiga jenis objek:
sync_timeline
sync_pt
sync_fence
linimasa_sinkronisasi
sync_timeline
adalah linimasa yang meningkat secara monoton yang
yang harus diimplementasikan vendor untuk setiap {i>
driver<i}, seperti konteks GL,
pengontrol tampilan, atau blitter 2D. sync_timeline
jumlah
tugas yang dikirimkan ke {i>kernel<i}
untuk perangkat keras tertentu.
sync_timeline
memberikan jaminan tentang urutan operasi
dan memungkinkan implementasi yang spesifik untuk hardware.
Ikuti panduan ini saat menerapkan sync_timeline
:
- Berikan nama yang berguna untuk semua pengemudi, linimasa, dan pembatas untuk menyederhanakan proses debug.
- Mengimplementasikan
timeline_value_str
danpt_value_str
operator dalam linimasa agar output proses debug lebih mudah dibaca. - Implementasikan isian
driver_data
untuk memberikan library userspace, seperti library GL, akses ke data linimasa pribadi, jika diinginkan.data_driver
memungkinkan vendor meneruskan informasi tentang elemen yang tidak dapat diubahsync_fence
dansync_pts
untuk membuat command line berdasarkan rekomendasi tersebut. - Jangan izinkan userspace untuk membuat atau memberi sinyal fence secara eksplisit. Eksplisit menghasilkan sinyal/{i>fence<i} menyebabkan serangan {i>denial-of-service<i} yang menghentikan fungsi pipeline.
- Jangan akses
sync_timeline
,sync_pt
, atausync_fence
secara eksplisit. API menyediakan semua hal yang diperlukan fungsi-fungsi lainnya.
sinkronisasi_pt
sync_pt
adalah nilai atau titik tunggal pada
sync_timeline
. Sebuah titik
memiliki tiga status: aktif, tersinyal, dan error. Titik dimulai dalam status aktif
dan bertransisi ke status sinyal
atau kesalahan. Misalnya, saat gambar
konsumen tidak lagi memerlukan buffer, sync_pt
diberi sinyal
sehingga produser gambar tahu bahwa
menulis ke buffer dapat dilakukan lagi.
sync_fence
sync_fence
adalah kumpulan nilai sync_pt
yang sering
memiliki induk sync_timeline
yang berbeda (seperti untuk layar
pengontrol dan GPU). sync_fence
, sync_pt
, dan
sync_timeline
adalah primitif utama yang dibutuhkan driver dan userspace
gunakan untuk mengkomunikasikan
dependensi mereka. Ketika pagar menjadi sinyal, semua
perintah yang dikeluarkan sebelum fence dijamin lengkap karena
{i>driver<i} {i>kernel<i} atau blok perangkat keras
mengeksekusi perintah secara berurutan.
Framework sinkronisasi memungkinkan beberapa konsumen atau produsen memberi sinyal saat mereka
selesai menggunakan buffer, mengomunikasikan informasi dependensi dengan satu fungsi
. Pagar didukung oleh deskriptor file dan diteruskan dari
{i>kernel<i} ke ruang pengguna. Misalnya, sebuah pagar dapat berisi dua
Nilai sync_pt
yang menandakan bahwa dua konsumen gambar terpisah selesai
untuk membaca {i>buffer.<i} Ketika fence diberi sinyal, produser gambar tahu bahwa baik
dikonsumsi oleh konsumen.
Pagar, seperti nilai sync_pt
, mulai aktif dan mengubah status berdasarkan
status poin mereka. Jika semua nilai sync_pt
menjadi sinyal,
sync_fence
menjadi sinyal. Jika satu sync_pt
jatuh
menjadi error, seluruh sync_fence
akan memiliki status error.
Keanggotaan di sync_fence
tidak dapat diubah setelah fence
dibuat. Untuk mendapatkan lebih dari satu titik
dalam fence, penggabungan adalah
dilakukan di mana titik dari dua pagar yang berbeda
ditambahkan ke pagar ketiga.
Jika salah satu titik itu diberi sinyal
di pagar awal dan yang lainnya tidak,
pagar ketiga juga tidak akan
berada dalam status sinyal.
Untuk menerapkan sinkronisasi eksplisit, sediakan hal berikut:
- Subsistem kernel-space yang mengimplementasikan framework sinkronisasi
untuk {i>driver<i} perangkat
keras tertentu. Pengemudi yang perlu
waspada terhadap pagar
pada umumnya semua hal yang mengakses atau
berkomunikasi dengan {i>Hardware Composer<i}.
File utama meliputi:
- Implementasi inti:
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
- Dokumentasi di
kernel/common/Documentation/sync.txt
- {i>Library<i} untuk berkomunikasi
dengan ruang {i>kernel<i} di
platform/system/core/libsync
- Implementasi inti:
- Vendor harus menyediakan sinkronisasi yang sesuai
fence sebagai parameter untuk
validateDisplay()
dan FungsipresentDisplay()
di HAL. - Dua ekstensi GL terkait fence (
EGL_ANDROID_native_fence_sync
) danEGL_ANDROID_wait_sync
) serta dukungan fence dalam grafis {i>driver<i}.
Studi kasus: Mengimplementasikan driver tampilan
Untuk menggunakan API yang mendukung fungsi sinkronisasi,
mengembangkan driver tampilan yang
memiliki fungsi buffer tampilan. Sebelum
framework sinkronisasi sudah ada, fungsi ini akan menerima dma-buf
objek tersebut, letakkan buffer tersebut di layar, dan blokir 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
lebih kompleks. Saat menampilkan buffer, buffer dikaitkan
dengan fence yang menunjukkan
kapan {i>buffer<i} akan siap. Anda dapat mengantrekan
dan memulai pekerjaan
setelah {i>pagar<i} dibersihkan.
Mengantre dan memulai pekerjaan setelah {i>pagar<i} dibersihkan tidak akan menghambat apa pun. Anda segera mengembalikan fence Anda sendiri, yang menjamin saat buffer akan berada di luar layar. Saat Anda mengantrekan {i>buffer<i}, {i>kernel<i} 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 kerangka kerja sinkronisasi {i>kernel<i} dengan bagian userspace dari kerangka kerja Android dan {i>driver<i} yang harus satu sama lain. Objek ruang {i>kernel<i} direpresentasikan sebagai deskriptor file di {i>userspace<i}.
Konvensi integrasi
Ikuti konvensi antarmuka HAL Android:
- Jika API menyediakan deskriptor file yang merujuk ke
sync_pt
, {i>driver<i} vendor atau HAL yang menggunakan API harus menutup deskriptor file. - Jika {i>driver<i} 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 fence, driver vendor, atau HAL harus menduplikasi deskriptor.
Nama objek fence diganti setiap kali melewati BufferQueue.
Dukungan fence kernel memungkinkan fence memiliki string untuk nama, sehingga sinkronisasi
menggunakan nama jendela dan indeks buffer yang diantrekan untuk diberi nama
pagar, seperti SurfaceView:0
. Ini
sangat membantu dalam {i>debugging<i} untuk mengidentifikasi
sumber {i>deadlock<i} ketika nama muncul
pada output /d/sync
dan laporan bug.
Integrasi ANativeWindow
ANativeWindow mengenali fence. dequeueBuffer
,
queueBuffer
, dan cancelBuffer
memiliki parameter fence.
Integrasi OpenGL ES
Integrasi sinkronisasi OpenGL ES bergantung pada dua ekstensi EGL:
EGL_ANDROID_native_fence_sync
menyediakan cara untuk menggabungkan atau membuat deskriptor file fence Android nativeEGLSyncKHR
objek.EGL_ANDROID_wait_sync
memungkinkan kios sisi GPU bukan sisi CPU, sehingga GPU akan menungguEGLSyncKHR
. Tujuan EkstensiEGL_ANDROID_wait_sync
sama denganEGL_KHR_wait_sync
.
Untuk menggunakan ekstensi ini secara terpisah, terapkan
EGL_ANDROID_native_fence_sync
beserta ekstensi terkait
dukungan {i>kernel<i}. Berikutnya, aktifkan EGL_ANDROID_wait_sync
di {i>driver<i} Anda. EGL_ANDROID_native_fence_sync
ekstensi terdiri dari objek EGLSyncKHR
fence native yang berbeda
. Oleh karena itu, ekstensi yang berlaku untuk EGLSyncKHR
yang sudah ada
jenis objek belum tentu berlaku untuk EGL_ANDROID_native_fence
objek, menghindari interaksi yang tidak diinginkan.
Ekstensi EGL_ANDROID_native_fence_sync
menggunakan native yang sesuai
atribut deskriptor file {i>fence<i} yang hanya
dapat ditetapkan pada waktu pembuatan dan
tidak dapat langsung dikueri dari objek sinkronisasi yang sudah ada. Atribut ini
dapat disetel ke salah satu dari dua mode:
- Deskriptor file fence yang valid menggabungkan native yang ada
Deskriptor file fence Android dalam objek
EGLSyncKHR
. - -1 membuat deskriptor file fence Android native dari
Objek
EGLSyncKHR
.
Gunakan panggilan fungsi DupNativeFenceFD()
untuk mengekstrak
EGLSyncKHR
dari deskriptor file fence Android native.
Ini memiliki hasil yang sama dengan kueri atribut {i>set<i}, tetapi mematuhi
sesuai dengan konvensi bahwa penerima menutup
pagar (oleh karena itu duplikat
operasi). Terakhir, menghancurkan objek EGLSyncKHR
akan menutup
atribut fence internal.
Integrasi Hardware Composer
Hardware Composer menangani tiga jenis fence sinkronisasi:
- Acquire fence diteruskan bersama dengan buffer input untuk
panggilan
setLayerBuffer
dansetClientTarget
. Ini mewakili operasi tulis yang tertunda ke dalam buffer dan harus memberikan sinyal sebelum SurfaceFlinger atau HWC mencoba membaca dari {i>buffer<i} terkait ke melakukan komposisi. - Release fence diambil setelah panggilan ke
presentDisplay
menggunakan panggilangetReleaseFences
. Ini mewakili pembacaan tertunda dari buffer sebelumnya pada lapisan yang sama. J melepaskan sinyal {i>fence <i}saat HWC tidak lagi menggunakan {i>buffer <i}sebelumnya karena {i>buffer<i} saat ini telah menggantikan penyangga sebelumnya pada layar. Pagar rilis diteruskan kembali ke aplikasi bersama dengan buffer sebelumnya yang akan diganti selama komposisi saat ini. Aplikasi harus menunggu sampai melepaskan sinyal {i>fence<i} sebelum menulis konten baru ke dalam {i>buffer<i} yang dikembalikan kepada mereka. - Pagar yang ada ditampilkan, satu per frame, sebagai bagian dari
panggilan ke
presentDisplay
. Pagar yang ada menunjukkan kapan komposisi bingkai ini telah selesai, atau alternatifnya, ketika hasil komposisi frame sebelumnya tidak lagi diperlukan. Untuk fisik menampilkan,presentDisplay
akan menampilkan fence yang ada saat {i>frame <i}saat ini akan muncul di layar. Setelah pagar yang ada dikembalikan, aman untuk menulis ke {i> buffer <i}target SurfaceFlinger lagi, jika berlaku. Untuk tampilan virtual, fence yang ada akan ditampilkan saat aman untuk dibaca dari buffer output.