iOS"離屏渲染"整理總結(jié)
2019-11-07 23:46:59
供稿:網(wǎng)友
 
一.渲染機(jī)制
CPU 計(jì)算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū),隨后視頻控制器會(huì)按照 VSync 信號(hào)逐行讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過(guò)可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。
二.GPU屏幕渲染有兩種方式
1>On-Screen Rendering:意為當(dāng)前屏幕渲染
指GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行
2>Off-Screen Rendering:離屏渲染
指GPU在當(dāng)前屏幕緩沖區(qū)以外新開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作
三.兩種渲染方式比較
相比于當(dāng)前屏幕渲染,離屏渲染的代價(jià)是很高的,主要體現(xiàn)在兩個(gè)方面:
1>創(chuàng)建新緩沖區(qū)
要想進(jìn)行離屏渲染,首先要?jiǎng)?chuàng)建一個(gè)新的緩沖區(qū)。
2>上下文切換
離屏渲染的整個(gè)過(guò)程,需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上有需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕。而上下文環(huán)境的切換是要付出很大代價(jià)的。
四.還有一種特殊的離屏渲染指:CPU渲染
如果重寫(xiě)了drawRect方法,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作,就涉及到了CPU渲染。整個(gè)渲染過(guò)程由CPU在App內(nèi) 同步地完成,渲染得到的bitmap最后再交由GPU用于顯示。CoreGraphic通常是線程安全的,所以可以進(jìn)行異步繪制,顯示的時(shí)候再放回主線程,一個(gè)簡(jiǎn)單的異步繪制過(guò)程大致如下:
- (void)display {   dispatch_async(backgroundQueue, ^{       CGContextRef ctx = CGBitmapContextCreate(...);       // draw in context...       CGImageRef img = CGBitmapContextCreateImage(ctx);       CFRelease(ctx);       dispatch_async(mainQueue, ^{           layer.contents = img;       });   });}五.離屏渲染的觸發(fā)方式
??shadows(陰影)
??shouldRasterize(光柵化)
??masks(遮罩)
??edge antialiasing(抗鋸齒)
??group opacity(不透明)
??復(fù)雜形狀設(shè)置圓角等…
??漸變
??UILabel, CATextLayer, Core Text……
小插曲
日程經(jīng)常打交道的TableViewCell,TableViewCell的重繪是很頻繁的(因?yàn)镃ell的復(fù)用),如果Cell的內(nèi)容不斷變化,則Cell需要不斷重繪,如果此時(shí)設(shè)置了cell.layer可光柵化。則會(huì)造成大量的離屏渲染,降低圖形性能。
值得注意的是,如果shouldRasterize被設(shè)置成YES,在觸發(fā)離屏繪制的同時(shí),會(huì)將光柵化后的內(nèi)容緩存起來(lái),如果對(duì)應(yīng)的layer及其sublayers沒(méi)有發(fā)生改變,在下一幀的時(shí)候可以直接復(fù)用。這將在很大程度上提升渲染性能
而其它屬性如果是開(kāi)啟的,就不會(huì)有緩存,離屏繪制會(huì)在每一幀都發(fā)生。
六.為什么有時(shí)會(huì)使用離屏渲染
當(dāng)使用圓角,陰影,遮罩的時(shí)候,圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制,所以就需要屏幕外渲染被喚起。屏幕外渲染并不意味著軟件繪制,但是它意味著圖層必須在被顯示之前在一個(gè)屏幕外上下文中被渲染(不論CPU還是GPU).所以當(dāng)使用離屏渲染的時(shí)候會(huì)很容易造成性能消耗,因?yàn)樵?code>OpenGL里離屏渲染會(huì)單獨(dú)在內(nèi)存中創(chuàng)建一個(gè)屏幕外緩沖區(qū)并進(jìn)行渲染,而屏幕外緩沖區(qū)跟當(dāng)前屏幕緩沖區(qū)上下文切換是很耗性能的。
七.Instruments工具檢測(cè)
使用Instruments下的Core Animation有相關(guān)的檢查選項(xiàng)
1>Color Offscreen-Rendered Yellow
開(kāi)啟后會(huì)把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問(wèn)題。
2>Color Hits Green and Misses Red
如果shouldRasterize被設(shè)置成YES,對(duì)應(yīng)的渲染結(jié)果會(huì)被緩存,如果圖層是綠色,就表示這些緩存被復(fù)用;如果是紅色就表示緩存會(huì)被重復(fù)創(chuàng)建,這就表示該處存在性能問(wèn)題了。
八.該選擇哪種實(shí)現(xiàn)方式?
1>盡量使用當(dāng)前屏幕渲染
離屏渲染、CPU渲染可能帶來(lái)的性能問(wèn)題,一般情況下,我們要盡量使用當(dāng)前屏幕渲染。
2>離屏渲染  和  CPU渲染
由于GPU的浮點(diǎn)運(yùn)算能力比CPU強(qiáng),CPU渲染的效率可能不如離屏渲染;但如果僅僅是實(shí)現(xiàn)一個(gè)簡(jiǎn)單的效果,直接使用CPU渲染的效率又可能比離屏渲染好,畢竟離屏渲染要涉及到緩沖區(qū)創(chuàng)建和上下文切換等耗時(shí)操作。
九.iOS系統(tǒng)版本區(qū)別
參考學(xué)習(xí)以下博文
博文一(王中周)    博文二  博文三   博文四(全面)