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ı göstermesini sağlayan bir API sağlar. Çerçeve aynı zamanda senkronizasyon temellerinin sürücüler arasında çekirdekten kullanıcı alanına ve kullanıcı alanı süreçleri arasında geçirilmesine izin verir.

Örneğin, bir uygulama GPU'da gerçekleştirilecek işi sıraya alabilir. 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 birleştiricisine iletilir. Pencere oluşturucu önceden işlemeye başlar ve işi ekran denetleyicisine iletir. Benzer şekilde, CPU işi önceden yapılır. GPU bittiğinde, ekran denetleyicisi hemen görüntüyü görüntüler.

Senkronizasyon çerçevesi aynı zamanda uygulayıcıların kendi donanım bileşenlerinde senkronizasyon kaynaklarından faydalanmalarını sağlar. 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 bitirdiklerinde sinyal vermelerini sağlar. Açık senkronizasyon, çekirdek alanında uygulanır.

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

  • Cihazlar arasında daha az davranış değişikliği
  • Daha iyi hata ayıklama desteği
  • Geliştirilmiş test metrikleri

Eşitleme çerçevesinin üç nesne türü vardır:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline , satıcıların bir GL bağlamı, görüntü denetleyicisi veya 2D kırpıntı gibi her sürücü örneği için uygulaması gereken monoton artan bir zaman çizelgesidir. sync_timeline , belirli bir donanım parçası için çekirdeğe gönderilen işleri sayar. sync_timeline , işlem sırası hakkında garantiler sağlar ve donanıma özel uygulamaları etkinleştirir.

sync_timeline uygularken şu yönergeleri izleyin:

  • Hata ayıklamayı basitleştirmek için tüm sürücüler, zaman çizelgeleri ve çitler için 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 çizelgelerinde uygulayın.
  • GL kitaplığı gibi kullanıcı alanı kitaplıklarına istenirse özel zaman çizelgesi verilerine erişim sağlamak için dolgu driver_data uygulayın. data_driver , satıcıların bunlara dayalı komut satırları oluşturmak için değişmez sync_fence ve sync_pts hakkında bilgi iletmesine izin verir.
  • Kullanıcı alanının açıkça bir çit oluşturmasına veya işaret etmesine izin vermeyin. Açıkça sinyaller/çitler oluşturmak, boru hattı işlevselliğini durduran bir 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 , bir sync_timeline üzerindeki tek bir değer veya noktadır. Bir noktanın üç durumu vardır: aktif, sinyal verildi ve hata. Noktalar aktif durumda başlar ve sinyal veya hata durumlarına geçiş yapar. Örneğin, bir görüntü tüketicisinin artık bir ara belleğe ihtiyacı kalmadığında, bir sync_pt sinyali gönderilir, böylece bir görüntü üreticisi arabelleğe yeniden yazmanın uygun olduğunu bilir.

sync_fence

sync_fence , genellikle farklı sync_timeline sahip bir sync_pt değerleri topluluğudur (ekran denetleyicisi ve GPU için olduğu gibi). 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 bir arabellek kullanarak bitirdiklerinde, bağımlılık bilgilerini tek bir işlev parametresiyle ileterek sinyal vermelerine olanak tanır. Çitler bir dosya tanımlayıcı tarafından desteklenir ve çekirdek alanından kullanıcı alanına iletilir. Örneğin, bir çit, iki ayrı görüntü tüketicisinin bir arabelleği okumasının ne zaman bittiğini belirten iki sync_pt değeri içerebilir. Çit sinyali verildiğinde, görüntü üreticileri her iki tüketicinin de tüketmesinin bittiğini biliyor.

Fences, sync_pt değerleri gibi aktif olmaya 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 durumuna sahiptir.

Bir sync_fence üyeliği, çit oluşturulduktan sonra değişmez. Bir çitte birden fazla nokta elde etmek için, iki farklı çitten gelen noktaların üçüncü bir çite eklendiği bir birleştirme gerçekleştirilir. Bu noktalardan biri başlangıç ​​çitinde işaretlenmiş ve diğeri verilmemişse, üçüncü çit de işaretlenmiş durumda olmayacaktır.

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

  • Belirli bir donanım sürücüsü için eşitleme çerçevesini uygulayan bir çekirdek alanı alt sistemi. Çitlerin farkında olması gereken sürücüler genellikle Donanım Oluşturucuya erişen veya onunla iletişim kuran her şeydir. Anahtar dosyalar şunları içerir:
    • Temel uygulama:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt
    • platform/system/core/libsync içindeki çekirdek alanıyla iletişim kurmak için kitaplık
  • Satıcı, HAL'deki validateDisplay() ve presentDisplay() işlevlerine parametre olarak uygun eşitleme ç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: Bir görüntü sürücüsü uygulama

Senkronizasyon işlevini destekleyen API'yi kullanmak için, görüntü arabelleği işlevine sahip bir görüntü sürücüsü geliştirin. Senkronizasyon çerçevesi mevcut olmadan önce, bu fonksiyon dma-buf nesnelerini alacak, bu arabellekleri ekrana yerleştirecek ve arabellek görünürken engelleyecekti. Ö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çevesi ile display_buffer işlevi daha karmaşıktır. Bir arabellek ekrana getirilirken, arabellek, arabelleğin ne zaman hazır olacağını gösteren bir çit ile ilişkilendirilir. Çit temizlendikten sonra sıraya girebilir ve işi başlatabilirsiniz.

Çit temizlendikten sonra kuyruğa girmek ve işe başlamak hiçbir şeyi engellemez. Arabelleğin ne zaman ekrandan çıkacağını garanti eden kendi çitinizi hemen iade edersiniz. 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üm, çekirdek-alan eşitleme ç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ğini açıklar. Çekirdek alanı nesneleri, kullanıcı alanında dosya tanımlayıcıları olarak temsil edilir.

Entegrasyon kuralları

Android HAL arabirim kurallarını izleyin:

  • API, sync_pt bir dosya tanımlayıcı sağlıyorsa, satıcının sürücüsü veya API'yi kullanan HAL, dosya tanımlayıcıyı kapatmalıdır.
  • Satıcı sürücüsü veya HAL, bir API işlevine sync_pt içeren bir dosya tanımlayıcı iletirse, satıcı sürücüsü veya HAL dosya tanımlayıcıyı kapatmamalıdır.
  • Çit dosyası tanımlayıcısını kullanmaya devam etmek için satıcı sürücüsü veya HAL, tanımlayıcıyı çoğaltmalıdır.

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 eşitleme çerçevesi, çiti adlandırmak için sıraya alınan SurfaceView:0 gibi pencere adını ve arabellek dizinini kullanır. Bu, adlar /d/sync ve hata raporlarının çıktısında göründüğü için bir kilitlenmenin kaynağını belirlemek için hata ayıklamaya yardımcı olur.

ANativeWindow entegrasyonu

ANativeWindow çit farkındadı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 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ı duraklamalarına izin vererek GPU'nun EGLSyncKHR için beklemesini sağlar. EGL_ANDROID_wait_sync uzantısı, EGL_KHR_wait_sync uzantısı ile 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ı, ayrı bir yerel çit EGLSyncKHR nesne türünden oluşur. Sonuç olarak, mevcut EGLSyncKHR nesne türlerine uygulanan uzantılar, istenmeyen etkileşimlerden kaçınarak EGL_ANDROID_native_fence nesnelerine mutlaka uygulanmaz.

EGL_ANDROID_native_fence_sync uzantısı, yalnızca oluşturma zamanında ayarlanabilen ve mevcut bir eşitleme nesnesinden doğrudan sorgulanamayan karşılık gelen bir yerel çit dosyası tanımlayıcı özniteliği kullanır. Bu öznitelik 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ğini sorgulamakla aynı sonuca sahiptir, ancak alıcının çiti kapatması kuralına bağlıdır (dolayısıyla yinelenen işlem). Son olarak, EGLSyncKHR nesnesinin yok edilmesi dahili çit niteliğini kapatır.

Donanım Besteci entegrasyonu

Hardware Composer, üç tür eşitleme çitini işler:

  • Edinme çitleri , giriş arabellekleriyle birlikte setLayerBuffer ve setClientTarget çağrılarına geçirilir. Bunlar, arabelleğe bekleyen bir yazmayı temsil eder ve SurfaceFlinger veya HWC, kompozisyonu gerçekleştirmek için ilişkili arabellekten okumaya çalışmadan önce sinyal vermelidir.
  • getReleaseFences çağrısı kullanılarak presentDisplay çağrısından sonra serbest bırakma çitleri alınır. Bunlar, aynı katmandaki önceki tampondan bekleyen bir okumayı temsil eder. Geçerli arabellek ekranda önceki arabelleğin yerini aldığından, HWC artık önceki arabelleği kullanmadığında bir serbest bırakma çiti sinyali verir. Serbest bırakma çitleri, mevcut kompozisyon sırasında değiştirilecek olan önceki arabelleklerle birlikte uygulamaya geri gönderilir. Uygulama, kendilerine döndürülen arabelleğe yeni içerikler yazmadan önce bir yayın sınırı sinyali verene kadar beklemelidir.
  • Mevcut çitler , presentDisplay çağrısının bir parçası olarak kare başına bir tane olacak şekilde döndürülür. Mevcut çitler, bu çerçevenin kompozisyonunun ne zaman tamamlandığını veya alternatif olarak, önceki çerçevenin kompozisyon sonucunun artık gerekli olmadığı zamanı temsil eder. Fiziksel görüntüler için, presentDisplay , geçerli çerçeve ekranda göründüğünde mevcut çitleri döndürür. Mevcut çitler döndürüldükten sonra, varsa, SurfaceFlinger hedef arabelleğine yeniden yazmak güvenlidir. Sanal ekranlar için, çıktı arabelleğinden okumak güvenli olduğunda mevcut çitler döndürülür.