Android Frame Pacing 程式庫 (又稱為 Swappy) 是 Android Game SDK 的一部分。這個程式庫可讓 OpenGL 和 Vulkan 遊戲在 Android 裝置上流暢地顯示畫面,並修正影格同步情形。
影格同步是指遊戲的邏輯和算繪迴圈,與 OS 螢幕子系統和基礎顯示硬體的同步處理程序。Android 螢幕子系統經過特別設計,可避免特定視覺瑕疵 (例如撕裂) 的發生。螢幕子系統會執行下列操作,避免畫面撕裂:
- 在內部為已通過的影格預留緩衝區
- 偵測延遲提交的影格
- 偵測到影格延遲時,繼續顯示目前影格
影格顯示時間不一致,是因為遊戲的算繪迴圈以與原生顯示硬體支援的不同速率運作。如果遊戲的算繪迴圈執行速度過慢,就會導致基礎顯示硬體的顯示時間不一致。舉例來說,如果以每秒 30 個影格數執行的遊戲試圖在原生支援每秒 60 個影格數的裝置上執行,遊戲的算繪迴圈就會導致重複影格在螢幕上保留額外 16 毫秒。這類不連結會導致影格時間出現明顯的不一致性,例如 33 毫秒、16 毫秒、49 毫秒等等。過度複雜的場景會導致影格遭到遺漏,使得問題更加複雜。
Frame Pacing 程式庫會執行下列工作:
- 可補償因遊戲影格過短而導致的畫面延遲。
- 新增顯示時間戳記,以便影格準時顯示,而不會提早顯示。
- 使用顯示時間戳記副檔名
EGL_ANDROID_presentation_time
和VK_GOOGLE_display_timing
。
- 使用同步圍欄處理長影格,以免畫面卡頓或延遲。
- 將等候插入的影格插入應用程式,該應用程式允許顯示管道擷取而不允許建構背壓。
- 使用同步區隔 (
EGL_KHR_fence_sync
和VkFence
)。
- 如果裝置支援多種刷新率,系統會選擇刷新率,以提供彈性和流暢的呈現效果。
- 使用影格統計資料提供偵錯和剖析統計資料。
如要瞭解如何根據需求,將程式庫設為在不同模式下執行,請參閱「支援的作業模式」。
如要使用 OpenGL 或 Vulkan 轉譯器實作,請參閱
詳情請參閱「達到適當的影格使用速度」一文。
每秒畫格數節流介入措施
每秒影格數 (FPS) 節流介入措施可讓遊戲以適當的 FPS 執行,只需進行平台端變更,開發人員不必採取任何行動。
FPS 節流介入措施的實作方式會使用下列元件:
GameManagerService
GameManagerService 元件會維護遊戲模式和遊戲介入的所有使用者和遊戲資訊。FPS 資訊會與其他介入資訊 (例如解析度縮小係數) 一併儲存在 GameManagerService 中,並在每個使用者設定檔的 <PACKAGE_NAME, Interventions>
對應項目中。當遊戲模式變更或介入措施更新時,系統就會存取 FPS 資訊。UID
是每個 PACKAGE_NAME
和使用者的專屬值,且可進一步轉譯為 <UID, Frame Rate>
組合,以便傳送至 SurfaceFlinger。
SurfaceFlinger
只要影格速率是螢幕重新整理頻率的除數,SurfaceFlinger 元件就已支援限制應用程式的 FPS。在 vsync 事件中,SurfaceFlinger 會檢查受限應用程式的 vsync 有效性,方法是確認 vsync 時間戳記是否與應用程式的影格速率同步。如果影格速率與 vsync 不同步,SurfaceFlinger 會保留影格,直到影格速率和 vsync 同步為止。
下圖說明 GameManagerService 與 SurfaceFlinger 之間的互動:

圖 1. GameServiceManager 與 SurfaceFlinger 之間的互動
SurfaceFinger 會維護 <UID, Frame Rate>
組對應,以便設定新的影格速率節流優先順序。UID
在使用者和遊戲之間是獨一無二的,因此單一裝置上的每位使用者都可以為同一款遊戲設定不同的影格速率。為了限制遊戲的影格速率,GameServiceManager 會呼叫 SurfaceFlinger,藉此覆寫 UID 的影格速率。透過這項機制,SurfaceFlinger 會在遊戲模式變更或介入措施更新時,更新對應項目。SurfaceFlinger 會根據緩衝區鎖定方式處理 FPS 變更。
如要進一步瞭解 FPS 節流,請參閱「 FPS 節流簡介」。