相對(duì)于 CPU 來(lái)說(shuō),GPU 能干的事情比較單一:接收提交的紋理(Texture)和頂點(diǎn)描述(三角形),應(yīng)用變換(transform)、混合并渲染,然后輸出到屏幕上。通常你所能看到的內(nèi)容,主要也就是紋理(圖片)和形狀(三角模擬的矢量圖形)兩類。
紋理的渲染
所有的 Bitmap,包括圖片、文本、柵格化的內(nèi)容,最終都要由內(nèi)存提交到顯存,綁定為 GPU Texture。不論是提交到顯存的過(guò)程,還是 GPU 調(diào)整和渲染 Texture 的過(guò)程,都要消耗不少 GPU 資源。當(dāng)在較短時(shí)間顯示大量圖片時(shí)(比如 TableView 存在非常多的圖片并且快速滑動(dòng)時(shí)),CPU 占用率很低,GPU 占用非常高,界面仍然會(huì)掉幀。避免這種情況的方法只能是盡量減少在短時(shí)間內(nèi)大量圖片的顯示,盡可能將多張圖片合成為一張進(jìn)行顯示。
當(dāng)圖片過(guò)大,超過(guò) GPU 的最大紋理尺寸時(shí),圖片需要先由 CPU 進(jìn)行預(yù)處理,這對(duì) CPU 和 GPU 都會(huì)帶來(lái)額外的資源消耗。目前來(lái)說(shuō),iPhone 4S 以上機(jī)型,紋理尺寸上限都是 4096x4096,更詳細(xì)的資料可以看這里:iosres.com。所以,盡量不要讓圖片和視圖的大小超過(guò)這個(gè)值。
視圖的混合 (Composing)
當(dāng)多個(gè)視圖(或者說(shuō) CALayer)重疊在一起顯示時(shí),GPU 會(huì)首先把他們混合到一起。如果視圖結(jié)構(gòu)過(guò)于復(fù)雜,混合的過(guò)程也會(huì)消耗很多 GPU 資源。為了減輕這種情況的 GPU 消耗,應(yīng)用應(yīng)當(dāng)盡量減少視圖數(shù)量和層次,并在不透明的視圖里標(biāo)明 opaque 屬性以避免無(wú)用的 Alpha 通道合成。當(dāng)然,這也可以用上面的方法,把多個(gè)視圖預(yù)先渲染為一張圖片來(lái)顯示。
圖形的生成
CALayer 的 border、圓角、陰影、遮罩(mask),CASharpLayer 的矢量圖形顯示,通常會(huì)觸發(fā)離屏渲染(offscreen rendering),而離屏渲染通常發(fā)生在 GPU 中。當(dāng)一個(gè)列表視圖中出現(xiàn)大量圓角的 CALayer,并且快速滑動(dòng)時(shí),可以觀察到 GPU 資源已經(jīng)占滿,而 CPU 資源消耗很少。這時(shí)界面仍然能正?;瑒?dòng),但平均幀數(shù)會(huì)降到很低。為了避免這種情況,可以嘗試開啟 CALayer.shouldRasterize 屬性,但這會(huì)把原本離屏渲染的操作轉(zhuǎn)嫁到 CPU 上去。對(duì)于只需要圓角的某些場(chǎng)合,也可以用一張已經(jīng)繪制好的圓角圖片覆蓋到原本視圖上面來(lái)模擬相同的視覺效果。最徹底的解決辦法,就是把需要顯示的圖形在后臺(tái)線程繪制為圖片,避免使用圓角、陰影、遮罩等屬性。
更多建議: