離屏渲染

離屏渲染是在iOS開發(fā)過程中脫離不了的話題骨杂,那么什么是離屏渲染以及哪些情況會導(dǎo)致離屏渲染呢?以及離譜渲染有哪些優(yōu)勢和劣勢芍殖?

首先看下面一段代碼疾嗅,那種模式會觸發(fā)離屏渲染呢外厂?

? ? ? ?//按鈕存在背景圖片,并且設(shè)置圓角

? ? ? ? let?btn1 =UIButton.init(type: .custom)

? ? ? ? btn1.frame=CGRect.init(x:100, y:100, width:44, height:44)

? ? ? ? btn1.layer.cornerRadius=5.0

? ? ? ? self.view.addSubview(btn1)

? ? ? ? btn1.setImage(UIImage.init(named:"tabbar_discover_hl"), for: .normal)

? ? ? ? btn1.clipsToBounds=true


? ? ? ? //按鈕不存在背景圖片代承,并且設(shè)置圓角

? ? ? ? let?btn2 =UIButton(type: .custom)

? ? ? ? btn2.frame=CGRect.init(x:100, y:180, width:44, height:44)

? ? ? ? btn2.layer.cornerRadius=5.0

? ? ? ? btn2.backgroundColor = .blue

? ? ? ? self.view.addSubview(btn2)

? ? ? ? btn2.clipsToBounds=true


? ? ? ? //圖片設(shè)置了背景色+背景圖片

? ? ? ? let?imgv1 =UIImageView(frame:CGRect.init(x:100, y:260, width:44, height:44))

? ? ? ? imgv1.image=UIImage.init(named:"tabbar_friends_hl")

? ? ? ? imgv1.backgroundColor = .blue

? ? ? ? imgv1.layer.cornerRadius=5.0

? ? ? ? imgv1.layer.masksToBounds=true

? ? ? ? self.view.addSubview(imgv1)


? ? ? ? //圖片只設(shè)置了背景色

? ? ? ? let?imgv2 =UIImageView(frame:CGRect.init(x:100, y:340, width:44, height:44))

? ? ? ? imgv2.image=UIImage.init(named:"tabbar_mine_hl")

? ? ? ? imgv2.layer.cornerRadius=5.0

? ? ? ? imgv2.layer.masksToBounds=true

? ? ? ? self.view.addSubview(imgv2)

XCode查看離屏渲染
測試效果

從上圖可知汁蝶,1、3中寫法觸發(fā)了離屏渲染论悴,2掖棉、4兩種寫法未觸發(fā)離屏渲染;

APP渲染流程

渲染流水線示意圖

從圖中可以看到(圖片來源:WWDC)膀估,Application以及RenderServer部分是運(yùn)行在CPU上的幔亥,Application處理好數(shù)據(jù)后,提交到Render Server察纯,然后Core Animation在會將具體操作轉(zhuǎn)換成GPU的Draw calls(OpenGL/Metal)帕棉;也就是CPU+GPU共同完成渲染工作

什么是離屏渲染:

如果要在顯示屏上顯示內(nèi)容,我們至少需要一塊與屏幕像素數(shù)據(jù)量一樣大的frame buffer饼记,作為像素數(shù)據(jù)存儲區(qū)域香伴,而這也是GPU存儲渲染結(jié)果的地方。如果有時因為面臨一些限制具则,無法把渲染結(jié)果直接寫入frame buffer即纲,而是先暫存在另外的內(nèi)存區(qū)域,之后再寫入frame buffer博肋,那么這個過程被稱之為離屏渲染(offscreen buffer)

通過下面兩幅圖結(jié)合上面的概念可以清晰離屏渲染的原理:

渲染結(jié)果直接給到FrameBuffer崇裁,然后展示到屏幕上
渲染結(jié)果線給到offscreenBuffer,在到FrameBuffer束昵,然后展示到屏幕上

那么離屏渲染是如何工作的呢拔稳?通過圓角觸發(fā)離屏渲染來進(jìn)行分析

設(shè)置圓角觸發(fā)offscreen render

從上圖可知,給UIButton設(shè)置背景圖片并且添加圓角涉及3部分內(nèi)容

1锹雏、backgroundColor

2巴比、contents

3、borderColor/borderWidth

當(dāng)每一部分layer會獨(dú)立繪制礁遵,然后保存到offscreenBuffer中轻绞,當(dāng)全部layer繪制后,對這3部分整體進(jìn)行添加圓角,所以需要先存入到offscreenBuffer中佣耐,否則繪制完會自動銷毀政勃,當(dāng)設(shè)置圓角時無法獲取到之前的layer;

繪制原理圖示

GPU離屏渲染兼砖,“畫家畫法”

