單獨使用 Android Choreographer
遊戲也會使用 Android Choreographer 進行同步處理。這個元件可透過 API 16 的 Java 和 API 24 的 C++ 提供,其滴答頻率與螢幕子系統相同。不過,相較於實際硬體 VSYNC,滴答提交的時間仍有些微差異,而且這些偏移會因裝置而異。長的影格可能仍會出現緩衝區填充的情形。
Frame Pacing 程式庫的優點
Frame Pacing 程式庫採用 Android Choreographer 進行同步處理,並處理所提交滴答中的各項變化。這項功能使用顯示時間戳記,確保系統在適當時機顯示影格並同步處理屏障,避免緩衝區填充的情況。這個程式庫使用
NDK Choreographer
(如果有的話)。如果沒有的話,則會改用
Java Choreographer
。
如果裝置支援該程式庫,這個程式庫就能處理多個刷新率,進而讓遊戲在顯示影格時更具彈性。舉例來說,對於支援 60 Hz 和 90 Hz 刷新率的裝置,如果遊戲無法每秒產生 60 個影格,只要將每秒影格數調降至 45 (而非 30),即可保持順暢運作。程式庫會偵測預期的遊戲影格速率,並據此自動調整影格顯示時間。Frame Pacing 程式庫也會避免不必要的螢幕更新,延長電池續航力。舉例來說,如果遊戲以每秒 60 個影格轉譯,但螢幕以 120 Hz 更新,則每個影格的畫面都會更新兩次。Frame Pacing 程式庫會將刷新率設為裝置支援且最接近目標影格速率的值,避免發生上述情況。
以下各節說明 Frame Pacing 程式庫如何處理長和短的遊戲影格,讓影格能夠正確同步。
以 30 Hz 為單位修正影格同步速度
在 60 Hz 裝置上以 30 Hz 算繪時,Android 上的理想狀態如圖 1 所示。SurfaceFlinger 會鎖住新的圖形緩衝區,如果有的話 (圖表中的 NB 表示「沒有緩衝區」,且前一個緩衝區會重複)。
圖 1.
以 30 Hz 的理想影格同步速度在 60 Hz 裝置上執行。
短的遊戲影格會導致播放不流暢
在大部分新型裝置上,遊戲引擎都仰賴平台編排器提交滴答,以推動系統提交影格。不過如圖 2 所示,較短的影格可能仍會導致影格同步情況不佳。較長的影格接續著較短的影格出現會被玩家視為延遲。
圖 2.
短的遊戲影格 C 會使得影格 B 只顯示一個影格,而後接續出現多個影格 C。
Frame Pacing 程式庫透過使用顯示時間戳記來解決這個問題。程式庫會使用顯示時間戳記副檔名
EGL_ANDROID_presentation_time
和
VK_GOOGLE_display_timing
,因此影格不會提早出現,如圖 3 所示。
圖 3.
遊戲影格 B 顯示兩次,讓遊戲流暢顯示。
長的影格會導致播放不流暢或延遲
當顯示工作負載所花的時間超過應用程式工作負載的時間時,系統會將額外的影格新增至佇列。如此一來,畫面會再次出現延遲,也可能因為緩衝區填充而造成額外的影格延遲 (參閱圖 4)。程式庫會同時移除延遲和額外的影格延遲。
圖 4.
對於 2 個影格 (A 和 B),長的影格 B 同步處理不正確
透過同步處理屏障 (
EGL_KHR_fence_sync
和
VkFence
) 將等候插入的影格插入應用程式,該應用程式允許顯示管道擷取而不允許建構背壓,程式庫得以解決這個問題。影格 A 仍顯示額外影格,但影格 B 現在已經可以正確顯示,如圖 5 所示。
圖 5.
等候顯示的影格 C 和 D。
支援的作業模式
您可以將 Frame Pacing 程式庫設為在下列任一模式中執行:
自動模式已關閉 + 管道
自動模式已開啟 + 管道
自動模式已開啟 + 自動管道模式 (管道/非管道)
建議的模式
您可以嘗試使用自動模式和管道模式,但必須先關閉這些模式,並在初始化 Swappy 後納入以下內容:
swappyAutoSwapInterval(false);
swappyAutoPipelineMode(false);
swappyEnableStats(false);
swappySwapIntervalNS(1000000000L/yourPreferredFrameRateInHz);
為了協調引擎工作負載,程式庫通常會使用管道模型,將 CPU 和 GPU 工作負載拆分至 VSYNC 邊界。
圖 6. 管道模式。
非管道模式
一般來說,這種做法會使得輸入畫面延遲的情況較少出現,且較容易預測。如果遊戲的影格時間非常短,則 CPU 和 GPU 工作負載可能都會融入單一交換間隔。在此情況下,非管道的方法實際上會縮短輸入畫面的延遲時間。
圖 7. 非管道模式。
大部分的遊戲不知道如何選擇替換間隔,也就是每幅影格顯示的時間長度 (例如為 30 Hz 選擇 33.3 毫秒)。在某些裝置上,遊戲能以每秒 60 個影格數算繪,而別部裝置則可能需要降到較低的值。自動模式會測量 CPU 和 GPU 時間,以便執行下列操作:
自動選取替換間隔 :在某些情況下,以 30 Hz 提交的遊戲和其他以 60 Hz 提交的遊戲可以允許程式庫動態調整這個間隔。
停用超快影格中的管道 :在任何情況下都能提交最佳的輸入畫面延遲時間。
多種刷新率
支援多種刷新率的裝置可讓使用者靈活切換替換間隔,讓畫面看起來更順暢:
在 60 Hz 的裝置上 :60 FPS / 30 FPS / 20 FPS
在 60 Hz + 90 Hz 的裝置上 :90 FPS / 60 FPS / 45 FPS / 30 FPS
在 60 Hz + 90 Hz + 120 Hz 的裝置上 :120 FPS / 90 FPS / 60 FPS / 45 FPS /
40 FPS / 30 FPS
程式庫會選擇與遊戲影格的實際顯示時間長度最相符的刷新率,以提供更優質的視覺體驗。
如要進一步瞭解多種刷新率的影格同步情形,請參閱「高刷新率算繪的 Android 網誌文章 」。
影格統計資料
Frame Pacing 程式庫提供下列統計資料供偵錯和剖析:
顯示算繪完成後,在合成器佇列等待的影格其畫面重新整理次數的直方圖。
顯示在要求的顯示時間與目前的實際時間之間,畫面重新整理次數的直方圖。
顯示兩個連續影格間,通過的畫面重新整理次數直方圖。
顯示 CPU 開始為這個影格運作與目前的實際時間之間,畫面重新整理次數的直方圖。
參閱以下任一指南,將 Android Frame Pacing 程式庫整合至遊戲中:
將 Android Frame Pacing 整合至 OpenGL 轉譯器
將 Android Frame Pacing 整合至 Vulkan 轉譯器
注意: Unity 已將 Android Frame Pacing 整合至自家引擎。如要在 Unity 2019.2 以上版本中啟用這項功能,請依序前往「Project Settings」>「Player」>「Settings for Android」>「Resolution and Presentation」,然後勾選下方的「Optimized Frame Pacing」核取方塊。 其他資源
Mir 2 使用 Swappy 提升轉譯效能 ,將緩慢工作階段率從 40% 降至 10%。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-02-28 (世界標準時間)。"],[],[]]