天天看點

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

  • 前言
  • 幀率 vs 螢幕重新整理頻率
    • 幀率
    • 螢幕重新整理頻率
  • VSync 是啥
  • VSync 有啥作用
    • 單緩存
    • 雙重緩存Double Buffer
    • 三重緩存Triple Buffer
  • 更多文章

前言

本文講解 VSync 産生的原因及其作用。内容涉及如下方面:

  • 幀率 vs 螢幕重新整理頻率;
  • 單緩存,雙重緩沖,三重緩存及各自的優缺點;
  • VSync 的工作過程;

幀率 vs 螢幕重新整理頻率

幀率

即 Frame Rate,機關 fps,是指 gpu 生成幀的速率,如 33 fps,60fps,越高越好。

螢幕重新整理頻率

即 Refresh Rate 或 Scanning Frequency,機關赫茲/Hz,是指裝置重新整理螢幕的頻率,該值對于特定的裝置來說是個常量,如 60hz。

如下圖,螢幕的重新整理過程是每一行從左到右(行重新整理,水準重新整理,Horizontal Scanning),從上到下(螢幕重新整理,垂直重新整理,Vertical Scanning)。當整個螢幕重新整理完畢,即一個垂直重新整理周期完成,會有短暫的空白期,此時發出 VSync 信号。是以,VSync 中的 V 指的是垂直重新整理中的垂直/Vertical。

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

對于一個特定的裝置,幀率和重新整理頻率沒有必然的大小關系。

VSync 是啥

安卓系統中有 2 種 VSync 信号:螢幕産生的硬體 VSync 和由 SurfaceFlinger 将其轉成的軟體 Vsync 信号。後者經由 Binder 傳遞給 Choreographer。

硬體 VSync 是一個脈沖信号,起到開關或觸發某種操作的作用。

更多資訊請自行複習《計算機組成原理》或《數字電路與邏輯設計》等大學教材(就像考研備考的時候研友感慨的:出來混,遲早要還的,當時沒學好,現在還得接着學)。

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

VSync 有啥作用

單緩存

在第一章我們講到,幀率和重新整理頻率沒有必然的大小關系。先記住這一點。

首先,我們來看下,沒有引入 VSync 時,螢幕顯示圖像的工作流程。

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

如上圖,CPU/GPU 向 Buffer 中生成圖像,螢幕從 Buffer 中取圖像、重新整理後顯示。這是一個典型的生産者——消費者模型。

理想的情況是幀率和重新整理頻率相等,每繪制一幀,螢幕顯示一幀。而實際情況是,二者之間沒有必然的大小關系,如果沒有鎖來控制同步,很容易出現問題。例如,當幀率大于重新整理頻率,當螢幕還沒有重新整理第 n-1 幀的時候,GPU 已經在生成第 n 幀了,從上往下開始覆寫第 n-1 幀的資料,當螢幕開始重新整理第 n-1 幀的時候,Buffer 中的資料上半部分是第 n 幀資料,而下半部分是第 n-1 幀的資料,顯示出來的圖像就會出現上半部分和下半部分明顯偏差的現象,我們稱之為 “tearing”,如下圖:

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

雙重緩存(Double Buffer)

注意,此處的“雙緩沖”和計算機組成原理中的“二級緩存”是兩回事。三重緩存也是如此。

為了解決單緩存的“tearing”問題,雙重緩存和 VSync 應運而生。雙重緩存模型如下圖:

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

兩個緩存區分别為 Back Buffer 和 Frame Buffer。GPU 向 Back Buffer 中寫資料,螢幕從 Frame Buffer 中讀資料。VSync 信号負責排程從 Back Buffer 到 Frame Buffer 的複制操作,可認為該複制操作在瞬間完成。其實,該複制操作是等價後的效果,實際上雙緩沖的實作方式是交換 Back Buffer 和 Frame Buffer 的名字,更具體的說是交換記憶體位址(有沒有聯想到那道經典的筆試題目:“有兩個整型數,如何用最優的方法交換二者的值?”),通過二位運算“與”即可完成,是以可認為是瞬間完成。

雙緩沖的模型下,工作流程這樣的:

在某個時間點,一個螢幕重新整理周期完成,進入短暫的重新整理空白期。此時,VSync 信号産生,先完成複制操作,然後通知 CPU/GPU 繪制下一幀圖像。複制操作完成後螢幕開始下一個重新整理周期,即将剛複制到 Frame Buffer 的資料顯示到螢幕上。

在這種模型下,隻有當 VSync 信号産生時,CPU/GPU 才會開始繪制。這樣,當幀率大于重新整理頻率時,幀率就會被迫跟重新整理頻率保持同步,進而避免“tearing”現象。

注意,當 VSync 信号發出時,如果 GPU/CPU 正在生産幀資料,此時不會發生複制操作。螢幕進入下一個重新整理周期時,從 Frame Buffer 中取出的是“老”資料,而非正在産生的幀資料,即兩個重新整理周期顯示的是同一幀資料。這是我們稱發生了“掉幀”(Dropped Frame,Skipped Frame,Jank)現象。

三重緩存(Triple Buffer)

雙重緩存的缺陷在于:當 CPU/GPU 繪制一幀的時間超過 16 ms 時,會産生 Jank。更要命的是,産生 Jank 的那一幀的顯示期間,GPU/CPU 都是在閑置的。

如下圖,A、B 和 C 都是 Buffer。藍色代表 CPU 生成 Display List,綠色代表 GPU 執行 Display List 中的指令進而生成幀,黃色代表生成幀完成。

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

如果有第三個 Buffer 能讓 CPU/GPU 在這個時候繼續工作,那就完全可以避免第二個 Jank 的發生了!

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

于是就有了三緩存:

了解 VSync前言幀率 vs 螢幕重新整理頻率VSync 是啥VSync 有啥作用更多文章

工作原理同雙緩沖類似,隻是多了一個 Back Buffer。

需要注意的是,第三個緩存并不是總是存在的,隻要當需要的時候才會建立。之是以這樣,是因為三緩存會顯著增加使用者輸入到顯示的延遲時間。如上圖,幀 C 是在第 2 個重新整理周期産生的,但卻是在第 4 個周期顯示的。最壞的情況下,你會同時遇到輸入延遲和卡頓現象。

更多文章

寫部落格的初衷不是分享,而是幫助自己總結整理、深化記憶。

也許本文不值一看,但是下面這些文章則不然:

  • Android Performance Patterns: Understanding VSYNC
  • Google I/O 2012 - For Butter or Worse: Smoothing Out Performance in Android UIs
  • Getting To Know Android 4.1, Part 3: Project Butter - How It Works And What It Added
  • Google I/O 2011: Accelerated Android Rendering
  • Triple Buffering: Why We Love It
  • Android圖形顯示系統(一)