Frame Pacing Kitaplığı Android Game Development Kit'in bir parçasıdır.

Swappy olarak da bilinen Android Frame Pacing kitaplığı AGDK Kitaplıkları'nın bir parçasıdır. OpenGL ve Vulkan oyunlarının Android'de sorunsuz oluşturma ve doğru kare hızı elde etmesine yardımcı olur. Bu belgede kare hızını tanımlar, kare hızının gerekli olduğu durumlar açıklanır ve kitaplığın bu durumları nasıl ele aldığı gösterilmektedir. Doğrudan oyununuzda kare hızını uygulamaya atlamak istiyorsanız Sonraki adım'a bakın.

Arka plan

Kare hızı, bir oyunun mantığı ve oluşturma döngüsünün, işletim sisteminin ekran alt sistemi ve altta yatan ekran donanımıyla senkronize edilmesidir. Android ekran alt sistemi, güncelleme sırasında ekran donanımı yeni bir çerçeveye geçtiğinde oluşabilecek görsel kusurları (yırtılma olarak bilinir) önlemek için tasarlanmıştır. Ekran alt sistemi, bu yapıları önlemek için aşağıdakileri yapar:

  • Geçmiş kareleri dahili olarak arabelleğe alır
  • Geç kare gönderimlerini algılar
  • Geç kareler algılandığında geçmiş karelerin gösterilmesini tekrar eder

Bir oyun, ekran alt sistemindeki birleştirici SurfaceFlinger'a bir kare için gereken tüm çizim çağrılarını gönderdiğini bildirir (eglSwapBuffers veya vkQueuePresentKHR yöntemini çağırarak). SurfaceFlinger, bir mandal kullanarak ekran donanımına bir karenin kullanılabilirliğini bildirir. Ekran donanımı daha sonra belirtilen çerçeveyi gösterir. Ekran donanımı sabit bir hızda (ör. 60 Hz) çalışır ve donanıma ihtiyaç duyduğunda yeni bir kare yoksa donanım önceki kareyi tekrar görüntüler.

Oyun oluşturma döngüsü yerel görüntü donanımından farklı bir hızda oluşturulduğunda genellikle tutarsız kare süreleri ortaya çıkar. 30 FPS'de çalışan bir oyun, yerel olarak 60 FPS'yi destekleyen bir cihazda oluşturmaya çalışırsa oyun oluşturma döngüsü, tekrarlanan bir karenin ekranda fazladan 16 milisaniye boyunca kaldığını fark etmez. Bu bağlantı kesilmesi, genellikle 49 milisaniye, 16 milisaniye ve 33 milisaniye gibi kare sürelerinde önemli ölçüde tutarsızlık meydana getirir. Aşırı karmaşık sahneler, eksik karelere neden olduğundan bu sorunu daha da karmaşık hale getirir.

Optimum olmayan çözümler

Kare hızıyla ilgili aşağıdaki çözümler geçmişte oyunlar tarafından kullanılmıştır ve genellikle tutarsız kare sürelerine ve daha fazla giriş gecikmesine neden olur.

Kareleri oluşturma API'sinin izin verdiği kadar hızlı gönderin

Bu yaklaşım, oyunu değişken SurfaceFlinger etkinliğine bağlar ve fazladan bir gecikme çerçevesine yol açar. Görüntüleme ardışık düzeni, genellikle 2 boyutta bir kare sırası içerir. Oyun, kareleri çok hızlı sunmaya çalışıyorsa bu sırayı doldurur. Sırada yer kalmadığında oyun döngüsü (veya en azından oluşturma iş parçacığı) bir OpenGL veya Vulkan çağrısı tarafından engellenir. Daha sonra oyun, ekran donanımının bir kare göstermesini beklemeye zorlanır ve bu karşı basınç iki bileşeni senkronize eder. Bu durum, tampon doldurma veya sıra doldurma olarak bilinir. Oluşturucu işlemi neler olup bittiğini fark etmez, dolayısıyla kare hızı tutarsızlığı daha da kötüleşir. Oyun, kareden önce girdi örneği alırsa giriş gecikmesi daha da kötüleşir.

Android Choreographer'ı tek başına kullanma

Oyunlar, senkronizasyon için Android Choreographer'ı da kullanır. API'de API 16'dan itibaren Java'da, API 24'ten itibaren C++'ta kullanılabilen bu bileşen, görüntüleme alt sistemiyle aynı sıklıkta düzenli onay işaretleri sağlar. Bu onay işaretinin, gerçek donanım VSYNC'sine göre ne zaman iletileceği konusunda hala ince ayrıntılar vardır ve bu ofsetler cihaza göre değişir. Uzun karelerde arabellek doldurma işlemi yine de gerçekleşebilir.

