屏幕刷新原理


說到界面卡頓,基本上就是兩個原因:CPU耗時任務、GPU渲染耗時。
優化方案基本也是從這兩個方向入手。但是為什么耗時的操作會導致丟幀?以及撕裂是怎么出現的?單緩沖、二級緩沖、三緩沖又是什么?
我們知道在整個顯示過程中,需要 CPU、GPU、顯示屏 三個模塊協調工作,大致流程如下:

  1. CPU 負責計算數據,把計算好數據交給 GPU
  2. GPU 會對圖形數據進行渲染,渲染好后放到緩沖區 buffer 里存起來
  3. 顯示屏 以特定的 屏幕刷新率 把 buffer 里的數據呈現到屏幕上

屏幕發光原理

我們先了解一下,幾種屏幕的發光原理,方面后面理解屏幕刷新流程:

  • CRT 顯示器由很多熒光點組成,發光管是一個射線管,靠電子束高速擊打熒光粉發光(據說離的太近,會有輻射)
  • LED 顯示器是靠二極管發光,一直常亮的,自身有固定的刷新率(一般是 60HZ)

 

屏幕刷新過程

從發光原理來看,我們知道有一個電子束(類似掃描搶)的東西存在,屏幕的刷新就從這開始了:

  • 從初始位置(第一行左上角)開始掃描,從左到右,進行水平掃描(Horizontal Scanning
  • 每一行掃描完成,掃描線會切換到下一行起點,這個切換過程叫做水平消隱,簡稱 hblank(horizontal blank interval),並發送水平同步信號(horizontal synchronization,又稱行同步)
  • 依次類推,整個屏幕(一個垂直周期)掃描完成后,顯示器就可以呈現一幀的畫面
  • 屏幕最后一行(一個垂直周期)掃描完成后,需要重返左上角初始位置,這個過程叫垂直消隱,簡稱 vblank(vertical blank interval
  • 掃描線回到初始位置之后,准備掃描下一幀,同時發出垂直同步信號(vertical synchronization,又稱場同步)。

這里解釋一下幾個名詞:

# 垂直消隱

完成一幀的掃描后,掃描點會回到初始點,准備掃描下一幀,這個過程會花一點時間,會有短暫的空白期。為了避免看到一個斜線顯示在屏幕上,需要把掃描點變blank,這個過程就是垂直消隱,也叫場消隱。

# 垂直同步信號

當掃描點回到初始點,在准備掃描下一幀的時候,同時發出垂直同步信號,告訴顯卡可以渲染下一幀了。這種情況下,顯卡的渲染能力會受到 屏幕刷新率 的制約。如果顯示器刷新頻率是60Hz,顯卡幀率最多只會達到60。對於高幀率的顯卡,開啟垂直同步自然會制約其性能發揮。

# 屏幕刷新頻率

Refresh RateScanning Frequency ,是指屏幕刷新的頻率,單位赫茲/Hz,一般是 60hz。也就是以這個頻率發出 垂直同步信號,告訴 GPU 可以往 buffer 里寫數據了,即渲染下一幀。

 

CPU GPU工作流程

我們再回來看第一部分 CPU 和 GPU,他們是如何工作的呢?

  1. CPU 繪制 View 樹,計算好圖形數據,提交到系統內存中
  2. CPU提交完成以后,通知 GPU 計算完成,系統總線會把數據拷貝到 GPU 的顯存里
  3. GPU 開始處理數據,以特定的 顯卡幀率 把數據寫到顯卡的緩沖區里
  4. 視頻控制器收到 垂直同步信號 ,逐行讀取幀緩沖區的數據,交給顯示器

CPU、GPU 的計算和交互還是挺復雜的,涉及到虛擬內存地址映射,我們暫且不深入研究了,這里我們主要看第三步:

GPU 以特定的幀率把處理結果寫到顯卡的緩沖區里 

這里我們就需要了解單緩沖、雙緩沖、垂直同步信號的概念了,我們一個一個來看:

#顯卡幀率

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

#單緩沖

單緩沖,也就是只有一個緩沖區(buffer),GPU 向 buffer 中寫入數據,屏幕從 buffer 中取圖像數據、刷新后顯示,理想的情況是 顯卡幀率 屏幕刷新頻率 相等,每繪制一幀,屏幕顯示一幀。而實際情況是,二者之間沒有必然的大小關系,如果沒有同步機制,很容易出現問題。

  1. 例如,當顯卡幀率大於屏幕刷新頻率,屏幕准備刷新第2幀的時候,GPU 已經在生成第3幀了,就會覆蓋第2幀的部分數據。
  2. 當屏幕開始刷新第2幀的時候,緩沖區中的數據一部分是第3幀數據,一部分是第2幀的數據,顯示出來的圖像就會出現明顯的偏差,也就是撕裂(tearing)。

#雙緩沖

為了單緩沖的撕裂和效率問題,雙緩沖誕生了。
雙緩沖有兩個緩沖區:frame bufferback buffer,GPU 向 back buffer 中寫數據,屏幕從 frame buffer 中讀數據。這樣不僅可以提升效率,而且可以避免因為幀率和刷新率不一致,導致圖像數據錯亂。
但是這兩個 buffer怎么去同步呢?這里就需要 垂直同步信號
當開啟垂直同步后,就會變成這樣:

  1. GPU 會等待 垂直同步信號 發出后,復制 back buffer 的數據到 frame buffer里(交換兩個緩沖區的內存地址)
  2. 渲染下一幀數據,寫到緩沖區里

這樣看來,幀率大於刷新頻率時,幀率就會被迫跟刷新頻率保持同步,從而避免撕裂現象。
需要注意的是,雙緩沖 + 垂直同步信號仍然不能完全保證正常顯示,比如說:

  1. 收到垂直同步信號時,如果 GPU 正在往緩沖區里寫數據,CPU、GPU 繪制一幀的時間超過16ms,也就是一個 屏幕刷新周期 還沒有准備完,這時候兩個緩沖區不會發生復制。
  2. 當屏幕進入下一個刷新周期時,從 frame buffer 中取出的是上一幀數據,即兩個刷新周期顯示的是同一幀數據,也就是掉幀(Jank)。

為此,引入了 三緩沖,但是仍然避免不了卡頓和延遲的現象,這里就不詳細介紹了,可以自行查閱相關資料。

參考鏈接

iOS 保持界面流暢的技巧(ibireme)
理解 VSync
Android 屏幕刷新顯示機制

 

https://laoqingcai.com/ios-screen-refresh/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM