你的游戏项目有这些问题吗?

你的游戏项目有这些问题吗?

在移动游戏对高品质画面的要求不断增加的背景下,我们一直专注于移动设备GPU性能的优化,以确保您的游戏体验得以最佳展现。然而,不同GPU芯片之间的性能差异以及由此可能引发的GPU瓶颈问题使得优化工作更加具有挑战性。

因此,在不久前,基于UWA最新发布的GOT Online GPU模式,我们为开发者提供了GPU性能优化免费试用测评和技术问诊服务。在总结经验时,我们发现了许多在开发、制作或优化性能过程中场景的问题,现在与大家分享,希望能够为大家提供一些有益的启示。

在GOT Online GPU模式报告中,UWA将GPU Clocks作为衡量GPU性能的主要指标,当GPU Clocks*目标帧率>=GPU最大频率*80%时,这一帧会被判定为GPU Bound并标记为粉色背景。GPU Bound反映了GPU在当前帧中计算所耗费的时钟周期数过高,使得单位时间内GPU的额定时钟周期数无法支持游戏满帧运行,即GPU压力。

当GPU出现Bound时,我们就需要通过一些更为细化的参数来分析,结合UWA报告的参数,例如GPU Shaded、GPU Primitive,Overdraw等走势,自行排查哪些参数造成的GPU渲染计算压力,并采取相应的优化方案。

1. 渲染密度顶点较多的网格

中招率:93%

网格最小渲染密度则可以用于排查网格资源的精度是否合理,同时可以帮助降低网格渲染面片数。

渲染密度表示在平均每一万像素(100*100,仅指甲盖大小的像素区)中网格的顶点数,如果该值大于1000,则说明我们在很小的画面中绘制了过于复杂的网格。

因此,当此网格的渲染密度最小时,如果该数值仍然高于1000,那么此网格的顶点数大概率是过高的,开发者可以考虑对这些网格资源进行减面操作,或使用LOD分级处理。

建议项目团队结合资源的渲染走势、生命周期和使用情况,进而更好地判断该资源是需要减模还是做Culling直接裁剪掉。

2. GPU不可见图元过多

中招率:92%

渲染面是产生GPU压力的重要因素之一。渲染面过多,一方面可能是模型过于复杂,一般可以通过 LOD、HLOD 等常用技术来简化远距离的模型,在不影响画质的情况下显著降低渲染面;另一方面,可能是地形、大建筑物等大面积模型没有进行适当的拆分,导致进入视域体的面片可能不多,但提交到GPU的渲染面依然很多。

在UWA的Primitive曲线中,我们可以看到:

总图元数:提交到GPU端的图元总数,该数值基本等同于引擎端统计的渲染面片总数。

可见图元数:在GPU端通过各种裁剪之后,留下的参与渲染的三角面。

在3D场景中,比较理想的情况下,可见图元的数量应该接近或高于 50%(对于大部分模型,有一半三角面会因为朝向被裁剪)。如果某些角度下,可见图元的比例非常低,则很可能存在上文提到的第二种情况,从而可以针对性地检查和优化场景中,这个角度下,被提交到GPU的大面积模型。

在如上项目中,我们看到大家这个裁剪的占比非常高,大部分场景下会有70%的比例。

我们建议应尽量在CPU端完成剔除,并减小送往GPU的图元数。

3. Overdraw较高

中招率:91%

Overdraw即多次绘制同一像素造成的GPU开销。在场景中渲染顺序控制合理的理想状况下,不透明物体的Overdraw应该尽量接近1。所以,造成Overdraw的主要元凶就是半透明物体,即粒子系统和UI。

在GPU模式中,我们定义了两种Overdraw,一种是“硬件”Overdraw,是由Fragment Shaded除以硬件分辨率得出,这种Overdraw是统计了后处理在内的渲染,也包括一些BlitCopy,如Copy Depth、Copy Color等;

另外一种是传统意义上的Overdraw,通过替换Shader渲染来计算叠加颜色的亮度从而计算得到的数值,这种Overdraw通常只统计场景或者UI,不会统计后处理以及BlitCopy,对于这种Overdraw,GPU模式提供了Overdraw视图。

这两种数值会存在一定的偏差,当偏差较大时,我们需要考虑是否是后处理造成的,如后处理中有较多的全屏BlitCopy。

结合热力图,也可以帮助排查导致Overdraw较高的来源。

如上图,从获得的Overdraw热力图中可以看到,爆炸特效对应的区域亮度较高,结合该场景截图判断该帧Overdraw较高应为爆炸特效所致。可以考虑以下方法进行:

(1)对粒子系统的最大粒子数量进行限制;

(2)在中低端机型上只保留“重要的”的粒子系统,对于该爆炸特效,可以只保留火焰本身,而关闭掉周边的烟尘效果;

