发布时间:2022-07-26 13:23:38来源:作者:老杨
围绕渲染模块相关优化更全面的内容可以参考《Unity性能优化系列—渲染模块》。
多线程渲染
一般情况下,在单线程渲染的流程中,在游戏每一帧运行过程中,主线程(CPU1)先执行Update,在这里做大量的逻辑更新,例如游戏AI、碰撞检测和动画更新等;然后执行Render,在这里做渲染相关的指令调用。
在渲染时,电脑游戏主线程需要调用图形API更新渲染状态,例如设置Shader、纹理、矩阵和Alpha融合等,然后再执行DrawCall,所有的这些图形API调用都是与驱动层交互的,而驱动层维护着所有的渲染状态,这些API的调用有可能会触发驱动层的渲染状态地改变,从而发生卡顿。
由于驱动层的状态对于上层调用是透明的,因此卡顿是否会发生以及卡顿发生的时间长短对于API的调用者(CPU1)来说都是未知的。而此时有关电脑游戏的其它CPU有可能处于空闲等待的状态,从而造成浪费。因此可以将渲染部分抽离出来,放到其它的CPU中,形成单独的渲染线程,与逻辑线程同时进行,以减少主线程卡顿。

其大致的实现流程是,在游戏运行的主线程中调用的图形API被封装成命令,提交到渲染队列,这样就可以节省在主线程中调用图形API的开销,从而提高帧率;渲染线程从渲染队列获取渲染指令并执行调用图形API与驱动层交互,这部分交互耗时从主线程转到渲染线程。
而Unity在Project Settings中支持且默认开启了Multithreaded Rendering,一般建议保持开启。在UWA的大量测试数据中,还是发现有部分项目关闭了多线程渲染。开启多线程渲染时,CPU等待GPU完成工作的耗时会被统计到Gfx.WaitForPresent函数中,而关闭多线程渲染时这一部分耗时则被主要统计到Graphics.PresentAndSync中。所以,项目中是否统计到Gfx.WaitForPresent函数耗时是判断是否开启了多线程渲染的一个依据。特别地,在有关网络游戏的项目开发和测试阶段可以考虑暂时性地关闭多线程渲染并打包测试,从而更直观地反映出渲染模块存在的性能瓶颈。