HDC 2023 | 网易张志祥:U3D《倩女幽魂手游》鸿蒙系统优化实践
【GameLook专稿,未经授权不得转载!】
GameLook报道/8月5日,HDC 2023游戏服务论坛在东莞松山湖举行。本论坛主要围绕基于HarmonyOS的全场景创新游戏体验、鸿蒙生态下升级的游戏联运服务、全生命周期开发者服务和新激励政策等内容展开讨论。
游戏论坛上,网易雷火事业群游戏开发专家、《倩女幽魂》手游客户端主程序张志祥分享了《倩女幽魂手游》在适配鸿蒙平台所使用到的性能优化技术以及这些技术背后的优势。
以下是Gamelook整理的完整演讲内容:
张志祥:
大家好,我是来自网易雷火事业群的张志祥,很荣幸今天来这里给大家带来分享,我今天分享的主题是“倩女幽魂手游在鸿蒙平台的性能优化实践”。
首先简单介绍一下《倩女幽魂》手游,《倩女幽魂》手游是网易雷火2016年研制发行的MMORPG手游,曾经在2017年登顶过畅销榜,目前已经稳定运营超过7年,仍然广受广大玩家的喜爱。
在游戏开发的最初,我们使用的是Unity 5.2.4版本,然后在2022年9月我们将引擎彻底升级到了Unity2018,整个开发过程中,我们一直使用原生引擎进行开发,没有任何的引擎源码改动,这也是当初选择《倩女幽魂》手游来作为鸿蒙平台适配的主要原因,目前我们游戏绝大部分的逻辑与功能都已经在鸿蒙平台适配成功。
从技术角度看,整个鸿蒙平台的游戏适配分为三层:最底层是系统层,系统层提供的游戏引擎和游戏功能所需要的所有接口,由鸿蒙团队负责技术支持,引擎层由Unity中国负责支持,我们游戏侧,主要是利用引擎和系统的能力完成了所有的功能适配。
今天我带来的优化的主要技术,集中来自于系统层,是由华为鸿蒙团队开发的最新的方舟游戏图形引擎,这个引擎中包含了大量的性能优化相关的算法和接口,今天我接下来分享的是一些在我们游戏中经过验证并实践的一些算法。
渲染指令精简、重组
首先带来方舟图形引擎的第一个算法,就是渲染指令的精简和重组。右侧这张图是Unity引擎的常规渲染流程,通过主线程,渲染线程派发各种Render的渲染相关指令,然后再由渲染线程将真正的Graphic Commander发往图形API。
这就会带来问题,就像图片中所示,这些渲染相关指令往往会包含逻辑和渲染两类指令,这就造成渲染线程的负载过高,尤其是在多核CPU上,会造成多核CPU利用不均衡。而利用方舟图形渲染引擎的渲染精简、重组技术,它会将逻辑指令和渲染指令分散在不同的线程中,尽可能利用多核CPU,让其负载均衡,这样有助于提升整个渲染效率。
整个技术集中在系统侧,它是轻量级的、并且效率很高。其实我还想再补充一点,不只是渲染线程,整个Unity主线程也会遇到多核上负载不均衡的问题,这是因为Unity引擎的引擎API都必须跑在主线程上,而我们逻辑要跟这些引擎API打交道,随着逻辑的堆叠,大量的线程都会跑在主线程上,就会造成多核CPU的负载不均衡。
这个问题的解决方案其实和这里类似,就是将主线程中的一些逻辑拆分到不同的线程中。具体来说,这可以充分利用Unity提供的Jobsystem技术,在方舟图形引擎内,内置了一个ffrt算法,该算法是通过调度的优化来尽可能提高多核CPU的负载均衡。该算法已经和Unity中国最新的引擎无缝结合,这部分的技术我们也在与鸿蒙团队紧密合作中,这里就不过多展开了。
Shader
方舟引擎的第二个加速技术,就是Shader的优化技术。随着游戏对于渲染的要求越来越高,Shader会越来越多,而且越来越复杂。如右侧这张图,Shader往往会存在过长、运算太复杂等问题,这些会增加整个渲染的开销。
即便是同一个Shader,在不同GPU上面,它的开销其实也不一样、涉及到的性能瓶颈也不一样。如左侧这张图是Mali-G76和Mali-G77的对比。上面那张图可以看到它的GPU Bound是LS(Load/Store),主要是在处理贴图方面是比较大的瓶颈。而下面这张图它的Bound主要是算数方面,就是逻辑运算方面的瓶颈比较大。
方舟图形引擎通过变量合并、算数优化和指令替换、Cache优化等技术,可以对这些Shader的瓶颈做一些优化。具体来说,我举几个案例。比如说在Shader中我们可能用到开平方,SQRT的操作,那么在方舟图形引擎中,它可能把这个开平方操作替换成一个多项式近似。我不知道大家了不了解泰勒展开(公式),如果懂这方面数学知识的话,我们可以用泰勒展开把开平方的运算替换成一个几项的多项式运算就可以完成。当然,它不是绝对精确的,会有一些误差的损失。
另外一方面,指令替换的话,比如说在游戏中我们可能会用到贴图采样,但采样完我可能只用到其中的一个通道,这时候我们其实可以用texture.get这个函数来替换texture LOD。通过这些方式,除了我举的这两个例子,整个Shader优化里面还有其他的一些技术,总括起来,就是该技术通过无损或者低损的Shader简化,软硬结合,降低了GPU的整体负载。
SAFR(基于相似度检测的动态帧率调控)
方舟引擎内的第三个技术,叫做SAFR,基于相似度检测的动态帧率调控。左侧这张图是一个ACM论文中的调研,它调研了整个市面上比较热门的10款游戏,可以看到大多数游戏都有75%以上的帧率是有相似的。
中间是来源于我们游戏里的真实截图,可以看到当人物不动,摄像机不动,算法分析出来除了人物的动画,左侧树木的动画以及右侧上面的UI粒子特效之外,整个画面的相似度也是非常高的。而SAFR算法正是基于一个这样的事实:当两帧画面相似度越高的时候,玩家对于帧率就约不敏感。
因此,大家可以这样想象,当两帧画面有70%相似度的时候,我们可以动态调整帧率,把帧率下降10%;当两帧的帧率有90%以上相似的时候,该算法可能就把它的帧率下降到50%。对玩家来说其实没什么感知,但对系统来说,有极大的性能收获。
除此之外,我们也可以反过来想,我们游戏侧也可以做类似的相关技术。比如我们还是回到游戏的这张图,除了人物和UI之外,我们可以近似于认为整个场景是静态的(也就是在人物不动的情况下),这个时候,我们可以把整个场景静态地画到一张RT上面,下一帧再绘制整个画面的时候,直接从RT里把场景读出来,绘制到最终的FrameBuffer里面,然后再通过一些深度比较,把人物和UI之类的堆叠上去。这种方式,在我们游戏里面叫做静态渲染。
相较于静态渲染,SAFR算法的一个优势,第一它不需要纯静态场景,我们的静态渲染,只要画面发生一些变化,原来那个RT可能就失效了,而SAFR算法是通过动态调整帧率的方式,所以它不需要画面完全不变,扩大了应用的范围。另外一方面,它完全集中在系统中,对我们开发者来说不需要额外的开发量。
RVRS(基于区域的可变速率着色)
第四个是RVRS技术,我首先介绍一下VRS技术,它叫做基于区域的可变速率着色。该算法其实是在最近两三年里特别火的一个算法,它的具体原理如右下这张图,我们的常规渲染流程可能是一个像素点就一定要调用一次pixelshader,而通过这个VRS技术,通过这种像素块,比如2×2这种一整个像素块只调用一次pixelshader,然后大家共用这个结果。
那么,整个画面中哪些区域适合VRS算法呢?其实就是颜色变化比较缓的区域,比如上面的水域以及被UI遮挡的这一部分区域。RVRS算法就是通过每帧调用一个compute shader来分析整个画面中颜色变化的频率,最终来指导VRS算法,降低整个pixelshader开销的目的。
SR(超分)
最后一个是超分算法(SR),在方舟图形引擎内总共内置了三个超分算法,分别是CAS、FSR和RCASU,前面两个其实是来源于AMD的开源算法,实现,大家如果有兴趣的话可以直接去网站查阅相关资料,这里就不过多做介绍了。RCASU算法是鸿蒙团队,就是方舟图形引擎内置的自研算法。
这三个算法相比,FSR功耗比较高,但它的表现很好。CAS功耗最低,但表现很一般;而RCASU的功耗和表现介于两者之间。在整个系统侧集成这三个算法之后,系统会自动根据设备的性能来动态调整调用这些算法。
可以看到调用结果,左侧是开了超分算法,右侧是不开超分算法的对比,可以看到画面清晰了很多。
这是我们游戏中真实的视频实录,是在我们游戏中经典的关岭玩法中的一个性能对比,左侧是优化前的,右侧是优化后的,大家可以看到两个红框框的区别。我们在应用了全套的方舟图形引擎以及优化技术之后,无论是帧率还是功耗都有很显著的改善。
总结
最后总结一下,整个方舟引擎内其实远不止这五个算法,目前将这几个只是在我们游戏中得到应用的算法,后续我们会更多、更紧密地与方舟图形引擎团队合作,争取把更多算法加入到我们游戏里面来。
另外一方面,除了方舟图形引擎之外,整个鸿蒙生态还有一些别的优化技术,比如端云协同技术,它可以通过端云协同把一些游戏中负载比较重的一部分搬到云端计算,然后再返回应用到客户端,该技术我们也在与相关团队的同事紧密合作中。
如若转载,请注明出处:http://www.gamelook.com.cn/2023/08/524884