senkronizasyon çerçevesi

Senkronizasyon çerçevesi, Android grafik sistemindeki farklı eşzamansız 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ı belirtmesine olanak tanıyan bir API sağlar. Çerçeve aynı zamanda senkronizasyon temellerinin çekirdekten kullanıcı alanına sürücüler arasında ve kullanıcı alanı işlemlerinin kendisi arasında aktarılmasına da olanak tanır.

Örneğin, bir uygulama GPU'da gerçekleştirilecek işi sıraya koyabilir. GPU bu görüntüyü çizmeye başlar. Görüntü henüz belleğe çekilmemiş olsa da arabellek işaretçisi, GPU işinin ne zaman biteceğini gösteren bir çitle birlikte pencere dizgisine iletilir. Pencere dizgicisi önceden işlemeye başlar ve işi ekran denetleyicisine aktarır. Benzer şekilde CPU işi de önceden yapılır. GPU bittiğinde ekran denetleyicisi görüntüyü hemen görüntüler.

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

Açık senkronizasyon

Açık senkronizasyon, grafik arabellek üreticilerinin ve tüketicilerinin, bir arabellek kullanarak işleri bittiğinde sinyal vermelerini sağlar. Açık senkronizasyon çekirdek alanında uygulanır.

Açık senkronizasyonun avantajları şunları içerir:

  • Cihazlar arasında daha az davranış değişimi
  • Daha iyi hata ayıklama desteği
  • Geliştirilmiş test ölçümleri

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

  • sync_timeline
  • sync_pt
  • sync_fence

senkronizasyon_zaman çizelgesi

sync_timeline satıcıların GL bağlamı, ekran denetleyicisi veya 2D ekran görüntüsü 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şleri sayar. sync_timeline işlemlerin sırası hakkında garantiler sağlar ve donanıma özgü uygulamalara olanak tanır.

sync_timeline uygularken bu yönergeleri izleyin:

  • Hata ayıklamayı kolaylaştırmak için tüm sürücülere, zaman çizelgelerine ve sınırlamalara yararlı adlar sağlayın.
  • Hata ayıklama çıktısını daha okunabilir hale getirmek için timeline_value_str ve pt_value_str operatörlerini zaman çizelgelerine uygulayın.
  • İstenirse, GL kitaplığı gibi kullanıcı alanı kitaplıklarına özel zaman çizelgesi verilerine erişim sağlamak için dolgu driver_data uygulayın. data_driver satıcıların değişmez sync_fence ve sync_pts hakkındaki bilgileri aktararak bunlara dayalı komut satırları oluşturmalarına olanak tanır.
  • Kullanıcı alanının açıkça bir çit oluşturmasına veya sinyal vermesine izin vermeyin. Açıkça sinyaller/çitler oluşturmak, boru hattı işlevselliğini durduran bir hizmet reddi saldırısıyla sonuçlanır.
  • sync_timeline , sync_pt veya sync_fence öğelerine açıkça erişmeyin. API gerekli tüm işlevleri sağlar.

senkronizasyon_pt

sync_pt sync_timeline çizelgesindeki tek bir değer veya noktadır. Bir noktanın üç durumu vardır: aktif, sinyalli ve hata. Noktalar aktif durumda başlar ve sinyal verilen veya hata durumlarına geçiş yapar. Örneğin, bir görüntü tüketicisinin artık ara belleğe ihtiyacı kalmadığında, bir sync_pt sinyali gönderilir, böylece görüntü üreticisi ara belleğe tekrar yazmanın sorun olmadığını bilir.

senkronizasyon_fence

sync_fence genellikle farklı sync_timeline üst öğelerine (ekran denetleyicisi ve GPU için olduğu gibi) sahip olan bir sync_pt değerleri koleksiyonudur. sync_fence , sync_pt ve sync_timeline , sürücülerin ve kullanıcı alanının bağımlılıklarını iletmek için kullandığı ana temel öğelerdir. Bir çit sinyali verildiğinde, ç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 tamamlanması garanti edilir.

