Frame-Pacing

Die Android Frame Pacing-Bibliothek, auch bekannt als Swappy, ist Teil des Android Game SDK. Es trägt dazu bei, dass OpenGL- und Vulkan-Spiele auf Android reibungslos gerendert werden und die Framerate korrekt ist.

Beim Frame-Pacing wird die Logik und der Rendering-Loop eines Spiels mit dem Anzeigesubsystem und der zugrunde liegenden Anzeigehardware eines Betriebssystems synchronisiert. Das Android-Display-Subsystem wurde so konzipiert, dass bestimmte visuelle Artefakte wie Tearing vermieden werden. Das Display-Subsystem vermeidet Tearing, indem es Folgendes tut:

  • Vergangene Frames werden intern gepuffert
  • Erkennen von verspäteten Frame-Einreichungen
  • Der aktuelle Frame wird weiterhin angezeigt, wenn ein verspäteter Frame erkannt wird.

Inkonsistente Frame-Anzeigezeiten werden dadurch verursacht, dass der Render-Loop eines Spiels mit einer anderen Rate ausgeführt wird, als die native Displayhardware unterstützt. Probleme treten auf, wenn die Renderingschleife eines Spiels zu langsam für die zugrunde liegende Displayhardware ausgeführt wird, was zu inkonsistenten Anzeigezeiten führt. Wenn ein Spiel mit 30 fps beispielsweise auf einem Gerät gerendert wird, das nativ 60 fps unterstützt, bleibt aufgrund der Renderschleife des Spiels ein wiederholter Frame 16 ms länger auf dem Bildschirm. Diese Art von Diskrepanz führt zu erheblichen Unregelmäßigkeiten bei den Frame-Zeiten, z. B. 33 ms, 16 ms und 49 ms. Zu komplexe Szenen verschärfen dieses Problem zusätzlich, da sie dazu führen, dass Frames ausgelassen werden.

Die Frame Pacing-Bibliothek führt folgende Aufgaben aus:

  • Kompensiert Ruckeln aufgrund kurzer Game-Frames.
  • Verwendet Synchronisationsbarrieren für lange Frames, was zu Ruckeln und Latenz führt.
    • Fügt Wartezeiten in die App ein. Dadurch kann die Display-Pipeline aufholen, anstatt dass sich ein Rückstau bildet.
    • Verwendet Synchronisations-Fences (EGL_KHR_fence_sync und VkFence).
  • Wählt eine Aktualisierungsrate aus, um Flexibilität und eine flüssige Darstellung zu ermöglichen, wenn Ihr Gerät mehrere Aktualisierungsraten unterstützt.
  • Bietet Statistiken für das Debugging und Profiling mit Frame-Statistiken.

Informationen zum Konfigurieren der Bibliothek für verschiedene Betriebsmodi finden Sie unter Unterstützte Betriebsmodi.

Informationen zur Implementierung mit dem OpenGL-Renderer oder dem Vulkan-Renderer finden Sie hier:

Weitere Informationen finden Sie unter Frame Pacing-Bibliothek.

Drosselung der Bilder pro Sekunde

Durch die FPS-Drosselung können Spiele mit einer angemessenen FPS-Rate ausgeführt werden. Dazu sind nur Änderungen auf der Plattformseite erforderlich und Entwickler müssen nichts unternehmen.

Bei der Implementierung der FPS-Drosselung werden die folgenden Komponenten verwendet.

GameManagerService

Die Komponente GameManagerService verwaltet alle nutzer- und spielbezogenen Informationen zum Spielmodus und zu Spieleingriffen. Die FPS-Informationen werden im GameManagerService zusammen mit anderen Interventionsinformationen wie dem Faktor für die Auflösungsverkleinerung in einer <PACKAGE_NAME, Interventions>-Zuordnung für jedes Nutzerprofil gespeichert. Auf die FPS-Informationen wird zugegriffen, wenn der Spielmodus geändert oder die Intervention aktualisiert wird. Eine UID ist für jedes PACKAGE_NAME und jeden Nutzer eindeutig und kann in ein <UID, Frame Rate>-Paar übersetzt werden, das an SurfaceFlinger gesendet wird.

SurfaceFlinger

Die SurfaceFlinger-Komponente unterstützt bereits das Drosseln der FPS einer Anwendung, sofern die Framerate ein Teiler der Displayaktualisierungsrate ist. Bei einem VSync prüft SurfaceFlinger die Gültigkeit des VSync für die gedrosselte Anwendung, indem es prüft, ob der VSync-Zeitstempel mit der Framerate der Anwendung übereinstimmt. Wenn die Framerate nicht mit dem VSync synchronisiert ist, hält SurfaceFlinger den Frame an, bis die Framerate und VSync synchronisiert sind.

Das folgende Bild zeigt die Interaktion zwischen GameManagerService und SurfaceFlinger:

Interaktion zwischen GameManagerService und SurfaceFlinger

Abbildung 1: Interaktion zwischen GameServiceManager und SurfaceFlinger

Der SurfaceFinger behält eine <UID, Frame Rate>-Paarzuordnung bei, um eine neue Priorität für die Drosselung der Framerate festzulegen. Die UID ist für Nutzer und Spiele eindeutig, sodass jeder Nutzer auf einem einzelnen Gerät unterschiedliche Einstellungen für die Bildrate für dasselbe Spiel haben kann. Um die Framerate eines Spiels zu drosseln, ruft der GameServiceManager den SurfaceFlinger auf, um die Framerate für eine UID zu überschreiben. Mit diesem Mechanismus aktualisiert SurfaceFlinger die Zuordnung immer dann, wenn der Spielmodus geändert oder die Intervention aktualisiert wird. SurfaceFlinger verarbeitet die Änderung der FPS durch entsprechendes Latching von Puffern.

Weitere Informationen zur FPS-Drosselung finden Sie unter FPS-Drosselung.