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,客户端开发,现就任于腾讯魔方工做室群。 本文可随意分发、分享。但请注明署名。