Frame Pacing kitaplığının avantajları

Frame Pacing kitaplığı, senkronizasyon için Android Choreographer'ı kullanır ve onay işareti teslimindeki değişkenlikleri sizin yerinize yapar. Karelerin doğru zamanda sunulduğundan emin olmak için sunum zaman damgaları kullanır ve arabellek doldurmayı önlemek için parmakları senkronize eder. Kitaplık, varsa NDK Choreographer'ı kullanır, yoksa Java Choreographer'a geri döner.

Cihaz tarafından destekleniyorsa kitaplık, birden fazla yenileme hızını işler; bu da bir oyuna kare sunma konusunda daha fazla esneklik sağlar. Örneğin, hem 60 Hz hem de 90 Hz yenileme hızını destekleyen bir cihazda, saniyede 60 kare üretemeyen bir oyunun düzgün çalışması için 30 FPS yerine 45 FPS'ye düşmesi mümkündür. Kitaplık, beklenen oyun kare hızını algılar ve kare sunum sürelerini buna göre otomatik olarak ayarlar. Frame Pacing kitaplığı da gereksiz görüntü güncellemelerini önlediği için pil ömrünü de iyileştirir. Örneğin, oyun 60 FPS'de oluşturuluyorsa ancak ekran 120 Hz'de güncelleniyorsa ekran her kare için iki kez güncellenir. Frame Pacing kitaplığı, yenileme hızını cihaz tarafından desteklenen hedef kare hızına en yakın değere ayarlayarak bunu önler.

İşleyiş şekli

Aşağıdaki bölümlerde Frame Pacing kitaplığının doğru kare hızı elde etmek için uzun ve kısa oyun kareleriyle nasıl çalıştığı gösterilmektedir.

30 Hz'de doğru kare ilerleme hızı