Senkronizasyon çerçevesi, birden fazla tüketicinin veya üreticinin işleri bittiğinde bir arabellek kullanarak sinyal göndermesine olanak tanır ve bağımlılık bilgilerini tek bir işlev parametresi ile iletir. Çitler bir dosya tanımlayıcı tarafından desteklenir ve çekirdek alanından kullanıcı alanına aktarılır. Örneğin bir çit, iki ayrı görüntü tüketicisinin arabelleği okumayı bitirdiğini belirten iki sync_pt değeri içerebilir. Çit sinyali verildiğinde görüntü üreticileri her iki tüketicinin de tüketmeyi bıraktığını bilir.

Çitler, tıpkı sync_pt değerleri gibi, aktif olarak başlar ve noktalarının durumuna göre durum değiştirir. Tüm sync_pt değerleri sinyallenirse, sync_fence sinyallenir. Bir sync_pt hata durumuna düşerse tüm sync_fence bir hata durumu olur.

sync_fence üyeliği, çit oluşturulduktan sonra değiştirilemez. Bir çitte birden fazla nokta elde etmek için, iki farklı çitin noktalarının üçüncü bir çite eklendiği bir birleştirme yapılır. Bu noktalardan biri başlangıç ​​çitinde sinyal verilmişse ve diğeri değilse, üçüncü çit de sinyal verilmiş durumda olmayacaktır.

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. Çite duyarlı olması gereken sürücüler genellikle Donanım Oluşturucuya erişen veya onunla iletişim kuran herhangi bir şeydir. Anahtar dosyalar şunları içerir:
    • Çekirdek uygulama:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt adresindeki belgeler
    • platform/system/core/libsync çekirdek alanıyla iletişim kuracak kitaplık
  • Satıcı, 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: Bir ekran sürücüsünü uygulama

Senkronizasyon işlevini destekleyen API'yi kullanmak için, ekran arabelleği işlevine sahip bir ekran sürücüsü geliştirin. Senkronizasyon çerçevesi mevcut olmadan önce bu işlev, dma-buf nesnelerini alır, bu arabellekleri ekrana yerleştirir ve arabellek görünür durumdayken bloke ederdi. Ö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 tamponu ekrana koyarken, tampon, tamponun ne zaman hazır olacağını belirten bir çitle ilişkilendirilir. Çit temizlendikten sonra sıraya girip çalışmaya başlayabilirsiniz.

Çit temizlendikten sonra sıraya girmek ve işi başlatmak hiçbir şeyi engellemez. Tamponun ne zaman ekrandan çıkacağını garanti eden kendi çitinizi hemen geri getirirsiniz. Siz arabellekleri sıraya koyarken ç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ı nesneleri, kullanıcı alanında dosya tanımlayıcıları olarak temsil edilir.

Entegrasyon kuralları

Android HAL arayüz kurallarına uyun:

  • API, sync_pt başvuran bir dosya tanımlayıcı sağlıyorsa, satıcının sürücüsünün veya API'yi kullanan HAL'nin dosya tanımlayıcıyı kapatması gerekir.
  • Satıcı sürücüsü veya HAL, bir API işlevine sync_pt içeren bir dosya tanımlayıcıyı geçirirse, satıcı sürücüsü veya HAL, dosya tanımlayıcıyı kapatmamalıdır.
  • Koruma dosyası tanımlayıcısını kullanmaya devam etmek için satıcı sürücüsünün veya HAL'nin tanımlayıcıyı çoğaltması gerekir.

Bir çit nesnesi BufferQueue'dan her geçtiğinde yeniden adlandırılır. Çekirdek çit desteği, çitlerin adlar için dizelere sahip olmasına izin verir, bu nedenle senkronizasyon çerçevesi, çiti adlandırmak için sıraya alınan pencere adını ve arabellek dizinini kullanır; örneğin SurfaceView:0 . Bu, adların /d/sync çıktısında ve hata raporlarında görünmesi nedeniyle, kilitlenmenin kaynağını tanımlamak için hata ayıklamada faydalıdır.

