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

http://www.jianshu.com/p/35096e796aa3


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

144 
作者 DonaldW 
2015.08.07 21:42* 字數 3181 閱讀 5430評論 5

What is MGD

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

Why MGD

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

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

另外,本文假設已確定瓶頸出現在GPU。否則,應優先調優CPU性能。直接使用Unity真機調試是不錯的CPU性能調優手段。

Doc & Setup

閱讀ARM® Mali™ Graphics Debugger User Guide是瞭解MGD最全面的途徑,裏面包括瞭如何設置MGD和使用MGD。
由於MGD裏會直接出現大量OpenGL/OpenGL ES的API,所以也可按需查閱AW OpenGL ES 3.0 Programming Guide 2nd Edition

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

關於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,客戶端開發,現就職於騰訊魔方工作室羣。
本文可隨意分發、分享。但請註明署名。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章