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 arabelleklerin ne zaman serbest bırakıldığını belirtmesini sağlayan bir API sunar. Çerçeve, senkronizasyon temel öğelerinin çekirdekten kullanıcı alanına ve kullanıcı alanı işlemleri arasında sürücüler arasında geçirilmesine de olanak tanır.

Örneğin, bir uygulama GPU'da yapılacak işleri sıraya alabilir. GPU, bu görüntüyü çizmeye başlar. Resim henüz belleğe çizilmemiş olsa da arabellek işaretçisi, GPU çalışmasının ne zaman tamamlanacağını belirten bir çitle birlikte pencere birleştiricisine iletilir. Pencere birleştirici, işlemeye önceden başlar ve işi ekran denetleyicisine aktarır. Benzer şekilde, CPU çalışması önceden yapılır. GPU işlemi tamamladığında ekran denetleyicisi görüntüyü hemen gösterir.

Senkronizasyon çerçevesi, uygulayıcıların kendi donanım bileşenlerinde senkronizasyon kaynaklarından yararlanmasına da olanak tanır. Son olarak, çerçeve, hata ayıklamaya yardımcı olmak için grafik işlem hattı hakkında 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 vermesini sağlar. Açık senkronizasyon, çekirdek alanında uygulanır.

Açık senkronizasyonun avantajları şunlardır:

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

Senkronizasyon çerçevesinde üç nesne türü vardır:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline, satıcıların her sürücü örneği (ör. GL bağlamı, ekran denetleyicisi veya 2D blitter) için uygulaması gereken, tekdüze şekilde artan bir zaman çizelgesidir. sync_timeline Belirli bir donanım parçası için çekirdeğe gönderilen işlerin sayısı. sync_timeline, işlemlerin sırası hakkında garantiler sunar ve donanıma özel uygulamaları etkinleştirir.

sync_timeline işaretlemesini uygularken aşağıdaki yönergeleri izleyin:

  • Hata ayıklamayı kolaylaştırmak için tüm sürücülere, zaman çizelgelerine ve sınırlara yararlı adlar verin.
  • Hata ayıklama çıkışını daha okunabilir hale getirmek için zaman çizelgelerinde timeline_value_str ve pt_value_str operatörlerini uygulayın.
  • İstenirse kullanıcı alanı kitaplıklarının (ör. GL kitaplığı) özel zaman çizelgesi verilerine erişmesini sağlamak için doldurma driver_data işlevini uygulayın. data_driver, satıcıların değişmez sync_fence ve sync_pts hakkında bilgi iletmesine olanak tanır. Böylece, bu bilgilere dayalı komut satırları oluşturulabilir.
  • Kullanıcı alanının açıkça bir çit oluşturmasına veya sinyal vermesine izin vermeyin. Açıkça sinyal/çit oluşturmak, işlem hattı işlevselliğini durduran bir hizmet reddi saldırısına neden olur.
  • sync_timeline, sync_pt veya sync_fence öğelerine doğrudan erişmeyin. API, gerekli tüm işlevleri sağlar.

sync_pt

sync_pt, sync_timeline üzerinde tek bir değer veya noktadır. Bir noktanın üç durumu vardır: etkin, sinyal verilmiş ve hata. Puanlar etkin durumda başlar ve sinyal verilen veya hata durumlarına geçer. Örneğin, bir resim tüketicisinin artık arabelleğe ihtiyacı kalmadığında sync_pt sinyali verilir. Böylece resim üreticisi, arabelleğe tekrar yazmanın sorun olmayacağını anlar.

sync_fence

sync_fence, genellikle farklı sync_timeline üst öğelere (ör. ekran denetleyicisi ve GPU) sahip olan sync_pt değerlerinden oluşan bir koleksiyondur. 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 öğelerdir. Bir bariyer sinyal verdiğinde, çekirdek sürücüsü veya donanım bloğu komutları sırayla yürüttüğünden bariyerden önce verilen tüm komutların tamamlanacağı garanti edilir.

Senkronizasyon çerçevesi, birden fazla tüketicinin veya üreticinin bir arabellek kullanmayı bitirdiklerinde sinyal vermesine olanak tanır ve bağımlılık bilgilerini tek bir işlev parametresiyle iletir. Çitler, dosya tanımlayıcısı tarafından desteklenir ve çekirdek alanından kullanıcı alanına geçirilir. Örneğin, bir çit, iki ayrı görüntü tüketicisi bir arabelleği okumayı bitirdiğinde bunu belirten iki sync_pt değeri içerebilir. Sınır işaretlendiğinde, görüntü üreticiler her iki tüketicinin de tüketimi tamamladığını bilir.

sync_pt değerleri gibi çitler etkin olarak başlar ve durumlarını noktalarının durumuna göre değiştirir. Tüm sync_pt değerleri sinyalli hâle gelirse sync_fence sinyalli hâle gelir. Bir sync_pt hata durumuna düşerse tüm sync_fence hata durumuna düşer.

Ç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 yapılır. Bu noktalardan biri başlangıç çitinde işaretlenmişse ve diğeri işaretlenmemişse üçüncü çit de işaretlenmiş durumda olmaz.

