Senkronizasyon çerçevesi

Senkronizasyon çerçevesi, Android grafik sistemindeki farklı asenkron işlemler arasındaki bağımlılıkları açıkça tanımlar. Çerçeve, bileşenlerin tamponların ne zaman serbest bırakıldığını belirtmesine olanak tanıyan bir API sağlar. Çerçeve, senkronizasyon primitiflerinin çekirdekten kullanıcı alanına ve kullanıcı alanı süreçleri arasında iletilmesine de olanak tanır.

Örneğin, bir uygulama GPU'da gerçekleştirilecek işleri sıraya alabilir. GPU bu resmi çizmeye başlar. Görüntü henüz belleğe çizilmemiş olsa da arabellek işaretçisi, GPU çalışmasının ne zaman biteceğini belirten bir çitle birlikte pencere derleyiciye iletilir. Pencere birleştirici, işlemeyi önceden başlar ve işi ekran denetleyicisine iletir. Benzer şekilde, CPU çalışması da önceden yapılır. GPU işlem bittikten sonra ekran denetleyicisi resmi hemen gösterir.

Senkronizasyon çerçevesi, uygulayıcıların kendi donanım bileşenlerindeki senkronizasyon kaynaklarından da yararlanmasına olanak tanır. Son olarak, çerçeve, hata ayıklama işlemine yardımcı olmak için grafik ardışık düzenine görünürlük sağlar.

Açık senkronizasyon

Açık senkronizasyon, grafik arabelleklerinin üreticilerinin ve tüketicilerinin bir arabelleği kullanmayı bitirdiklerinde sinyal göndermelerini sağlar. Açık senkronizasyon, çekirdek alanında uygulanır.

Belirli bir zamana göre senkronizasyonun avantajları şunlardır:

  • Cihazlar arasında daha az davranış varyasyonu
  • Daha iyi hata ayıklama desteği
  • İyileştirilmiş test metrikleri

Senkronizasyon çerçevesi üç nesne türüne sahiptir:

  • sync_timeline
  • sync_pt
  • sync_fence

senkronizasyon_zaman çizelgesi

sync_timeline, tedarikçi firmaların GL bağlamı, ekran denetleyici veya 2D blitter gibi her sürücü örneği için uygulaması gereken monoton olarak artan bir zaman çizelgesidir. sync_timeline, belirli bir donanım parçası için çekirdeğe gönderilen işlerin sayısını belirtir. sync_timeline, işlemlerin sırası hakkında garantiler sağlar ve donanıma özel uygulamaları etkinleştirir.

sync_timeline'ü uygularken aşağıdaki yönergeleri izleyin:

  • Hata ayıklamayı kolaylaştırmak için tüm sürücüler, zaman çizelgeleri ve çitler için faydalı adlar sağlayın.
  • Hata ayıklama çıktısını daha okunabilir hale getirmek için zaman çizelgesinde timeline_value_str ve pt_value_str operatörlerini uygulayın.
  • İsterseniz GL kitaplığı gibi kullanıcı alanı kitaplıklarına gizli zaman çizelgesi verilerine erişim izni vermek için dolgu driver_data uygulayın. data_driver, tedarikçilerin sabit sync_fence ve sync_pts ile ilgili bilgileri ileterek bu bilgilere dayalı komut satırları derlemesine olanak tanır.
  • Kullanıcı alanının açıkça çit oluşturmasına veya sinyal göndermesine izin vermeyin. Açıkça sinyal/çit oluşturmak, ardışık düzen işlevini durduran hizmet reddi saldırısına neden olur.
  • sync_timeline, sync_pt veya sync_fence öğelerine açıkça erişmeyin. API, gerekli tüm işlevleri sağlar.

sync_pt

sync_pt, sync_timeline üzerinde tek bir değer veya noktadır. Noktaların üç durumu vardır: etkin, sinyal verilmiş ve hata. Noktalar etkin durumda başlar ve sinyal veya hata durumlarında geçiş yapar. Örneğin, bir resim tüketicisinin artık arabelleğe ihtiyacı olmadığında sync_pt sinyali gönderilir. Böylece resim üretici, arabelleğe tekrar yazmanın uygun olduğunu bilir.

sync_fence

sync_fence, genellikle farklı sync_timeline üst öğelere sahip sync_pt değerlerinin bir koleksiyonudur (ör. ekran denetleyici ve GPU). sync_fence, sync_pt ve sync_timeline, sürücülerin ve kullanıcı alanının bağımlılıklarını bildirmek için kullandığı temel primitiflerdir. Bir çit sinyali aldığında, çekirdek sürücüsü veya donanım bloğu komutları sırayla yürüttüğü için çitten önce verilen tüm komutların tamamlanacağı garanti edilir.

