返回 登录
1

Unreal* Engine 4 VR应用的CPU性能优化和差异化:第一部分

作者:王文斓

虚拟现实(VR)能够带给用户前所未有的沉浸体验,但同时由于双目渲染、低延迟、高分辨率、强制垂直同步(vsync)等特性使VR对CPU渲染线程和逻辑线程,以及GPU的计算压力较大[1]。如何能有效分析VR应用的性能瓶颈,优化CPU线程提高工作的并行化程度,从而降低GPU等待时间提升利用率将成为VR应用是否流畅、会否眩晕、沉浸感是否足够的关键。Unreal* Engine 4 (UE4) 作为目前VR开发者主要使用的两大游戏引擎之一,了解UE4的CPU线程结构和相关优化工具能够帮助我们开发出更优质的VR应用。本文将集中介绍UE4的CPU性能分析和调试指令、线程结构、优化方法和工具、以及如何在UE4里发挥闲置CPU核心的计算资源来增强VR内容的表现,为不同配置的玩家提供相应的视听表现和内容,优化VR的沉浸感。

本文已发表于《程序员》杂志2017年08月期,如需转载,可与《程序员》联系。

为何要把PC VR游戏优化到90fps

Asynchronous Timewarp(ATW),Asynchronous Spacewarp(ASW)和Asynchronous Reprojection等VR runtime提供的技术可以在VR应用出现掉帧的时候,以插帧的方式生成一张合成帧,等效降低延时。然而,这些并不是完美的解决方案,分别存在不同的限制:

ATW和Asynchronous Reprojection能够补偿头部转动(rotational movement)产生的 Motion-To-Photon(MTP)延迟,但如果头部位置发生改变(positional movement)或者画面中有运动对象,即使用上ATW和Asynchronous Reprojection,也无法降低MTP延迟; 另外ATW和Asynchronous Reprojection需要在GPU的drawcall之间插入,一旦某个drawcall时间太长(例如后处理)或者剩下来给ATW和Asynchronous Reprojection的时间不够,都会导致插帧失败。而ASW会在渲染跟不上的时候将帧率锁定在45fps,让一帧有22.2ms的时间做渲染,两张渲染帧之间则以传统图像运动估算(motion estimation)的方式插入一张合成帧,如图1所示。但合成帧中运动剧烈或者透明的部分会产生形变(例如图1中红圈框起来的部分),另外光照变化剧烈的时候也容易产生估算错误,导致持续用ASW插帧的时候用户容易感觉到画面抖动。这些VR runtime的技术在频繁使用的情况下都不能够很好解决掉帧问题,因此开发者还是应该保证VR应用在绝大部分情况下都能够稳定跑在90fps,只有偶然的掉帧才依赖上述的插帧方法解决。图片描述
图 1.ASW插帧效果。

UE4性能调试指令简介

用UE4开发的应用可以通过控制台命令(console command)中的“stat”指令查询各种实时性能数据[2-3]。其中“stat unit”指令可以看到一帧渲染总消耗时间(Frame)、渲染线程消耗时间(Draw)、逻辑线程消耗时间(Game)以及GPU消耗时间(GPU)。从中可以简单看出哪部分是制约一帧渲染时间的主要原因,如图2所示。结合“show”或“showflag”指令动态开关各种功能(features)来观察分别对渲染时间的影响,找出影响性能的原因,期间可以用“pause”指令暂停逻辑线程来观察。需要注意的是其中GPU消耗时间包括了GPU工作时间和GPU闲置时间,所以即使在“stat unit”下看到GPU花了最长的时间,也并不代表问题就出在GPU上,很有可能是因为CPU瓶颈导致GPU大部分时间处于闲置状态,拉长了GPU完成一帧渲染所需时间。因此还是需要结合其他工具,例如GPUView[4]来分析CPU和GPU的时间图,从中找出实际瓶颈位置。
图片描述
表 1.stat unit”统计数字。

另外,因为VR是强制开启垂直同步的,所以只要一帧的渲染时间超过11.1ms,即使只超过0.1ms,也会导致一帧需要花两个完整的垂直同步周期完成,使得VR应用很容易因为场景稍微改变而出现性能大降的情形。这时候可以用“–emulatestereo”指令,同时把分辨率(resolution)设为2160x1200,屏幕百分比(screenpercentage)设为140,就可以在没有接VR头显及关闭垂直同步的情况下分析性能。

而渲染线程相关的性能数据可以通过“stat scenerendering”来看,包括绘制调用(drawcall)数目、可见性剔除(visibility culling)时长、光照处理时间等。其中可见性剔除又可以通过“stat initviews”指令进一步了解和分柝各部分的处理时长,包括视锥剔除(frustum culling)、预计算遮挡剔除(precomputed visibility culling)和动态遮挡剔除(dynamic occlusion culling)等,用以判断各剔除的效率; 输入“stat sceneupdate”指令查看更新世界场景例如添加、更新和移除灯光所花费的时间。另外,也可以通过“stat dumphitches”指令,指定一帧的渲染时间超过t.HitchThreshold时把渲染帧信息写进日志。

如果要使游戏效果能够适配不同等级的PC,那么“stat physics”,“stat anim”和“stat particles”会是三个经常用到跟CPU性能相关的指令,分别对应到物理计算时间(布料模拟,破坏效果等)、蒙皮网格(skin meshing)计算时间和CPU粒子计算时间。由于这三个计算在UE4里都能够分到工作线程作并行处理,因此对这些部分进行扩展能够把VR应用有效适配到不同等级的硬件,使VR体验以及效果能够随着CPU的核数增加而增强。

另外,可以直接输入控制台命令“stat startfile”和“stat stopfile”采集一段实时运行的数据,然后用UE4 Session Frontend里的Stats Viewer查看运行期间各时间段CPU线程的利用率和调用堆栈(call stack),寻找CPU热点并进行相应的优化,如图3所示,功能类似Windows* Assessment and Deployment Kit(ADK)里的Windows* Performance Analyzer(WPA)。


查看全文


了解更多相关内容,请关注CSDN英特尔开发专区

评论