https://www.jianshu.com/p/35096e796aa3?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-friends&from=singlemessage&isappinstalled=0html
DonaldWandroid
2015.08.07 21:42* 字數 2891 閱讀 7031評論 5喜歡 17正則表達式
ARM® Mali™ Graphics Debugger的做用之一是針對採用ARM® Mali™ GPU的Android手機,進行app的GPU運行時調試和調優。shell
本文MGD主要用於性能調優。windows
關於GPU性能調優,定性不定量都是耍流氓。
猜是虛的、打嘴炮討論是無用的、運行時正則表達式disable對象是盲目的、Unity Profiler是難於真機調試的、GPA(Intel® Graphics Performance Analyzers)是不一樣平臺的、Unity FrameDebugger是從實現本質決定了不能定量到高於DrawCall精度的。app
另外,本文假設已肯定瓶頸出如今GPU。不然,應優先調優CPU性能。直接使用Unity真機調試是不錯的CPU性能調優手段。框架
閱讀[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 Edition。tcp
本文以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版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和設備
MGD成功自動收集killer的GPU運行時調試信息
至此,Setup操做已完畢。接下來,須要保持手機和電腦的USB鏈接,進行進一步的調試調優操做,亦可用經過菜單將當前調試數據保存到電腦。
killer(產品名字《獨立防線》)爲咱們項目組一款基於Unity的可FPS/TPS切換、可PVP/PVE的3D射擊遊戲。
在遊戲中操做,進入戰鬥。並保持主角在主角第三人稱狀態,未露出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狀態,露出精細武器,無槍火特效
在以前的暫停狀態下,取消點擊收集Fragment數量按鈕(Get the fragment count statistics),不然將會很卡,而後點擊播放按鈕(Resume Tracing),以和第一幀相似的方法進行數據收集。
取消Get the fragment count statistics,才繼續進行操做
從收集數據看來,結果和第一幀數據並沒有質變。但因爲知道變化的因素是精細武器自己,因此應特定肯定該Shader的消耗。
此時,若是對武器Shader不熟悉,能夠打開Unity,在Editor重現該狀況,在Editor直接閱讀Shader代碼,以下:
精細武器的Shader:Bumped Specular
根據Shader特徵Shininess
、Gloss
和Normalmap
等,回到MGD,也是按Cycle數從大到小逐個觀察(由於渲染武器的消耗確定不會很小),肯定爲第871號Fragment Shader。
第871號Fragment Shader,用於精細武器的Bumped Specular Fragment Shader
因此有結論七:
結論七:精細武器的Shader的Cycle比例(4.6%)和Shader指令,哪怕是用Surface Shader,也不算複雜,不是瓶頸。這多是由於Unity的按平臺編譯Shader的優化結果。
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數量進行分析,但還沒有說起的更多性能評估點包括:
更多的優化細節,也可參考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)尚待改進的地方有:
上述部分問題已在MGDv3.0得以解決。
DonaldW,客戶端開發,現就任於騰訊魔方工做室羣。 本文可隨意分發、分享。但請註明署名。