(3)尽可能降低粒子特效在屏幕中的覆盖面积,覆盖面积越大,越容易产生重叠遮盖,从而造成更高的Overdraw。

4. 带宽过高

中招率:88%

由于GPU读、写带宽较高时都会造成大量的发热和耗电,需要开发者重点关注。

带宽分为 “读带宽”和“写带宽”,一般来说“读带宽”是个较高的占比,其中又分为读纹理和读顶点,我们需要关注以下这些方向:

>> 压缩格式

使用合理的压缩格式,能够有效降低纹理带宽。

>> 是否开启Mipmap

对于3D场景而言,对其中的物体材质的纹理开启Mipmap设置,能够用一小部分内存上升作为代价有效降低带宽。

>> 纹理的采样格式

纹理的各向异性采样和三线性插值采样,对于手游来说的性能开销都是较大的,应当尽量避免。概括来说,纹理采样时会去读OnChip缓存里面的内容,如果没命中就产生了Cache Miss,就会往离GPU更远的内存去读System Memory,因此会产生更大的Read带宽。当使用三线性插值采样或者各项异性采样时,纹理采样点会增多,在OnChip上的Cache Miss的概率就会变大,因此会造成带宽上升。

>> RT 相关采样的设置

比如Bloom的上下采样次数和采样的分辨率、Blur、DOF、CopyColor CopyDepth,以及一些AA等操作,也是对带宽有较大的影响。

>> 分辨率

修改渲染分辨率为0.9倍乃至更低,会减少参与纹理采样的像素,也会降低渲染的RT的Load/Store的开销,最终降低带宽。

同时,功率和带宽是一个互相影响的逻辑,一般1G/S的带宽,会造成差不多 80 ~ 100 mw的功率开销。因此,也可以结合报告中的功率走势查看是否导致掉电过快的问题。

5. Shader复杂度过高

中招率:87%

片元阶段还有一个较为重要的影响因素,就是Shader Cycles,代表GPU花在Shader上的计算周期数。报告还列出了Shader Arithmetic Cycles、Shader Interpolator Cycles、Shader LoadStore Cycles、Shader Texture Cycles四项数据。用户可以快速定位到高Shader复杂度场景下,数学计算、顶点到像素插值、寄存器读取、纹理处理相关Cycles数中,哪一个单元是Shader复杂度过高的瓶颈,以便针对性地对项目的Shader复杂度情况进行排查和优化。

研发团队要避免在项目中存在大面积的Shader,比如建筑物地表的计算过于复杂,因为它的面积较大导致它的整体开销会比较大;另外一种就是半透明物体Shader,由于它更容易产生Overdraw,因此画的像素也会比较多,所以也要特别关注。

除此之外,也可以参考Mali Offline Compiler工具获取Shader的指令数和时钟周期数,对项目的Shader情况进行监控分析。

6. 渲染利用率为0的纹理/网格

中招率:83%

渲染利用率为0%,表示在整个游戏测试过程中,这些资源被加载到内存中,却没有提交给GPU,所以它的渲染利用率很低,甚至为0%。出现这种情况的原因主要有以下几点:

(1)过量加载导致资源被加载到内存中,但可能很少被用到或者压根用不到,建议研发团队结合具体资源名称查看资源的使用情况;

(2)测试过程中并没有测到这些资源,比如场景很大、特殊剧情需要触发或者特效预加载等等,建议制作更加全面的测试流程,尽可能把测试内容都跑全,最好做成自动化的遍历方式,进行长时间测试。

7. Mipmap层级使用不合理的纹理

中招率:82%

这里我们首先关注Mipmap第0层采样率低于20%的资源,这些资源大概率是尺寸过大,即没有物尽其用的,开发者可通过降低这些纹理资源分辨率缓解内存和GPU压力,同时也不会影响画面效果。

比如下图红框中的纹理,虽然是1024*1024,但是Mipmap第0层纹理在整个过程中完全没有使用过,96.15%的像素都是用128*128的层级进行采样的。

从它的使用生命周期中我们可以查到,该纹理在哪里参与渲染,以及使用的Mipmap层级具体情况:由于96.15%的像素用的都是Mipmap3+,所以该纹理可以直接从1024x1024的分辨率降为128x128,进而降低内存,提升加载效率。

虽然解决GPU的压力要注意方方面面,且随着玩家对于品质要求的提升优化的难度也越来越大,但好在通过科学的解题思路,再加上一些趁手的工具,我们也能一步步庖丁解牛,一些团队主动发来的优化前后对比效果,也是我们喜闻乐见的。

欢迎大家来使用UWA GOT Online GPU模式,帮助项目在渲染表现上达到更好的效果。

相关推荐

功能上新|全新GPU性能优化方案
UWA报告使用技巧小视频,你get了么?(第十一弹)