離屏渲染就是在當前屏幕緩沖區以外,新開辟一個緩沖區進行操作。
離屏渲染出發的場景有以下:
- 圓角 (maskToBounds并用才會觸發)
- 圖層蒙版
- 陰影
- 光柵化
為什么要有離屏渲染?
大家高中物理應該學過顯示器是如何顯示圖像的:需要顯示的圖像經過CRT電子槍以極快的速度一行一行的掃描,掃描出來就呈現了一幀畫面,隨后電子槍又會回到初始位置循環掃描,形成了我們看到的圖片或視頻。
為了讓顯示器的顯示跟視頻控制器同步,當電子槍新掃描一行的時候,準備掃描的時發送一個水平同步信號(HSync信號),顯示器的刷新頻率就是HSync信號產生的頻率。然后CPU計算好frame等屬性,將計算好的內容交給GPU去渲染,GPU渲染好之后就會放入幀緩沖區。然后視頻控制器會按照HSync信號逐行讀取幀緩沖區的數據,經過可能的數模轉換傳遞給顯示器,就顯示出來了。具體的大家自行查找資料或詢問相關專業人士,這里只參考網上資料做一個簡單的描述。
離屏渲染的代價很高,想要進行離屏渲染,首選要創建一個新的緩沖區,屏幕渲染會有一個上下文環境的一個概念,離屏渲染的整個過程需要切換上下文環境,先從當前屏幕切換到離屏,等結束后,又要將上下文環境切換回來。這也是為什么會消耗性能的原因了。
由于垂直同步的機制,如果在一個 HSync 時間內,CPU 或者 GPU 沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時顯示屏會保留之前的內容不變。這就是界面卡頓的原因。
為什么要避免離屏渲染?
CPU
GPU
在繪制渲染視圖時做了大量的工作。離屏渲染發生在 GPU
層面上,會創建新的渲染緩沖區,會觸發 OpenGL
的多通道渲染管線,圖形上下文的切換會造成額外的開銷,增加 GPU
工作量。如果 CPU
GPU
累計耗時 16.67
毫秒還沒有完成,就會造成卡頓掉幀。
圓角屬性
、蒙層遮罩
都會觸發離屏渲染。指定了以上屬性,標記了它在新的圖形上下文中,在未愈合之前,不可以用于顯示的時候就出發了離屏渲染。
-
在OpenGL中,GPU有2種渲染方式
- On-Screen Rendering:當前屏幕渲染,在當前用于顯示的屏幕緩沖區進行渲染操作
- Off-Screen Rendering:離屏渲染,在當前屏幕緩沖區以外新開辟一個緩沖區進行渲染操作
-
離屏渲染消耗性能的原因
- 需要創建新的緩沖區
- 離屏渲染的整個過程,需要多次切換上下文環境,先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束以后,將離屏緩沖區的渲染結果顯示到屏幕上,又需要將上下文環境從離屏切換到當前屏幕
-
哪些操作會觸發離屏渲染?
- 光柵化,layer.shouldRasterize = YES
- 遮罩,layer.mask
- 圓角,同時設置 layer.masksToBounds = YES、layer.cornerRadius大于0
- 考慮通過 CoreGraphics 繪制裁剪圓角,或者叫美工提供圓角圖片
- 陰影,layer.shadowXXX,如果設置了 layer.shadowPath 就不會產生離屏渲染
更多:iOS面試題合集