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