http://blog.ch-wind.com/ue4-profiling-preview/

Profililng是成品制作过程中非常重要的一个步骤,通过Profiling才能提高运行效率使得作品达到用户能够运行从程度。

UE4本身有提供用于Profiling的工具,但是要正确的将其用于优化却需要经过一些学习。在掌握基础之后,要很好的完成优化,需要的是更多的实践所累积的经验了。

本文的主要内容来自对Tech Art Aid的[Profiling系列视频]的总结和官方的[性能分析文档]。

不过由于Profiling本身的覆盖范围较广,所以这里也只是记录刚刚开始接触的内容。同时,由于并没有很深入的了解过渲染相关的知识,文中有的术语可能存在翻译不正确的现象:D

Scalability

UE4中有提供所谓的可延展性功能,这个功能可以用于快速的调整引擎的工作性能-效率平衡。

但是这个功能并不是为优化而设计的,虽然其中使用到的一些设置可以用于优化,但是Scalability本身更多的是为了让开发者为用户提供一个快速的配置。

通常在游戏配置界面中能够看到的配置就是从Scalability入手的。

可以在蓝图中看到一些类似这样的函数

社区中也有共享简单的游戏配置的实现,在设置窗口中可以对不同的渲染等级进行预览,以评估游戏在目标渲染等级上的表现。

更多的关于Scalability的内容可以参考[官方文档]。

Profiling

通常性的优化目标就是提高帧率,降低每帧消耗时间。由于现代的CPU通常比较强大,只要不是在游戏逻辑中进行复制的物理模拟或者高强度的AI逻辑运算,性能的瓶颈都会出在与渲染相关的地方。

在进行优化的时候需要注意的是,要在项目配置中关闭Smooth Frame Rate,否则没有办法很好的对性能进行分析。对于打包优化,官方的建议是至少在Development以上的级别下进行,因为Debug下有很多东西非常的影响性能。

同时关闭垂直同步在某些情况下也是必要的,使用r.VSync指令就可以了,在打包版本中也可以使用命令行参数-NoVSync。

常用指令

官方的stat指令集中提供了大量的用于性能优化的指令,其中比较常用的是通用的问题定位指令,在找到性能瓶颈之后,可以进一步的使用相关的指令进行问题的查看。

stat unit

使用stat unit就可以粗略的对问题的来源进行定位。

为了差分渲染与游戏逻辑的性能消耗,可以通过r.SetRes或者r.ScreenPercentage来有效的降低渲染消耗来辅助定位。

这里面Frame与stat fps输出的帧时间是一样的,其他的三项则对应不同的性能瓶颈:

Game为CPU游戏线程,如果是这里有问题的话通常就是游戏逻辑本身设计太消耗性能了。

Draw为CPU渲染线程,这里是负责向GPU发送DrawCall的,已经是渲染相关的优化。

GPU就是GPU的帧时间了,完全的渲染相关。

stat SceneRendering

指令可以用于更加详细的对性能瓶颈进行分析

通过寻找性能消耗较大的pass,对其进行针对性的优化就好了。

stat gpu

则可以用于查看gpu上的性能消耗比例

StartFire/stat stopfile

这组指令可以将性能分析文件生成到Saved/Profiling文件夹中。这些文件可以使用Front End中的分析器进行加载并分析:

GPU Visualizer

在优化中最常使用的工具还是GPU Visualizer,按快捷键[Ctrl+Shift+,]就会出来了。

性能优化从这里入手的话就比较直观一些。

渲染优化

渲染上会产生的瓶颈通常分为三大类别,Pixel-bound、Vertex-bound、Memory-bound。

Pixel-bound

Translucent的材质物体的大规模使用,半透明粒子都会导致在像素渲染级别上出现瓶颈。

在材质的使用上,Opaque的性能是最高的,因为可以有效的进行Z-buffer裁剪,其次是Masked材质,性能消耗最高的是Translucent。尤其是场景内出现大规模的半透明物体叠加的时候,就会产生大量的绘制负担。

在场景布局上,利用Opaque的物体进行遮蔽,尽量的避免镜头内出现大量半透明物体,有效的利用LOD都是非常重要的。

还有一个方面就是Quad Overdraw,这个似乎是由于GPU的渲染机制引起的,直接引用视频中看到的图片:

在优化上,要尽量避免屏幕空间内出现小而长的三角形,将其分割为更多的三角形反而更加有效。同时,将屏幕内足够小的物体进行LOD,也可以有效的避免性能消耗。对于Foliage上的叶子,可以使用Particle Trimming来避免过度绘制,据说Speed Tree是自带这个功能的,不过由于没有使用过所以无法确认。particle trimming如其名,在粒子的优化中也有作用。

不过没有实际使用过这个功能,按照介绍的话,性能提升还是比较明显的:

Original: 100%

Aligned rect: 69.23%

Optimized 3 verts: 70.66%

Optimized 4 verts: 60.16%

Optimized 5 verts: 55.60%

Optimized 6 verts: 53.94%

Optimized 7 verts: 52.31%

Optimized 8 verts: 51.90%

这个数据来自于[这里]。

Quared OverDraw可以通过调整为检查模式来对场景中的物体进行检查

Vertex-bound

通常受到影响的就是场景中三角形的数量,如果印象没有错的话,当前UE4内部所有的面应该都是三角形的。会在这里产生瓶颈的还有阴影投射与曲面细分,关于曲面细分,官方有建议是尽量不要使用,在建模阶段直接进行细分是更加具有效率的。

UV Seam和Hard Edges会额外的增加计算的顶点计算的负担,要尽量避免减少使用的频度。

同时Morph Target与WolrdPostionOffset也会产生更多的顶点计算,Skinned Mesh也是如此,不过这些方面,除了WorldPostionOffset可以尽量避免使用之外,只能从游戏逻辑本身的设计上入手了呢。

如果有使用LandScape的话,尽量减少LandScape的面数可以很好的提高性能。

为了避免过量的顶点计算负担,对于远景物体尽量使用BillBoard或者Imposter meshes、Skyboxe texture来代替3D物体。

Memory-bound

如果有大量的材质使用了不同的贴图,导致Texture Sample的数量爆炸的话,就会自然的变成瓶颈。

UE4有使用Texture Streaming,如果存储空间爆炸了的话,就会出现贴图模糊的情况,这时候可以使用Stat Streaming指令进行分析。

对于使用相同的材质的情况,可以通过材质中的设定让他们共享Texture。同时在材质中启用GPU本身支持的压缩可以有效的减少存储空间的占用,尽量的使用Texture Packing也是非常的重要的。载入的时候尽量使用Mip级别较低的图片,可以有效的减少存储占用。在材质的贴图使用中,尽量的进行优化的配置也非常的重要。

对于不需要太精细的贴图可以限制其最大尺寸

另外,光照贴图等也是被算作贴图占用存储空间的,因此也有在这里产生瓶颈的可能性。因此尽量的调低光照贴图的分辨率可以很好的提高性能。

使用Alt+0/Light Map Density可以对场景中的光照贴图密度进行分析。

在窗口>统计总也能进一步的对当前的存储使用状况进行分析

前向渲染与延迟渲染

UE4面向VR可以区分前向渲染与延迟渲染,两方各有优劣,在优化上也会有所不同。引擎采用的前向渲染方式是Cluster Forward Shading(Forward+),详细的技术细节并没有关注过,不过通常前向渲染的光照计算成本会高些,尤其是光照数量较多时会产生明显的性能下降。

使用缓存区可视化功能,可以对延迟渲染使用的缓存进行查看。

按通道优化

优化的过程,通常是在玩家通常的地点放置观察摄像,然后通过这个固定点使用GPU Visualizer进行优化。

在使用GPU Visualizer时,会看到各个通道的性能消耗比例,这样就可以针对不同的通道进行优化了。

在打包模式下按下GPU Visualizer后,不会出现界面,但是相关数据会被记录到Log中。

在GPU Visualizer中对帧时间消耗进行排序可以帮助快速找到当前消耗的瓶颈,不过有的pass的消耗可能是不得已的,这里大概就是需要经验的地方了。pass根据工作方式大体上分别工作于屏幕空间和运算空间,像是PostProcess这样的后期处理以及延迟渲染的光照都是工作在屏幕空间的。而像是Z-Buffer的生成这一类的操作则是通过运算空间进行的。一般工作在屏幕空间的通道受到渲染分辨率的影响就会比较大,例如SSAO、AA等。而在运算空间的Pass就会受到Mesh的数量、面数、shader的复杂度的影响。

光照

LightCompositionTasks_PreLighting

这个通道被SSAO以及非D-Buffer类型的Decals使用。

这里的性能消耗在屏幕空间上,通过在PostProcess中降低AO的半径和消退距离可以减少其产生的运算负担。

同时,非D-Buffer类的Decals也会对其产生影响。

Composition After Lighting

只影响Subsurface Profile的Shading Model的SSS效果的通道。

由于工作于屏幕空间,减少其在屏幕中的占比就可以有效的减少消耗。比如使用LOD之类的。

使用Subsurface的Shading Model或者Matcap之类的来进行替代也可以降低这里的消耗。

Compute Light Grid

用于计算光照相关性的pass,减少动态光照的数量就可以减低消耗。

Lights

延迟渲染的光照是基于DBuffer在屏幕空间呢进行演算的,因此受屏幕分辨率的影响也比较大。

无论是静态光照还是动态光照,都会受到光照本身的数量以及范围的影响。

而动态光照的效率额外的受到光照影响到的面数的影响。

光照的优化应该尽量的减少光照范围的重叠,避免大范围的动态光照,关闭没有太大必要性物体的动态阴影投射。光照的重叠等的查看可以通过调整视图

来进行有效的排查。

光照类型的性能消耗是点光源>直线光源>聚光灯,在使用光照时,如果能用IES或者光照函数进行替代的话,不要使用很多个光源组合成类似的效果。

同时光照函数通常的性能消耗大于IES,其消耗受到光照材质本身的复杂度的影响比较大。

在对光照范围进行优化时,可以通过关闭Use Inverse Squared Falloff,并自己设置Light Falloff Exponent来达到减小光照范围达到类似光照效果。

Filter Translucent Volume

这是半透明物体的光照计算时会用到的pass

带光照的半透明物体的光照大多数来源于一系列面向视锥体的cascade处理过的体积贴图。 这样在体积内的任意点,光照均为单次,但缺点就是体积贴图的分辨率比较低,而且从观察者角度来说,只涵盖了有限的深度范围。

详细的说明可以参考官方文档:[带光照的半透明物体]。

这里产生了瓶颈的话要检查光照的数目、范围和影响到的物体的数量。

ShadowDepths

这个生成通过光源进行阴影投射的深度数据的pass。

作用与这里的消耗主要受到开启了投影的光的数目、动态光照影响的面数、以及阴影的质量的影响。

阴影的质量可以通过Sg.shadow quality进行全局的调节。

Shadow Projection

实际的阴影投射,工作于屏幕空间,所以受分辨率影响,同时也会受到投影的光照数量和范围的影响。

基础通道

PrePass DOM_…

EarlyZPass,对非透明物体进行的早期的深度计算。

数据似乎被用于遮蔽计算,如果不使用Dbuffer Decals的话可以关掉。虽然视频中是这样建议的,但是早期的深度计算可以在BasePass之前进行遮蔽计算,能让basepass以及之后所有的通道的计算减少很多。而且即便在这里不进行深度计算,会影响这里的运算量的变量依然会作用与后面的深度计算阶段,因此关闭EarlyZPass还是需要多做考虑的。另外要使用DBuffer Decals的话必须使用Opaque and masked的zpass计算,否则应该会出现奇怪的现象。

性能上受到非透明物体的面数的影响,同时根据上面的选项不同也受到Masked的材质的影响。

HZB

Hierarchical Z-Buffer,用于计算HZB遮蔽,同时也会被屏幕空间内的射线演算使用,例如屏幕空间反射计算、AO等。同时被用于Mip的设置。

受屏幕空间的大小影响。据官方描述,HZB拥有较高的固定性能消耗,每个物体所造成的消耗较小。可以通过r.HZBOcclusion来调整运算的类型。

Base Pass

对非透明的物体进行演算并填充到GBuffer,使用缓冲区可视化模式可以在视图中看到效果。几乎所有的延迟渲染都受到其影响,因此才叫基础通道。

其计算结果包括base color, metallic, specular, roughness, normal, sss profile,并且Decals、Fog以及Velocity的计算也在此处。

其开销受到屏幕空间尺寸、物体数量、面数、Decals的数量、Shader的复杂度,生成的过程中包含光照贴图的推送,因此也会受到光照贴图的大小的影响。

可以通过Stat rhi指令检查各种贴图和triangle的消耗。

另外,前向渲染的光照也在这里进行,此时光照的数量也会影响到这里的消耗。

Translucency

半透明的材质以及光照演算,通过Stat gpu中的Translucency and Translucent Lighting可以进一步查看。

消耗受到屏幕空间大小以及屏幕内的半透明物体的数量影响,半透明物体的光照计算要尽量减少过度绘制。以及避免过多的需要进行半透明光照计算的光的数量。

其他

Particle Simulation/Injection

粒子模拟,这里只展示GPU粒子的消耗,性能主要受粒子数量以及是否开启了基于深度的粒子碰撞影响。

粒子的优化主要通过LOD以及设计上的优化进行。

Post process

UE4的后期处理功能比较多,AA、DOF、自动曝光以及很多其他的功能都在其中。每种PP特效都会产生额外的性能消耗,如果使用了PP材质的话,其复杂度也会影响性能。

Relection Envirionment

反射捕捉控件的计算缓存

可以将显示模式调整为Reflections来查看各个控件对缓存的影响

通常的建议是,放一个大范围的低精度反射捕捉,然后在需要的地方尽量不重叠的放置高精度的捕捉控件。

影响性能的主要就是捕捉控件的数量及范围,也受屏幕空间的大小影响。

Render Velocities

速度主要用于TAA以及Motion Blur,受到移动物体的数量以及其面数的影响。

主要的优化策略是使用LOD。

Screen Space Reflections

屏幕空间反射通过以下连个指令来进行调节:

r.ssr.maxroughness 0.0-1.0

r.ssr.quality 0..4

其中Maximum roughness决定着计算的范围的大小。

第三方工具

要使用第三方工具进行Profiling,一般需要打包。在进行捕捉之前,打开Toggle draw event的话可以让UE4提供更多的信息给第三方Profiling工具,捕捉完之后则使用同一个命令关闭就好。

第三方工具有Intel的GraphicsPerformance Analyzers、AMD的GPU PerfStudio以及开源的RenderDoc等。

使用第三方工具可以提供一些在硬件层次上获得的细节,在使用UE4本身的Profiling工具无法定位问题时可以进行尝试。

总结

总体而言,Profiling是一个复杂的过程。由于是面向最终用户的,需要花费很多精力在上面。

通常的策略包括LOD、裁剪、避免重叠以及低性能的近似替代等,很多的问题还需要在实践中才能发现和解决。

初探UE4中的Profiling【转】的更多相关文章

  1. UE4 中Struct Emum 类型的定义方式 笔记

    UE4 基础,但是不经常用总是忘记,做个笔记加深记忆: 图方便就随便贴一个项目中的STRUCT和 Enum 的.h 文件 Note:虽然USTRUCT可以定义函数,但是不能加UFUNCTION 标签喔 ...

  2. UE4 中在 Actor 中动态 Create Component 与ChildActor 的 小笔记

    Note:旧版本的UE4 的Attach 和12.13版本有些不一样 创建Component: UCpp_MyComponent* temp_imageCom = NewObject<UCpp_ ...

  3. UE4中使用数据表(Data Table)

    本文依据官方文档数据驱动游戏性元素整理而来. 做过游戏的应该都清楚,如果游戏稍微有点规模,那么使用数据驱动来做游戏一般是必不可少的一步,一般也就是策划通过本表的方式来解决.下面我们来简单说一下UE4中 ...

  4. 充分利用 UE4 中的噪声

    转自:https://www.unrealengine.com/zh-CN/blog/getting-the-most-out-of-noise-in-ue4 UE4 推出基于材质的程序式噪声已经有一 ...

  5. 初探 iOS8 中的 Size Class

    初探 iOS8 中的 Size Class 分类: Ios2014-09-16 13:11 4323人阅读 评论(1) 收藏 举报   目录(?)[+]   初探 iOS8 中的 Size Class ...

  6. 3D游戏开发之在UE4中创建非玩家角色(NPC)

    接着上节我们继续学习,现在我们来创建一些NPC(non-playable characters,非玩家角色).在这个游戏中,当我们靠近NPC时,它们会做出相应的反应. 一 创建C++类 1) 在UE编 ...

  7. UE4中的集合:TSet容器

    好久没有更新了,最近一直在老家过年,网络不通的,今天才有时间更新一集. 一.TSet<T>是什么 UE4中,除了TArray动态数组外,还提供了各种各样的模板容器.这一节,我们就介绍集合容 ...

  8. UE4中的单映射:TMap容器

    一.TMap<T>是么 TMap<T>是UE4中的一种关联容器,每个键都关联着一个值,形成了单映射关系.因此你可以通过键名来快速查找到值.此外,单映射要求每个键都是唯一的.类似 ...

  9. 【转载】 [unreal4入门系列之七] UE4中的Actor类和Pawn类

    原文地址: http://www.52vr.com/article-558-1.html 现在我们开始进入UE4的代码开发工作.首先,UE4的类框架是非常庞大的,看起来有点让人措手不及.不过正因为UE ...

随机推荐

  1. MyBatis3 用log4j在控制台输出 SQL

    用log4j在控制台输出 SQL 在spring-mybatis.xml中配置 <bean id="sqlSessionFactory" class="org.my ...

  2. EXPLAIN sql优化方法(2) Using temporary ; Using filesort

    优化GROUP BY语句   默认情况下,MySQL对所有GROUP BY col1,col2...的字段进行排序.这与在查询中指定ORDER BY col1,col2...类似.因此,如果显式包括一 ...

  3. Python修饰器讲解

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 文章先由stackoverflow上面的一个问题引起吧,如果使 ...

  4. 108.Convert Sorted Array to Binary Search Tree(Array; Divide-and-Conquer, dfs)

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 思路 ...

  5. crm第一天

    课程由1-7组成 自己实现的代码: 教程:

  6. 朴素贝叶斯算法的python实现-乾颐堂

    算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 朴素贝叶斯 比如我们想判断一个邮件是不是垃圾邮件,那么我们知道的 ...

  7. go语言的特殊变量 iota

    iota,是go语言的特殊常量,可以认为是一个可以被编译器修改的常量. 在每一个const关键字出现时,被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1. 来 ...

  8. 独立看门狗实验-IWDG

    为什么要看门狗? 注意:喂狗是0XAAAA写到KR. 头文件iwdg.h iwdg.c

  9. javascript总结48:正则表达式(RegExp)

    1 正则表达式(英语:Regular Expression) 正则表达式(英语:Regular Expression,在代码中常简写为regex.regexp或RE)使用单个字符串来描述.匹配一系列符 ...

  10. Arch Linux 使用markdown

    Arch Linux 使用markdown pandoc 文档格式转换 pygments 代码高亮 markdown-mode.el 配置emacs pandoc 号称文件格式转换的瑞士军刀,这里主要 ...