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).
Ş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.
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.
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.
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.
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)
Önerilen mod
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.
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.
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:
- Android Frame Pacing'i OpenGL oluşturucunuza entegre etme
- Android Frame Pacing'i Vulkan oluşturucunuza entegre etme