Açık senkronizasyonu uygulamak için aşağıdakileri sağlayın:

  • Belirli bir donanım sürücüsü için senkronizasyon çerçevesini uygulayan bir çekirdek alanı alt sistemi. Çit farkında olması gereken sürücüler genellikle Donanım Birleştirici'ye erişen veya onunla iletişim kuran her şeydir. Başlıca dosyalar:
    • Temel uygulama:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt adresindeki belgeler
    • platform/system/core/libsync içinde çekirdek alanı ile iletişim kurmak için kullanılan kitaplık
  • Tedarikçi, HAL'deki validateDisplay() ve presentDisplay() işlevlerine parametre olarak uygun senkronizasyon çitlerini sağlamalıdır.
  • İki çitle ilgili 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: Ekran sürücüsü uygulama

Senkronizasyon işlevini destekleyen API'yi kullanmak için görüntü arabelleği işlevi olan bir ekran sürücüsü geliştirin. Senkronizasyon çerçevesi oluşturulmadan önce bu işlev, dma-buf nesneleri alır, bu arabellekleri ekrana yerleştirir ve arabellek görünürken engellerdi. Ö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. Bir arabellek ekrana yerleştirilirken arabellek, hazır olma zamanını belirten bir çitle ilişkilendirilir. Çalışmayı sıraya alabilir ve sınırlama kaldırıldıktan sonra başlatabilirsiniz.

Çit temizlendikten sonra işi sıraya koymak ve başlatmak hiçbir şeyi engellemez. Arabellek ne zaman ekrandan çıkacaksa bunu garanti eden kendi çitinizi hemen döndürürsünüz. Arabellekleri sıraya alırken çekirdek, senkronizasyon çerçevesiyle 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ı nesneleri, kullanıcı alanında dosya tanımlayıcıları olarak gösterilir.

Entegrasyon kuralları

Android HAL arayüzü kurallarına uyun:

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

Bir çit nesnesi, BufferQueue'dan her geçtiğinde yeniden adlandırılır. Çekirdek çit desteği, çitlerin ad için dizeler içermesine olanak tanır. Bu nedenle, senkronizasyon çerçevesi, çiti adlandırmak için sıraya alınan pencere adını ve arabellek dizinini kullanır (ör. SurfaceView:0). Bu, /d/sync çıkışında ve hata raporlarında adlar göründüğünden kilitlenmenin kaynağını belirlemek için hata ayıklamada faydalıdır.

ANativeWindow entegrasyonu

ANativeWindow, çit farkındadır. dequeueBuffer, queueBuffer ve cancelBuffer'de sınır parametreleri bulunur.

OpenGL ES entegrasyonu

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

  • EGL_ANDROID_native_fence_sync, EGLSyncKHR nesnelerinde yerel Android çit dosyası tanımlayıcılarını sarmalama veya oluşturma yöntemi sağlar.
  • EGL_ANDROID_wait_sync, CPU tarafı yerine GPU tarafında duraklamalara izin vererek GPU'nun EGLSyncKHR beklemesine neden olur. 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 ilişkili çekirdek desteğiyle birlikte EGL_ANDROID_native_fence_sync uzantısını uygulayın. Ardından, sürücünüzde EGL_ANDROID_wait_sync uzantısını etkinleştirin. EGL_ANDROID_native_fence_sync uzantısı, farklı bir yerel çit EGLSyncKHR nesne türünden oluşur. Bu nedenle, mevcut EGLSyncKHR nesne türleri için geçerli olan uzantılar, EGL_ANDROID_native_fence nesneleri için geçerli olmayabilir ve istenmeyen etkileşimler önlenir.

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

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

Yerel Android çit dosya tanımlayıcısından DupNativeFenceFD() nesnesini çıkarmak için DupNativeFenceFD() işlev çağrısını kullanın.EGLSyncKHR Bu, set özelliğine sorgu göndermekle aynı sonucu verir ancak alıcının çiti kapatması (dolayısıyla yinelenen işlem) kuralına uyar. Son olarak, EGLSyncKHR nesnesinin yok edilmesi dahili çit özelliğini kapatır.

Donanım Composer entegrasyonu

Donanım Composer üç tür senkronizasyon bariyerini işler:

  • Acquire fences, giriş arabellekleriyle birlikte setLayerBuffer ve setClientTarget çağrılarına iletilir. Bunlar, arabelleğe yazma işleminin beklemede olduğunu gösterir ve SurfaceFlinger veya HWC, kompozisyon gerçekleştirmek için ilişkili arabellekten okumaya çalışmadan önce sinyal vermelidir.
  • Yayın sınırları, getReleaseFences araması kullanılarak presentDisplay araması yapıldıktan sonra alınır. Bunlar, aynı katmandaki önceki arabellekten okunmayı bekleyen verileri gösterir. A HWC, geçerli arabellek ekranda önceki arabelleğin yerini aldığından önceki arabelleği kullanmayı bıraktığında yayın bariyeri sinyalleri gönderir. Yayın sınırları, mevcut kompozisyon sırasında değiştirilecek önceki arabelleklerle birlikte uygulamaya geri iletilir. Uygulama, kendisine döndürülen arabelleğe yeni içerik yazmadan önce yayınlanma sınırı sinyallerini beklemelidir.
  • Mevcut çitler, presentDisplay çağrısının bir parçası olarak kare başına bir tane döndürülür. Mevcut bariyerler, bu karenin kompozisyonunun tamamlandığı veya alternatif olarak, önceki karenin kompozisyon sonucunun artık gerekli olmadığı zamanı gösterir. Fiziksel ekranlarda, geçerli çerçeve ekranda göründüğünde presentDisplay mevcut sınırlayıcıları 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.