通過渲染流水線示意圖中我們可以看到奸远,主要的渲染操作都是由CoreAnimation的Render Server模塊既棺,通過調(diào)用顯卡驅(qū)動所提供的OpenGL/Metal接口來執(zhí)行的。通常對于每一層layer懒叛,Render Server會遵循“畫家算法”丸冕,按次序輸出到frame buffer,后一層覆蓋前一層薛窥,就能得到最終的顯示結(jié)果(值得一提的是胖烛,與一般桌面架構(gòu)不同,在iOS中诅迷,設(shè)備主存和GPU的顯存共享物理內(nèi)存佩番,這樣可以省去一些數(shù)據(jù)傳輸開銷)

然而有些場景并沒有那么簡單。作為“畫家”的GPU雖然可以一層一層往畫布上進(jìn)行輸出罢杉,但是無法在某一層渲染完成之后趟畏,再回過頭來擦除/改變其中的某個部分——因為在這一層之前的若干層layer像素數(shù)據(jù),已經(jīng)在渲染中被永久覆蓋了屑那。這就意味著,對于每一層layer艘款,要么能找到一種通過單次遍歷就能完成渲染的算法持际,要么就不得不另開一塊內(nèi)存,借助這個臨時中轉(zhuǎn)區(qū)域來完成一些更復(fù)雜的哗咆、多次的修改/剪裁操作

當(dāng)sublayer繪制到屏幕上之后蜘欲,就會將sublayer從幀緩存區(qū)移除,從而節(jié)省空間


將要混合的內(nèi)容各自渲染完晌柬,暫時存在離屏緩存區(qū)
等所有l(wèi)ayer全部繪制完成姥份,從offscreenBuffer中獲取數(shù)據(jù),進(jìn)行組合

通過上面的理解年碘,可以發(fā)現(xiàn)澈歉,App需要進(jìn)行額外的渲染和合并,必須使用Offscreen Buffer屿衅,然后進(jìn)行組合放入到Frame Buffer中埃难,然后現(xiàn)在到屏幕上

離屏渲染性能問題:

1,需要額外的存儲空間涤久,

2涡尘,將結(jié)果從Offscreen buffer轉(zhuǎn)存到Frame Buffer中也是需要時間的

Offscreen Buffer的空間也是有限制的(限制大小是屏幕像素大小的2.5倍)

既然離屏渲染容易帶來性能問題,為什么還要用呢响迂?

1.非常多的特殊效果考抄,并不能一次用一個圖層就能畫出來,所以需要使用額外的offscreen Buffer來保持中間狀態(tài)(不得不使用),比如:圓角蔗彤,陰影

2.能帶來效率的優(yōu)勢:既然效果會多次出現(xiàn)在屏幕上川梅,可提前渲染好疯兼,保存在offscreen Buffer中,從而達(dá)到復(fù)用的結(jié)果? 比如:光珊化shouldRasterize

常見離屏渲染:

能引起離屏渲染

所以我們在項目開發(fā)的過程中挑势,根據(jù)實際情況進(jìn)行相關(guān)的優(yōu)化镇防,突出其優(yōu)勢避免其劣勢

特別說明:關(guān)于光珊化并不是所有的光珊化都會帶來性能問題,以下是關(guān)于光珊化的使用建議

光珊化使用建議
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末潮饱,一起剝皮案震驚了整個濱河市来氧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌香拉,老刑警劉巖啦扬,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異凫碌,居然都是意外死亡扑毡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門盛险,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞄摊,“玉大人,你說我怎么就攤上這事苦掘』恢模” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵鹤啡,是天一觀的道長惯驼。 經(jīng)常有香客問我,道長递瑰,這世上最難降的妖魔是什么祟牲? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮抖部,結(jié)果婚禮上说贝,老公的妹妹穿的比我還像新娘。我一直安慰自己慎颗,他們只是感情好狂丝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著哗总,像睡著了一般几颜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上讯屈,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天蛋哭,我揣著相機(jī)與錄音,去河邊找鬼涮母。 笑死谆趾,一個胖子當(dāng)著我的面吹牛躁愿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沪蓬,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼彤钟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了跷叉?” 一聲冷哼從身側(cè)響起逸雹,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎云挟,沒想到半個月后梆砸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡园欣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年帖世,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沸枯。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡日矫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绑榴,到底是詐尸還是另有隱情哪轿,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布彭沼,位于F島的核電站缔逛,受9級特大地震影響备埃,放射性物質(zhì)發(fā)生泄漏姓惑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一按脚、第九天 我趴在偏房一處隱蔽的房頂上張望于毙。 院中可真熱鬧,春花似錦辅搬、人聲如沸唯沮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽介蛉。三九已至,卻和暖如春溶褪,著一層夾襖步出監(jiān)牢的瞬間币旧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工猿妈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吹菱,地道東北人巍虫。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像鳍刷,于是被迫代替她去往敵國和親占遥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360