Senkronizasyon çerçevesi, birden fazla tüketicinin veya üreticinin bir arabellek kullanarak işlerini bitirdiğinde sinyal göndermesine olanak tanır. Bu sayede, bağımlılık bilgileri tek bir işlev parametresi ile iletilir. Çitler bir dosya tanımlayıcısıyla desteklenir ve çekirdek alanından kullanıcı alanına aktarılır. Örneğin, bir çit, iki ayrı resim tüketicisinin bir arabelleği okumayı ne zaman bitirdiğini belirten iki sync_pt değeri içerebilir. Çit sinyali verildiğinde, görüntü üreticileri her iki tüketicinin de tüketimi tamamladığını bilir.

sync_pt değerleri gibi çitler etkin olarak başlar ve noktalarının durumuna göre durum değiştirir. Tüm sync_pt değerleri sinyalle gönderilirse sync_fence sinyalle gönderilir. Bir sync_pt hata durumuna girerse sync_fence'un tamamı hata durumuna girer.

Çit oluşturulduktan sonra sync_fence üyeliği değiştirilemez. Bir çitte birden fazla nokta elde etmek için iki farklı çitten gelen noktaların üçüncü bir çite eklendiği bir birleştirme işlemi gerçekleştirilir. Bu noktalardan biri kaynak çitte sinyalle gönderilmişse ve diğeri gönderilmemişse üçüncü çit de sinyalle gönderilmiş durumda olmaz.

Açık senkronizasyon yapmak için aşağıdakileri sağlayın:

  • Belirli bir donanım sürücüsü için senkronizasyon çerçevesini uygulayan çekirdek alanı alt sistemidir. Çit farkında olması gereken sürücüler genellikle Donanım Oluşturucu'ya erişen veya Donanım Oluşturucu ile iletişim kuran her şeydir. Önemli dosyalar şunlardır:
    • Temel uygulama:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt adresindeki dokümanlar
    • platform/system/core/libsync alanındaki çekirdek alanıyla iletişim kurmak için kullanılan kitaplık
  • Tedarikçi firma, HAL'deki validateDisplay() ve presentDisplay() işlevlerine parametre olarak uygun senkronizasyon çitlerini sağlamalıdır.
  • Çitle ilgili iki GL uzantısı (EGL_ANDROID_native_fence_sync ve EGL_ANDROID_wait_sync) ve grafik sürücüsünde çit desteği.

Örnek olay: Görüntü sürücüsü uygulama

Senkronizasyon işlevini destekleyen API'yi kullanmak için ekran arabelleği işlevi olan bir ekran sürücüsü geliştirin. Senkronizasyon çerçevesi mevcut olmadan önce bu işlev dma-buf nesne alır, bu arabellekleri ekrana yerleştirir ve arabellek görünür durumdayken blok yapar. Örneğin:

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

Senkronizasyon çerçevesiyle display_buffer işlevi daha karmaşıktır. Tampon ekrana yerleştirilirken tamponun ne zaman hazır olacağını belirten bir çitle ilişkilendirilir. Çitler ortadan kalktıktan sonra işleri sıraya sokabilir ve işe başlayabilirsiniz.

Çit temizlendikten sonra iş sıraya eklenip başlatılırsa hiçbir şey engellenmez. Hemen kendi çitinizi iade edersiniz. Bu sayede, arabelleğin ekrandan ne zaman kaldırılacağını garanti edersiniz. Arabellekleri sıraya eklediğinizde çekirdek, senkronizasyon çerçevesiyle olan bağımlılıkları listeler:

/*
 * 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);

Senkronizasyon entegrasyonu

Bu bölümde, çekirdek alanı senkronizasyon çerçevesinin Android çerçevesinin kullanıcı alanı bölümleriyle ve birbirleriyle iletişim kurması gereken sürücülerle nasıl entegre edileceği açıklanmaktadır. Çekirdek alanındaki nesneler, kullanıcı alanında dosya tanımlayıcıları olarak temsil edilir.

Entegrasyon kuralları

Android HAL arayüzü kurallarına uyun:

  • API, bir sync_pt öğesine referans veren dosya açıklayıcısı sağlıyorsa tedarikçi firmanın sürücüsü veya API'yi kullanan HAL, dosya açıklayıcıyı kapatmalıdır.
  • Tedarikçi firma sürücüsü veya HAL, bir API işlevine sync_pt içeren bir dosya açıklayıcısı iletirse tedarikçi firma sürücüsü veya HAL, dosya açıklayıcıyı kapatmamalıdır.
  • Çit dosya tanımlayıcısını kullanmaya devam etmek için tedarikçi sürücü veya HAL, tanımlayıcıyı kopyalamalıdır.

Çit nesnesi, BufferQueue'dan her geçtiğinde yeniden adlandırılır. Çekirdek çit desteği, çitlerin ad olarak dize kullanmasına olanak tanır. Bu nedenle senkronizasyon çerçevesi, çiti adlandırmak için sıraya eklenen pencere adını ve arabellek dizesini (ör. SurfaceView:0) kullanır. Adlar /d/sync ve hata raporlarının çıktısında göründüğü için bu, kilitlenmenin kaynağını belirlemek için hata ayıklamada faydalıdır.

ANativeWindow entegrasyonu

ANativeWindow her şeye duyarlıdır. dequeueBuffer, queueBuffer ve cancelBuffer çit parametrelerine sahiptir.

OpenGL ES entegrasyonu

OpenGL ES senkronizasyon entegrasyonu iki EGL uzantısına dayanır:

  • EGL_ANDROID_native_fence_sync, EGLSyncKHR nesnelerinde yerel Android çit dosya tanımlayıcılarını sarmalama veya oluşturma yöntemi sağlar.
  • EGL_ANDROID_wait_sync, CPU tarafında değil GPU tarafında duraklamalar yapılmasına izin verir ve GPU'nun EGLSyncKHR için beklemesini sağlar. EGL_ANDROID_wait_sync uzantısı, EGL_KHR_wait_sync uzantısıyla aynıdır.

Bu uzantıları bağımsız olarak kullanmak için EGL_ANDROID_native_fence_sync uzantısını ilişkili çekirdek desteğiyle birlikte uygulayın. Ardından, sürücünüzde EGL_ANDROID_wait_sync uzantı etkinleştirin. EGL_ANDROID_native_fence_sync uzantısı, ayrı bir yerel çit EGLSyncKHR nesne türünden oluşur. Sonuç olarak, mevcut EGLSyncKHR nesne türleri için geçerli olan uzantılar, istenmeyen etkileşimlerden kaçınarak EGL_ANDROID_native_fence nesneleri için geçerli olmayabilir.

EGL_ANDROID_native_fence_sync uzantısı, yalnızca oluşturma zamanında ayarlanabilen ve mevcut bir senkronizasyon nesnesinden doğrudan sorgulanamayan karşılık gelen bir yerel çit dosyası tanımlayıcı özelliği kullanır. Bu özellik iki moddan birine ayarlanabilir:

  • Geçerli bir çit dosyası tanımlayıcısı, mevcut bir yerel Android çit dosyası tanımlayıcısını bir EGLSyncKHR nesnesine sarar.
  • -1, EGLSyncKHR nesnesinden yerel bir Android çit dosya tanımlayıcısı oluşturur.

Yerel Android fence dosyası tanımlayıcısından EGLSyncKHR nesnesini ayıklamak için DupNativeFenceFD() işlev çağrısını kullanın. Bu işlem, set özelliğini sorgulamakla aynı sonucu verir ancak alıcının çiti kapatması (bu nedenle kopyalama işlemi) kuralı geçerlidir. Son olarak, EGLSyncKHR nesnesi yok edildiğinde dahili çit özelliği kapatılır.

Donanım Oluşturucu entegrasyonu

Donanım Derleyici üç tür senkronizasyon çiti işler:

  • Sınır edinme, giriş arabellekleriyle birlikte setLayerBuffer ve setClientTarget çağrılarına iletilir. Bunlar, arabelleğe bekleyen bir yazma işlemini temsil eder ve SurfaceFlinger veya HWC, derleme yapmak için ilişkili arabellekten okumaya çalışmadan önce sinyal vermelidir.
  • Serbest bırakma çitleri, getReleaseFences çağrısı kullanılarak presentDisplay çağrısından sonra alınır. Bunlar, aynı katmandaki önceki arabellekten bekleyen bir okuma işlemini temsil eder. Mevcut arabellek ekrandaki önceki arabelleğin yerini aldığı için HWC artık önceki arabelleği kullanmıyorsa serbest bırakma çiti sinyalleri gönderilir. Yayın parmaklıkları, geçerli beste sırasında değiştirilecek önceki arabelleklerle birlikte uygulamaya geri gönderilir. Uygulama, kendisine döndürülen arabelleğe yeni içerikler yazmadan önce bir yayın çiti sinyali almayı beklemelidir.
  • presentDisplay çağrısının parçası olarak, gösterme çitleri kare başına bir tane olacak şekilde döndürülür. Mevcut çitler, bu karenin derlemesinin tamamlandığını veya alternatif olarak önceki karenin derleme sonucuna artık ihtiyaç duyulmadığını gösterir. Fiziksel ekranlarda presentDisplay, geçerli kare ekranda göründüğünde mevcut çitleri döndürür. Mevcut çitler döndürüldükten sonra, geçerliyse SurfaceFlinger hedef arabelleğine tekrar yazmak güvenlidir. Sanal ekranlarda, çıkış arabelleğinden okumanın güvenli olduğu durumlarda mevcut çitler döndürülür.