ANativeWindow entegrasyonu

ANativeWindow çit farkındadır. dequeueBuffer , queueBuffer ve cancelBuffer koruma 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 dosyası tanımlayıcılarını sarmak veya oluşturmak için bir yol sağlar.
  • EGL_ANDROID_wait_sync , CPU tarafı yerine GPU tarafının durmasına izin vererek GPU'nun EGLSyncKHR 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, ilgili çekirdek desteğiyle birlikte EGL_ANDROID_native_fence_sync uzantısını uygulayın. Daha sonra 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. Sonuç olarak, mevcut EGLSyncKHR nesne türleri için geçerli olan uzantıların EGL_ANDROID_native_fence nesneleri için de geçerli olması gerekmeyebilir ve bu da istenmeyen etkileşimlerin önüne geçer.

EGL_ANDROID_native_fence_sync uzantısı, yalnızca oluşturma sırasında ayarlanabilen ve mevcut bir senkronizasyon nesnesinden ileriye doğru doğrudan sorgulanamayan, karşılık gelen bir yerel çit dosyası tanımlayıcı özelliğini 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, bir EGLSyncKHR nesnesinden yerel bir Android çit dosyası tanımlayıcısı oluşturur.

EGLSyncKHR nesnesini yerel Android çit dosyası tanımlayıcısından çıkarmak için DupNativeFenceFD() işlev çağrısını kullanın. Bu, set özniteliğinin sorgulanmasıyla aynı sonucu verir, ancak alıcının çiti kapatması kuralına uyar (dolayısıyla çoğaltma işlemi). Son olarak EGLSyncKHR nesnesinin yok edilmesi dahili çit özelliğini kapatır.

Donanım Oluşturucu entegrasyonu

Donanım Oluşturucusu üç tür senkronizasyon çitini yönetir:

  • Alma çitleri, giriş arabellekleriyle birlikte setLayerBuffer ve setClientTarget çağrılarına iletilir. Bunlar, arabelleğe bekleyen bir yazmayı temsil eder ve SurfaceFlinger veya HWC, kompozisyonu gerçekleştirmek için ilgili arabellekten okumaya çalışmadan önce sinyal vermelidir.
  • Serbest bırakma çitleri, getReleaseFences çağrısını kullanarak presentDisplay çağrısından sonra alınır. Bunlar, aynı katmandaki önceki arabellekten bekleyen bir okumayı temsil eder. Geçerli arabellek ekrandaki önceki arabelleğin yerini aldığı için HWC artık önceki arabelleği kullanmadığında, serbest bırakma çiti sinyali verir. Serbest bırakma çitleri, geçerli kompozisyon sırasında değiştirilecek olan önceki arabelleklerle birlikte uygulamaya geri aktarılır. Uygulamanın, kendisine döndürülen ara belleğe yeni içerik yazmadan önce serbest bırakma sinyali verene kadar beklemesi gerekir.
  • presentDisplay çağrısının bir parçası olarak mevcut çitler , kare başına bir tane olmak üzere döndürülür. Mevcut çitler, bu çerçevenin kompozisyonunun ne zaman tamamlandığını veya alternatif olarak önceki çerçevenin kompozisyon sonucuna artık ihtiyaç duyulmadığı zamanı temsil eder. Fiziksel ekranlar için, presentDisplay geçerli çerçeve ekranda göründüğünde mevcut çerçeveleri döndürür. Mevcut çitler döndürüldükten sonra, mümkünse SurfaceFlinger hedef arabelleğine yeniden yazmak güvenlidir. Sanal ekranlar için, çıkış arabelleğinden okumak güvenli olduğunda mevcut çitler döndürülür.