一步步學(xué)習(xí)計算機視覺 in IOS番外篇(三)離屏渲染

什么是離屏渲染

首先我們來看一下渲染架構(gòu):


image.png

CPU 計算好顯示內(nèi)容提交到 GPU,如果要在顯示屏上顯示內(nèi)容,我們至少需要一塊與屏幕像素數(shù)據(jù)量一樣大的幀緩沖區(qū)(frame buffer),作為像素數(shù)據(jù)存儲區(qū)域,而這也是GPU存儲渲染結(jié)果的地方。GPU 渲染完成后將渲染結(jié)果放入frame buffer,隨后視頻控制器會按照 VSync 信號逐行讀取frame buffer的數(shù)據(jù),經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。顯示完成后,frame buffer中的數(shù)據(jù)直接丟棄

如果有時因為面臨一些限制,無法把渲染結(jié)果直接寫入frame buffer,而是先暫存在另外的內(nèi)存區(qū)域,之后再寫入frame buffer,那么這個過程被稱之為離屏渲染。

image.png

這里要注意,被iOS認(rèn)定的離屏渲染是GPU產(chǎn)生的,如果重寫了drawRect方法,并且使用任何Core Graphics 的技術(shù)進行了繪制操作,就涉及到CPU渲染。這種CPU渲染可以成為軟件渲染,不會被iOS系統(tǒng)認(rèn)定為離屏渲染。

離屏渲染帶來的影響

1)額外的內(nèi)存

離屏渲染需要開放一塊內(nèi)存存放渲染數(shù)據(jù),這部分內(nèi)存最大為屏幕展示的2.5倍

2)上下文切換

離屏渲染的整個過程需要切換上下文環(huán)境,先從當(dāng)前屏幕切換到離屏,等結(jié)束后,又要將上下文環(huán)境切換回來。雖然在iOS中,設(shè)備主存和GPU的顯存共享物理內(nèi)存,這樣可以省去一些數(shù)據(jù)傳輸開銷,但是還是要占用系統(tǒng)資源。

離屏渲染的原因

先說下我的理解:

離屏渲染是由于渲染層之間存在依賴引發(fā)的。

在上面的渲染流水線示意圖中我們可以看到,主要的渲染操作都是由CoreAnimation的Render Server模塊,通過調(diào)用顯卡驅(qū)動所提供的OpenGL/Metal接口來執(zhí)行的。通常對于每一層layer,Render Server會遵循“畫家算法”,按次序輸出到frame buffer,后一層 After Layer 會覆蓋前一層 Before Layer,就能得到最終的顯示結(jié)果。

但是,如果此時After Layer的渲染數(shù)據(jù)是半透明的,需要混合Before Layer的數(shù)據(jù),按照正常的渲染流程,此時frame buffer中Before Layer已經(jīng)被丟棄了,根本無法進行混合。為了保留Before Layer,iOS開辟了離屏渲染緩沖區(qū),對Before Layer進行存儲。

圓角 與 masksToBounds

首先我們要了解 CALayer的層次結(jié)構(gòu):CALayer由背景色backgroundColor、內(nèi)容contents、邊緣borderWidth&borderColor構(gòu)成

image.png

cornerRadius的文檔中明確說明:
cornerRadius的設(shè)置只對 CALayer 的背景色層和邊緣層起作用

當(dāng)我們只配置cornerRadius時,背景色層和邊緣層生成圓角,內(nèi)容層的渲染數(shù)據(jù)是直接覆蓋背景色層,邊緣層的數(shù)據(jù)也是同樣,這時候不會觸發(fā)離屏渲染

當(dāng)我們配置 masksToBounds的時候,這個時候,內(nèi)容層也要被裁剪圓角,而裁剪方式依賴邊緣層。還記得我們說過的,離屏渲染是由于渲染層之間存在依賴引發(fā)的。現(xiàn)在內(nèi)容層與邊緣層就相互依賴了,從而導(dǎo)致了離屏渲染。

常見的觸發(fā)離屏渲染情況

  1. 需要進行裁剪的 layer (layer.masksToBounds / view.clipsToBounds)

在View上設(shè)置相同形狀的Mask View,要背裁剪掉的部分設(shè)置成背景色

image.png
  1. 設(shè)置了組透明度為 YES,并且透明度不為 1 的 layer (layer.allowsGroupOpacity/ layer.opacity)

這個只能盡量不要使用

  1. 添加了投影的 layer (layer.shadow*)

使用陰影路徑計算

  1. 繪制了文字的 layer (UILabel, CATextLayer, Core Text 等)
    盡量使用Label代替

  2. 采用了光柵化的 layer (layer.shouldRasterize)
    這是主動進行離屏渲染,提高渲染效率.

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容