opengles 性能調優

https://www.jianshu.com/p/35096e796aa3?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-friends&from=singlemessage&isappinstalled=0html

使用Mali Graphics Debugger調優Unity程序(Killer示例)

96

DonaldWandroid

2015.08.07 21:42* 字數 2891 閱讀 7031評論 5喜歡 17正則表達式

What is MGD

ARM® Mali™ Graphics Debugger的做用之一是針對採用ARM® Mali™ GPU的Android手機,進行app的GPU運行時調試和調優。shell

Why MGD

本文MGD主要用於性能調優。windows

關於GPU性能調優,定性不定量都是耍流氓。
猜是虛的、打嘴炮討論是無用的、運行時正則表達式disable對象是盲目的、Unity Profiler是難於真機調試的、GPA(Intel® Graphics Performance Analyzers)是不一樣平臺的、Unity FrameDebugger是從實現本質決定了不能定量到高於DrawCall精度的。app

另外,本文假設已肯定瓶頸出如今GPU。不然,應優先調優CPU性能。直接使用Unity真機調試是不錯的CPU性能調優手段。框架

Doc & Setup

閱讀[ARM® Mali™ Graphics Debugger User Guide](http://malideveloper.arm.com/downloads/tools/mgd/1.3.2/Mali Graphics Debugger v1.3.2 User Guide.pdf)是瞭解MGD最全面的途徑,裏面包括瞭如何設置MGD和使用MGD。
因爲MGD裏會直接出現大量OpenGL/OpenGL ES的API,因此也可按需查閱AW OpenGL ES 3.0 Programming Guide 2nd Editiontcp

本文以MGDv2.1版本爲基礎進行編寫。編寫完畢後數天(約2015-08-11)得知MGDv3.0已發佈,其改進了體驗和UI框架、FrameBuffer View、支持MRT/DepthBuffer/StencilBuffer的截取、更好的截取性能和截取文件大小優化。詳情可參考官網或[Mali Graphics Debugger 3.0.0 User Guide](http://malideveloper.arm.com/downloads/tools/mgd/3.0/Mali Graphics Debugger v3.0.0 User Guide.pdf)。ide

關於MGD設置,本文爲了內容完整性也精簡地描述以下。(你若已設置好或暫不關心設置,也可跳過如下設置步驟,直接閱讀下面的操做步驟、思考過程和發現killer的問題及其如下章節。)函數

  • 在電腦裝好MGD
  • 準備好Mali GPU的Android手機。基於Mali的設備很多,好比Samsung Galaxy S3等基於Exynos SoC的手機。具體列表見Mali SoC implementation
  • 本文用已Root的Android的設備進行。但未Root也可用,但須要參考上面User Guide,以另外的方式進行。
  • 在電腦上安裝好ADB(Android Debug Bridge),而且把ADB設置到操做系統(windows or OSX)的環境變量中。
  • 鏈接Android設備和電腦。
  • 打開命令行,輸入:
#拷貝mgd版OpenGL ES運行時庫和mgd後臺進程到手機sdcard文件夾
cd /your_computer/path_of_installed_mgd

adb push libGLES_mgd.so /sdcard/
adb push mgddaemon /sdcard/

#準備進入手機進行命令行操做
adb shell
#如下命令在手機中執行
su
#拷貝mgd版OpenGL ES庫和mgd後臺進程到手機system文件夾而且修改成可執行權限
cd /sdcard/cp mgddaemon /system/bin/mgddaemon
chmod 777 /system/bin/mgddaemon
cp libGLES_mgd.so /system/lib/egl/libGLES_mgd.so
chmod 777 /system/lib/egl/libGLES_mgd.so

#Android 4.2 和 4.3切換到mgd版OpenGL ES運行時庫:改egl.cfg配置方式
cp /system/lib/egl/egl.cfg /system/lib/egl/egl.cfg.bak
echo "0 0 mgd" > /system/lib/egl/egl.cfg

#Android 4.4 and 5.0切換到mgd版OpenGL ES運行時庫:文件連接方式
cd /system/lib/egl
ln -s libGLES_mgd.so libGLES.so
ln -s libGLES_mgd.so libEGL_mgd.so
ln -s libGLES_mgd.so libGLESv2_mgd.so
ln -s libGLES_mgd.so libGLESv1_CM_mgd.so

#設置mgddaemon,叫它只調試com.tencent.killer這個進程。這裏應填入你本身的進程id
echo "com.tencent.killer" > /system/lib/egl/processlist.cfg

#先退回到電腦,可能不止一次exit
exit

#準備打通調試信息轉發通道
adb forward tcp:5002 tcp:5002

#再次進入手機,啓動mgd後臺進程
adb shell
su
mgddaemon
  • 在電腦上打開MGD,以下圖點擊Connect按鈕

     

    點擊Connect按鈕,鏈接MGD和設備

  • 運行killer(或你本身的app)
  • MGD成功自動收集killer的GPU運行時調試信息

MGD成功自動收集killer的GPU運行時調試信息

至此,Setup操做已完畢。接下來,須要保持手機和電腦的USB鏈接,進行進一步的調試調優操做,亦可用經過菜單將當前調試數據保存到電腦。

操做步驟、思考過程和發現killer的問題

關於killer

killer(產品名字《獨立防線》)爲咱們項目組一款基於Unity的可FPS/TPS切換、可PVP/PVE的3D射擊遊戲。

第一幀:主角第三人稱狀態,未露出FPS狀態精細武器、無特效

在遊戲中操做,進入戰鬥。並保持主角在主角第三人稱狀態,未露出FPS狀態精細武器、無特效——一個最純粹的戰鬥狀況。

保持主角在主角第三人稱狀態,未露出FPS狀態精細武器、無特效

 

從上圖發現MGD已自動收集GPU數據,非常煩人,此時,可點擊暫停按鈕,暫停遊戲,從而暫停收集。

點擊Toggle Fragment Count按鈕(注意以前的操做步驟如並不是MGD和設備先Connect好了以後才運行app,可能會致使本按鈕沒法點擊),再點擊下一幀,可用收集下一幀的Fragment Shader的信息。這是由於Fragment Shader每每是性能消耗大戶,需優先關注。

點擊*Toggle Fragment Count*按鈕,再點擊下一幀

點擊剛剛收集好Fragment Shader信息的第971幀,點擊Fragment Shaders,而後按指令週期比例排序,可馬上知道哪些shader佔消耗大頭,好比圖中的第877號shader,名字是「Shader 879」。

 

雙擊該877號shader,觀察代碼,可知是用於lightmap場景的shader

第877號Fragment Shader程序

 

因此,可輸出結論一和初步解決方案。

結論一:場景是GPU性能消耗第一大戶,需最優先關注。精簡、優化場景mesh和貼圖、精簡lightmap是可行方法。

再點擊下一個第619號Fragment Shader程序,

第619號Fragment Shader程序

經過經驗可知,爲渲染UI的Shader

 

UGUI的UI-Default.shader

 

因此,可輸出結論二和初步解決方案。

結論二:UI是GPU性能消耗第二大戶。留意到裏面有discard語句,可能帶來性能影響,因此應編寫無clip版本的shader。而且精簡UI、或進行UI紋理打包。

再點擊下一個Shader,發現和UI Shader很類似,只是少了一個顏色的運算,因此也不用有mediump的color_2中間變量。可知是UGUI針對材質顏色爲全白色時的優化版Shader

第622號Fragment Shader程序

 

因此,有結論三。

結論三:UI中,不需用顏色的,應保持此材質顏色爲白色。

至此,當前幀的Fragment Shader權重較高者,皆已列出,剩下的Fragment Shader已變得性價比不高。
需轉移目標,好比,Vertex Shader。
同理,切換至Vertex Shader,按cycle排序,找出性能消耗第一大戶,第880號Vertex Shader。經過裏面的代碼出現「SH」,可知是球諧函數「Spherical Harmonics」,即用Light Probe進行渲染的主角Shader。

第880號Vertex Shader

 

因此,有結論四。

結論四:主角頂點數過多(圖中爲23469個頂點),是形成性能的瓶頸之一。

同時,留意到咱們主角都是距離鏡頭很近的,因此,壓根不須要霧的運算,因此,有結論五。

結論五:主角的Shader,甚至一些在不遠處的敵兵shader,都須要去掉霧運算。

再觀察下一個877號Vertex Shader,留意到是用Light Map進行渲染的場景,因此。

 

第877號Vertex Shader

 

同理,亦能夠有結論六。

結論六:場景,若有可能,最好也去掉霧運算。

至此,第一幀分析基本完畢

第二幀:FPS狀態,露出精細武器,無槍火特效

遊戲戰鬥中是個多變的過程,不一樣時刻的兩個幀顯示的內容可能截然不同。
因此須要更換另外一種狀況進行繼續調優。好比FPS狀態,露出精細武器,無槍火特效。

FPS狀態,露出精細武器,無槍火特效

 

在以前的暫停狀態下,取消點擊收集Fragment數量按鈕(Get the fragment count statistics),不然將會很卡,而後點擊播放按鈕(Resume Tracing),以和第一幀相似的方法進行數據收集。

取消Get the fragment count statistics,才繼續進行操做

 

從收集數據看來,結果和第一幀數據並沒有質變。但因爲知道變化的因素是精細武器自己,因此應特定肯定該Shader的消耗。
此時,若是對武器Shader不熟悉,能夠打開Unity,在Editor重現該狀況,在Editor直接閱讀Shader代碼,以下:

精細武器的Shader:Bumped Specular

根據Shader特徵ShininessGlossNormalmap等,回到MGD,也是按Cycle數從大到小逐個觀察(由於渲染武器的消耗確定不會很小),肯定爲第871號Fragment Shader。

第871號Fragment Shader,用於精細武器的Bumped Specular Fragment Shader

 

因此有結論七:

結論七:精細武器的Shader的Cycle比例(4.6%)和Shader指令,哪怕是用Surface Shader,也不算複雜,不是瓶頸。這多是由於Unity的按平臺編譯Shader的優化結果。

第三幀:FPS狀態,露出精細武器,開火,播放開火特效

FPS狀態,露出精細武器,開火,播放開火特效

 

繼續採集數據。而且點擊開火,觸發開火特效,而後馬上點擊MGD暫停,並進行相似採集。發現有如下新的問題shader。

第862號Fragment Shader佔用了10%的cycles

經過觀察Shader代碼,和槍火特效(還有額外的四周防禦罩效果)的Shader一致,爲

特效Shader,Particles/Additivie

 

留意到該Shader並不複雜,但卻又霧的處理(理論上能夠去掉一個Tint的顏色乘法),而且該特效在Unity觀察overdraw也合理,因此也能夠有結論八:

在Unity觀察槍火特效overdraw也算合理

 

在Unity觀察防禦罩特效overdraw也算合理

結論八:槍火特效+滿屏的防禦罩特效會致使有額外10%的cycle產生。需去除霧的處理。由於需求緣由,佔用屏幕面積較大,但Overdraw程度尚算合理。

至此,關於Shader的調優在本文暫告一段落。接下來須要更多實地考察。
另外,操做上還有小技巧,能夠經過Frames with features enabled的過濾,剔除沒有詳細數據的幀

能夠經過*Frames with features enabled*的過濾,剔除沒有詳細數據的幀

 

內存狀況

內存不會直接影響幀率,但也是性能的一方面表現。太高的內存多是加載緩慢的誘因、可能會提升app後臺後被系統kill掉的概率、也可能直接致使內存不足crash。
點擊MGD裏的Textures,並點擊Size進行排序。

點擊Textures,並點擊Size進行排序

 

當前在killer出現了不合理狀況有:

不應在戰鬥出現的紋理泄露到了戰鬥

結論九:主界面的圖標從戰鬥外泄露到戰鬥內了。須要注意是否戰鬥內有錯誤的引用。可以使用運行時檢測工具打包Sprite Packer的tag是否戰鬥外、戰鬥內互斥。亦須要注意資源模塊ResourcesManager是否還有資源引用,致使Resource.UnloadUnused()沒法卸載主界面資源。

一個時刻只出現一個的icon圖片能夠不打包

結論十:軍銜圖標可能從戰鬥外泄露到戰鬥內了,也多是戰鬥內就是須要用到。
結論十一:一個時刻很大概率只出現一個的icon圖片能夠不打包,放棄必定的DrawCall效率來換取內存,而且這樣哪怕泄露也可減緩泄露的後果。

還沒有說起的更多性能評估點

本文着重從最根本的Shader的Cycles數量進行分析,但還沒有說起的更多性能評估點包括:

  • DrawCall是否合理,有否可能合併。Unity 3D遊戲中,合併DrawCall會決定於LightMap,也會決定於UI層次間的atlas分佈。
  • 是否有過多的OpenGL狀態切換。

更多的優化細節,也可參考ARM® Mali™ GPU Version: 3.0 OpenGL ES Application Optimization Guide,或ARM® Guide to Unity Version 2.1 Enhancing Your Mobile Games

MGD(v2.1)尚待改進的地方

MGD(v2.1)尚待改進的地方有:

  • 在本次調優過程當中,不能對已Capture的幀進行逐DrawCall重畫(用戶手冊給出了緣由);
  • 不能方便觀察頂點模型;
  • 不能以柱形圖直觀地列出時間或Cycles消耗。

上述部分問題已在MGDv3.0得以解決。

About

DonaldW,客戶端開發,現就任於騰訊魔方工做室羣。 本文可隨意分發、分享。但請註明署名。

相關文章
相關標籤/搜索