iOS离屏渲染的解释:渲染与cpu、gpu
重開一個(gè)環(huán)境(內(nèi)存、資源、上下文)來完成(部分)圖片的繪制
指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作
意為離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。
紅色代表GPU需要做額外的工作來渲染View,綠色代表GPU無需做額外的工作來處理bitmap。
UIView和CALayer關(guān)系
UIView繼承自UIResponder,可以處理系統(tǒng)傳遞過來的事件,如:UIApplication、UIViewController、UIView,以及所有從UIView派生出來的UIKit類。每個(gè)UIView內(nèi)部都有一個(gè)CALayer提供內(nèi)容的繪制和顯示,并且作為內(nèi)部RootLayer的代理視圖。
CALayer繼承自NSObject類,負(fù)責(zé)顯示UIView提供的內(nèi)容contents。CALayer有三個(gè)視覺元素:背景色、內(nèi)容和邊框,其中,內(nèi)容的本質(zhì)是一個(gè)CGImage。
界面渲染過程
RunLoop有一個(gè)60fps的回調(diào),即每16.7ms繪制一次屏幕,所以view的繪制必須在這個(gè)時(shí)間內(nèi)完成,view內(nèi)容的繪制是CPU的工作,然后把繪制的內(nèi)容交給GPU渲染,包括多個(gè)View的拼接(Compositing)、紋理的渲染(Texture)等等,最后顯示在屏幕上。但是,如果無法是16.7ms內(nèi)完成繪制,就會出現(xiàn)丟幀的問題,一般情況下,如果幀率保證在30fps以上,界面卡頓效果不明顯,那么就需要在33.4ms內(nèi)完成View的繪制,而低于這個(gè)幀率,就會產(chǎn)生卡頓的效果,影響體驗(yàn)。
渲染的過程如下:
UIView的layer層有一個(gè)content,指向一塊緩存,即backing store
UIView繪制時(shí),會調(diào)用drawRect方法,通過context將數(shù)據(jù)寫入backing store
在backing store寫完后,通過render server交給GPU去渲染,將backing store中的bitmap數(shù)據(jù)顯示在屏幕上
離屏渲染
在使用圓角、陰影和遮罩等視圖功能的時(shí)候,圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制,所有就需要在屏幕外的上下文中渲染,即離屏渲染。
離屏渲染卡頓原因
離屏渲染之所以會特別消耗性能,是因?yàn)橐獎(jiǎng)?chuàng)建一個(gè)屏幕外的緩沖區(qū),然后從當(dāng)屏緩沖區(qū)切換到屏幕外的緩沖區(qū),然后再完成渲染;其中,創(chuàng)建緩沖區(qū)和切換上下文最消耗性能,而繪制其實(shí)不是性能損耗的主要原因。
設(shè)置了以下屬性時(shí),就會觸發(fā)離屏繪制:
shouldRasterize(光柵化)
masks(遮罩)
shadows(陰影)
edge antialiasing(抗鋸齒)
group opacity(不透明)
復(fù)雜形狀設(shè)置圓角等
漸變
屏幕渲染類型
CPU計(jì)算好顯示內(nèi)容提交到GPU,GPU渲染完成后將渲染結(jié)果放入幀緩沖區(qū),隨后視頻控制器會按照VSync信號逐行讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。
屏幕渲染有如下三種:
GPU中的屏幕渲染:
1、On-Screen Rendering
意為當(dāng)前屏幕渲染,指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行
2、Off-Screen Rendering
意為離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作
3、CPU中的離屏渲染(特殊離屏渲染,即不在GPU中的渲染)
如果我們重寫了drawRect方法,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作,就涉及到了CPU渲染
CoreGraphic通常是線程安全的,所以可以進(jìn)行異步繪制,顯示的時(shí)候再放回主線程
https://www.cnblogs.com/fishbay/p/7576176.html
為什么會使用離屏渲染
當(dāng)使用圓角,陰影,遮罩的時(shí)候,圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制,所以就需要屏幕外渲染被喚起。
屏幕外渲染并不意味著軟件繪制,但是它意味著圖層必須在被顯示之前在一個(gè)屏幕外上下文中被渲染(不論CPU還是GPU)。
所以當(dāng)使用離屏渲染的時(shí)候會很容易造成性能消耗,因?yàn)樵贠PENGL里離屏渲染會單獨(dú)在內(nèi)存中創(chuàng)建一個(gè)屏幕外緩沖區(qū)并進(jìn)行渲染,而屏幕外緩沖區(qū)跟當(dāng)前屏幕緩沖區(qū)上下文切換是很耗性能的。
作者:齊滇大圣
鏈接:https://www.jianshu.com/p/6d24a4c29e18
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。
一、概念理解
OpenGL中,GPU屏幕渲染有以下兩種方式:
○ On-Screen Rendering
意為當(dāng)前屏幕渲染,指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行。
○ Off-Screen Rendering
意為離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。
二、離屏渲染的是是非非
相比于當(dāng)前屏幕渲染,離屏渲染的代價(jià)是很高的,主要體現(xiàn)在兩個(gè)方面:
· 創(chuàng)建新緩沖區(qū)
要想進(jìn)行離屏渲染,首先要?jiǎng)?chuàng)建一個(gè)新的緩沖區(qū)。
· 上下文切換
離屏渲染的整個(gè)過程,需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上有需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕。而上下文環(huán)境的切換是要付出很大代價(jià)的。
三、離屏渲染觸發(fā)方式
設(shè)置了以下屬性時(shí),都會觸發(fā)離屏繪制:
· shouldRasterize(光柵化)
· masks(遮罩)
· shadows(陰影)
· edge antialiasing(抗鋸齒)
· group opacity(不透明)
需要注意的是,如果shouldRasterize被設(shè)置成YES,在觸發(fā)離屏繪制的同時(shí),會將光柵化后的內(nèi)容緩存起來,如果對應(yīng)的layer及其sublayers沒有發(fā)生改變,在下一幀的時(shí)候可以直接復(fù)用。這將在很大程度上提升渲染性能。
而其它屬性如果是開啟的,就不會有緩存,離屏繪制會在每一幀都發(fā)生。
四、另一種特殊的“離屏渲染”
按照之前的說法,如果將不在GPU的當(dāng)前屏幕緩沖區(qū)中進(jìn)行的渲染都稱為離屏渲染,那么就還有另一種特殊的“離屏渲染”方式:CPU渲染。
如果我們重寫了drawRect方法,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作,就涉及到了CPU渲染。整個(gè)渲染過程由CPU在App內(nèi)同步地完成,渲染得到的bitmap最后再交由GPU用于顯示。
五、Instruments
Instruments的Core Animation工具中有幾個(gè)和離屏渲染相關(guān)的檢查選項(xiàng):
· Color Offscreen-Rendered Yellow
開啟后會把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問題。
· Color Hits Green and Misses Red
如果shouldRasterize被設(shè)置成YES,對應(yīng)的渲染結(jié)果會被緩存,如果圖層是綠色,就表示這些緩存被復(fù)用;如果是紅色就表示緩存會被重復(fù)創(chuàng)建,這就表示該處存在性能問題了。
六、如何抉擇
現(xiàn)在擺在我們面前得有三個(gè)選擇:當(dāng)前屏幕渲染、離屏渲染、CPU渲染,該用哪個(gè)呢?這需要根據(jù)具體的使用場景來決定。
· 盡量使用當(dāng)前屏幕渲染
鑒于離屏渲染、CPU渲染可能帶來的性能問題,一般情況下,我們要盡量使用當(dāng)前屏幕渲染。
· 離屏渲染 VS CPU渲染
由于GPU的浮點(diǎn)運(yùn)算能力比CPU強(qiáng),CPU渲染的效率可能不如離屏渲染;但如果僅僅是實(shí)現(xiàn)一個(gè)簡單的效果,直接使用CPU渲染的效率又可能比離屏渲染好,畢竟離屏渲染要涉及到緩沖區(qū)創(chuàng)建和上下文切換等耗時(shí)操作。
總之,具體的選擇應(yīng)該由性能測試結(jié)果來決定。
七、寫在最后
在趙巖同學(xué)的點(diǎn)撥下才理解了離屏渲染的概念,在此表示感謝!
如理解有誤還請大家指出。
http://imgtec.eetrend.com/d6-imgtec/blog/2018-08/17019.html
在第一章的1.2節(jié)中有提到渲染的流程圖,我們再更深入點(diǎn),先看看最基本的渲染通道流程:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
注:iOS的GPU渲染機(jī)制是Tile-Based的,而Tile-BasedGPU也是現(xiàn)在移動設(shè)備的主流;
我們再來看看需要Offscreen Render的渲染通道流程:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
一般情況下,OpenGL會將應(yīng)用提交到Render Server的動畫直接渲染顯示(基本的Tile-Based渲染流程),但對于一些復(fù)雜的圖像動畫的渲染并不能直接渲染疊加顯示,而是需要根據(jù)Command Buffer分通道進(jìn)行渲染之后再組合,這一組合過程中,就有些渲染通道是不會直接顯示的;對比基本渲染通道流程和Masking渲染通道流程圖,我們可以看到到Masking渲染需要更多渲染通道和合并的步驟;而這些沒有直接顯示在屏幕的上的通道(如上圖的 Pass 1 和 Pass 2)就是Offscreen Rendering Pass。
Offscreen Render為什么卡頓,從上圖我們就可以知道,Offscreen Render需要更多的渲染通道,而且不同的渲染通道間切換需要耗費(fèi)一定的時(shí)間,這個(gè)時(shí)間內(nèi)GPU會閑置,當(dāng)通道達(dá)到一定數(shù)量,對性能也會有較大的影響;
那哪些情況會Offscreen Render呢?
1)drawRect 2)layer.shouldRasterize=true; 3)有mask或者是陰影(layer.masksToBounds,layer.shadow*); 4)Text(UILabel,CATextLayer,CoreText,etc) ...
注:layer.cornerRadius,layer.borderWidth,layer.borderColor并不會Offscreen Render,因?yàn)檫@些不需要加入Mask。
還有更多與Offscreen Render以及動畫圖形優(yōu)化相關(guān)的知識,請認(rèn)真觀看WWDC。
參考:
WWDC2011 #121 Understanding UIKit Rendering
WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
http://oncenote.com/2015/12/08/How-to-build-UI/
總結(jié)
以上是生活随笔為你收集整理的iOS离屏渲染的解释:渲染与cpu、gpu的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理论物理极础10:泊松括号,角动量和对称
- 下一篇: 我的世界红石大炮怎么造的(我的世界红石大