60 Hz'lik bir cihazda 30 Hz'de oluşturma yaparken, Android'deki ideal durum Şekil 1'de gösterilmiştir. SurfaceFlinger, varsa yeni grafik arabellekleri kilitler (şemadaki NB'de "arabellek yok" ifadesi bulunur ve önceki grafik tekrar edilir).

60 Hz'lik cihazda 30 Hz'de ideal kare hızı

Şekil 1. 60 Hz'lik cihazda 30 Hz'de ideal kare hızı

Kısa oyun kareleri takılmaya neden oluyor

Oyun motorları, modern cihazların çoğunda karelerin gönderimini yönlendiren onay işaretleri gönderen platform koreografına güvenir. Bununla birlikte, Şekil 2'de görüldüğü gibi kısa kareler nedeniyle düşük bir kare hızı riski hâlâ vardır. Kısa karelerin ardından uzun kareler gelirse oynatıcı tarafından takılma olarak algılanır.

Kısa oyun çerçeveleri

2. Şekil. Kısa oyun karesi C, B karesinin yalnızca bir kare, ardından da birden fazla C karesi

Frame Pacing kitaplığı sunum zaman damgalarını kullanarak bu sorunu çözer. Kitaplık, sunum zaman damgası uzantılarını (EGL_ANDROID_presentation_time ve VK_GOOGLE_display_timing) kullanır. Böylece Şekil 3'te gösterildiği gibi kareler erkenden sunulmaz.

Sunu zaman damgaları

3. Şekil. Daha akıcı bir görüntü için B oyun karesi iki kez gösteriliyor

Uzun kareler takılmaya ve gecikmeye neden oluyor

Görüntülü reklamcılık iş yükü uygulama iş yükünden daha uzun sürdüğünde sıraya ekstra kareler eklenir. Bu da yine takılmaya yol açar ve arabellek doldurma işleminden dolayı fazladan bir gecikme çerçevesine yol açabilir (Şekil 4'e bakın). Kitaplık hem takılmayı hem de fazladan gecikme karesini ortadan kaldırır.

Uzun oyun çerçeveleri

4. Şekil. Uzun B karesi, 2 kare (A ve B) için yanlış ilerleme hızına neden oluyor

Kitaplık, geriye dönük baskının birikmesine izin vermek yerine görüntüleme ardışık düzeninin yetişebilmesini sağlayan beklemeleri uygulamaya eklemek için senkronizasyon parmaklarını (EGL_KHR_fence_sync ve VkFence) kullanarak bu sorunu çözer. A çerçevesi yine de ekstra bir kare gösterir, ancak Şekil 5'te görüldüğü gibi B çerçevesi artık doğru bir şekilde sunulmaktadır.

Uygulama katmanına bekleme sayısı eklendi

5. Şekil. C ve D kareleri sunmak için bekler

Desteklenen çalışma modları

Çerçeve İlerleme Hızı kitaplığını aşağıdaki üç moddan birinde çalışacak şekilde yapılandırabilirsiniz:

  • Otomatik mod kapalı + Ardışık düzen
  • Otomatik mod açık + Ardışık düzen
  • Otomatik mod açık + Otomatik ardışık düzen modu (Ardışık düzen/Ardışık düzen olmayan)

Otomatik mod ve ardışık düzen modlarıyla denemeler yapabilirsiniz. Ancak, Swappy'yi başlattıktan sonra aşağıdakileri devre dışı bırakarak ve aşağıdakileri ekleyerek başlarsınız:

  swappyAutoSwapInterval(false);
  swappyAutoPipelineMode(false);
  swappyEnableStats(false);
  swappySwapIntervalNS(1000000000L/yourPreferredFrameRateInHz);

Ardışık düzen modu

Kitaplık, motor iş yüklerini koordine etmek için genellikle CPU ve GPU iş yüklerini VSYNC sınırları arasında ayıran bir ardışık düzen modeli kullanır.

Ardışık düzen modu

6. Şekil. Ardışık düzen modu

Ardışık düzen olmayan mod

Genel olarak bu yaklaşım daha düşük ve daha tahmin edilebilir bir giriş ekranı gecikmesi sağlar. Bir oyunun kare süresinin çok düşük olduğu durumlarda, tek bir değiştirme aralığına hem CPU hem de GPU iş yükleri sığabilir. Bu durumda, ardışık düzensiz bir yaklaşım gerçekte daha düşük giriş ekranı gecikmesi sağlar.

Ardışık düzen olmayan mod

7. Şekil. Ardışık düzen olmayan mod

Otomatik mod

Çoğu oyun, değiştirme aralığının (her karenin gösterildiği süre) nasıl seçileceğini bilmez (örneğin, 30 Hz için 33,3 ms). Bir oyun bazı cihazlarda 60 FPS hızında oluşturulabilirken bazı cihazlarda daha düşük bir değere düşmesi gerekebilir. Otomatik mod, şunları yapmak için CPU ve GPU sürelerini ölçer:

  • Değiştirme aralıklarını otomatik olarak seç: Bazı sahnelerde 30 Hz, bazılarında ise 60 Hz sağlayan oyunlar kitaplığın bu aralığı dinamik olarak ayarlamasına izin verebilir.
  • Ultra hızlı kareler için ardışık düzeni devre dışı bırakın: Her durumda optimum giriş ekran gecikmesini sağlar.

Birden fazla yenileme hızı

Birden fazla yenileme hızını destekleyen cihazlar, sorunsuz görünen bir değiştirme aralığının seçilmesinde daha fazla esneklik sağlar:

  • 60 Hz cihazlarda: 60 FPS / 30 FPS / 20FPS
  • 60 Hz + 90 Hz cihazlarda: 90 FPS / 60 FPS / 45 FPS / 30 FPS
  • 60 Hz + 90 Hz + 120 Hz cihazlarda: 120 FPS / 90 FPS / 60 FPS / 45 FPS / 40 FPS / 30 FPS

Kitaplık, oyunun karelerinin gerçek oluşturma süresine en uygun yenileme hızını seçerek daha iyi bir görsel deneyim sunar.

Birden fazla yenileme hızı kare hızı hakkında daha fazla bilgi için Android'de yüksek yenileme hızında oluşturma blog yayınına bakın.

Kare istatistikleri

Frame Pacing kitaplığı, hata ayıklama ve profil çıkarma amacıyla aşağıdaki istatistikleri sunar:

  • Ekran yenileme sayısına yönelik histogram, oluşturma tamamlandıktan sonra birleştirici sırasında bekleyen bir karenin yenilenmesine neden olur.
  • İstenen sunu zamanı ile gerçek şimdiki zaman arasında geçen ekran yenileme sayısının histogramı.
  • Ardışık iki kare arasında geçirilen ekran yenileme sayısının histogramı.
  • Bu kare için CPU çalışmasının başlangıcı ile gerçek şu anki zaman arasında geçen ekran yenileme sayısının histogramı.

Sonraki adım

Android Frame Pacing kitaplığını oyununuza entegre etmek için aşağıdaki kılavuzlardan birine bakın: