Unity 性能优化之道(性能问题定位 | 渲染流程分析 | SSAO项优化 | AA优化 | 后处理优化)
性能优化之道
- 性能优化问题的本质
- 性能优化的流程
- 影响性能的四大类问题
- 隐藏的几类小问题
- 性能问题可能的情况
- 经常用的优化思路
- 性能总览与瓶颈
- 性能问题排查流程
- 线程时序
- 示例工程分析
- 渲染流程分析
- FrameDebugger
- 逐帧绘制步骤分析工具
- Mac : Xcode 
- Windows : UPR
- SSAO项优化
- Unity内置SSAO处理的五步RenderPass:
- Unity内置SSAO处理性能分析
- Unity内置SSAO RenderPass处理的可配置参数
- AO方案进一步优化:
- 抗锯齿反走样优化
- 抗锯齿反走样方案发展
- Unity内置URP下的抗锯齿技术方案
- SMAA进一步优化
- Unity中AA方案优化总结
- PostProcess 后处理优化
- 后处理效果分类
- 色彩校正与增强
- 画面效果增强
- 镜头效果
- 后处理效果性能分析
- 后处理效果使用原则
性能优化问题的本质
- 慢与快的问题
- 前提
- 稳定性:不能因优化造成稳定性变差
- 兼容性:不能因优化导致兼容性变差
- 性价比:优化要有度,考虑成本与复杂度
性能优化的流程
- 发现问题(什么平台、什么操作系统、什么情况下出现问题,一般问题还是特例问题等)
- 定位问题(什么地方造成的性能问题,我们要用什么工具、什么方法确定瓶颈)
- 研究问题(确定用什么方案处理这个问题,要考虑性能优化的前提)
- 解决问题(按问题研究的结论去实际处理,并验证处理结果与预期的一致性)
影响性能的四大类问题
- CPU
- GPU
- 带宽
- 内存
隐藏的几类小问题
- 功耗比
- 填充率
- 发热量
性能问题可能的情况
- 瓶颈可能性按由高到低的顺序排列(个人经验总结)
- CPU利用率
- 带宽利用率
- CPU/GPU强制同步
- 片元着色器指令
- 几何图形到CPU到GPU的传输
- 纹理CPU到GPU的传输
- 顶点着色器指令
- 几何图形复杂性
经常用的优化思路
- 升维与降维
- 维度转换,如空间与时间,量纲转换
性能总览与瓶颈
性能问题排查流程
- 设备方面先排查iOS后排查Android;
- 使用Profiler、Frame Debugger、Memory Profiler、Profile Analyzer,根据总体性能情况明确所出现的性能阻塞现象;
- 使用UPR工具的真机联机、云真机等功能,判断Runtime参数是否存在超出默认标准或所设定标准的地方;
- 根据上述性能阻塞现象和Runtime参数,分析导致异常的源头,并优化。
线程时序
- 在Profiler或UPR报告中获得Runtime线程时序;
- 观察单帧消耗总时长、各线程及其模块的消耗时长;
- 观察主线程性能分析标记占比,常见标记如下:
- WaitForTagetFps 等待达到目标帧率,此时CPU与GPU负载良好,无异常瓶颈;
- Gfx.WaitForCommands/Gfx.WaitForGfxCommandsFromMainThread 渲染线程已经准备接受新的渲染命令,此时瓶颈在CPU;
- Gfx.WaitForPresent/Gfx.WaitForPresentOnGfxThread 主线程等待渲染流程绘制完毕,此时瓶颈在GPU;
- WaitForJobGroupID 等待工作线程完成,此时瓶颈在CPU。
更多分析标记见官方文档:https://docs.unity.cn/cn/2022.3/Manual/profiler-markers.html。
示例工程分析
IOS:
Android:
- 从线程时序中分析,GPU与带宽可能是主要瓶颈。
- 导致瓶颈的源头以及后续验证方向如下:
- 渲染流程与效果(是否存在冗余与不合理项);
- 渲染中生成资源(是否存在冗余与不合理项);
- DrawCall与SetPassCall(判断数量过高的原因);
- 片元着色器(判断是否存在效率问题);
- 渲染三角形(判断三角形数目是否过高)。
渲染流程分析
FrameDebugger
FrameDebugger将逐条展示渲染流程中的各个绘制步骤,例如:
- UniversalRenderPipeline.RenderSingleCameraInternal:SceneTravelCamera 场景相机的绘制步骤;
- UGUI.Rendering.RenderOverlays UGUI部分绘制步骤;
渲染步骤后面的数字为调用GFX(Graphics Command Buffers)指令的次数,调用GFX次数与渲染性能开销正相关。
绘制步骤序列: - MainLightShadow 主光源阴影;
- DepthNormalPrepass 深度与法线信息预渲染通道;
- ColorGradingLUT 颜色分级查找表;
- RenderGBuffer 几何、材质缓冲区;
- CopyDepth 拷贝场景深度;
- DefferedPass 延迟渲染光照与着色通道;
- RenderQpaquesForwardOnly 不透明物品前向渲染;
- SSAO 场景环境遮蔽效果渲染;
- Camera.RenderSkybox 天空盒渲染;
- CopyColor 拷贝场景颜色;
- DrawTransparentObjects 透明、半透明物品渲染;
- RenderPostProcessingEffects 后处理效果渲染。
逐帧绘制步骤分析工具
Mac : Xcode 
上图工具中的选项内容:
- CPU:显示当前应用程序下的CPU负载情况以及主线程、各个工作线程和后台线程的负载情况
- Memory:显示当前系统的内存情况以及当前应用占用的内存情况
- Energy Impat:显示了当前应用程序的耗电情况,显示了具体哪些是对功耗影响比较高的部分
- Disk:显示了当前存储器读写状况
- Network:显示当前网络读写状况
- FPS:(需开启GPU Frame Capture)显示GPU概况以及设备整体、顶点着色器、片源着色器的负载情况
点击GPU Frame Capture来抓取当前应用程序的一帧(需要等待一会)
超过1ms的选项第一值得关注,整体控制在10ms左右。
Windows : UPR
SSAO项优化
Unity内置SSAO处理的五步RenderPass:
- 深度贴图与法线贴图采样与相关计算;
- 水平方向上进行模糊处理;
- 垂直方向上进行模糊处理;
- 生成最终模糊AO图;
- 混合不透明物体。
Unity内置SSAO处理性能分析
- SSAO五个Pass中,“深度贴图与法线贴图采样与计算”的时长开销最大。
- 在该Pass的BoundResources中发现,有大量尺寸过大(屏幕全分辨率大小)的中间纹理。
- 在该Pass的PipelineStatistics中发现,ALU模块时长开销以及WaitTime时长开销较大。
- 当ALU模块时长开销较大时,可能的原因包括:
- 复杂的着色器:着色器中包含大量的数学计算和逻辑运算,导致ALU的负载增加。
- 高分辨率或高多边形数量:渲染大量的顶点和像素需要更多的ALU资源。
- 不必要的计算:可能存在着不必要的计算或冗余计算,增加了ALU的负载。
- 并行性限制:某些硬件限制了ALU的并行执行能力,导致渲染流程中的ALU时长增加。
- 当WaitTime时长开销较大,可能的原因包括:
- GPU资源瓶颈:GPU资源(如纹理、缓冲区等)的竞争或不足可能导致等待时间增加。
- 内存带宽限制:内存传输速度不足,导致GPU等待数据加载或传输。
- 线程调度问题:可能存在线程调度问题,导致GPU等待某些任务完成。
- 同步问题:可能存在需要等待其他任务完成后才能进行的同步操作,导致等待时间增加。
在该Pass的Preference中发现,性能开销较大的主要是是在Fragment相关指令。
综上判断,在Unity的内置SSAO处理中,存在片元像素过大、带宽性能瓶颈的问题。
Unity内置SSAO RenderPass处理的可配置参数
DownSample
- 当开启该选项后,在处理过程中会降低中间纹理的大小。将较大程度的优化性能开销。
- SSAO处理的默认实现中,当开启DownSample时,只对第一个Pass的中间纹理进行压缩与缓冲,且只缩放至屏幕尺寸的1/4。可以通过编辑相关源码,对更多Pass以更大的程度进行中间纹理的压缩。
SSAO面板参数: - Name:名字
- Downsample:选择此选项课降低生成中间纹理分辨率
- After Optical:此选项是将计算和应用SSAO放到不透明物体渲染之后以改善在TiledBase架构的GPU上的效率。(考虑到是移动端的优化,虽然会稻城物理理论上的一些不精确,还是建议开启)
- Source:选项是灰的是由于工程师延时渲染的,所以默认会生成Depth和Normal的信息,用这两个信息可以生成更精确的AO
- Intensity:通过系数调整AO的混合强度,这个值一般不会影响效率
- Radius:采样半径,值越大GPU开销越大。一般需要在可接受的范围内调低Radius调高Intensity来优化AO效果
- Direct Lighting Strength:是直接光影响的强度,此选项一般是指直接光光照的像素来混合这个影响AO的系数。此参数不影响采样效率,一般不做修改。
- Sample Count:采样次数,这个值直接影响采样循环次数,值越大性能开销也就越大。值越大表现效果越好,但得不偿失,一般在移动平台小要采用最小循环数来保证AO效果
Downsample默认URP下只提供1/2采样处理,可以修改源码来进行降低:
AfterOpaque
-
当开启该选项后,将渲染流程中SSAO的处理后置到不透明物品的绘制之后。在移动平台上有更好的性能表现,但在物体真实感方面可能有所下降。
-
Source、NormalQuality
- 若渲染管线选择前向渲染,则可以通过该项调整该处理中生成法线的精度值。
- 若渲染管线为延迟渲染,则默认已计算获取法线信息,故该选项无法配置。
-
Intensity
该选项为AO强度设置。该项只影响混合系数即处理效果,该项本身不会有性能方面的影响。 -
Radius
该选项为AO采样半径,该值越大,GPU开销越大。- 一般情况下,在视觉效果可以接受的情况下,应尽量减小Radius并适当调大Intensity,从而实现性能与效果的平衡。
-
DirectLightingStrength
该选项为直接光对AO影响的强度。该项只影响处理效果,该项本身不会有性能方面的影响,一般保持默认值即可。 -
SampleCount
该选项为采样循环次数。次数越高、性能开销越大、同时效果越好。 -
对于移动端,推荐值配置为:
- 开启DownSample,开启AfterOpaque,Intensity数值为2,Radius数值为0.02,DirectLightingStrength数值为0.25,SampleCount数值为4。
- 同时修改源码,对各个Pass的中间纹理压缩至原先的1/16。
AO方案进一步优化:
1.8ms的SSAO渲染对于整体的渲染流程依然有渲染空间,进一步优化方案:
- 使用HBAO或GTAO方案替代SSAO;
- 针对SSAO的Shader指令做进一步优化;
- 采用烘焙AO到静态光照贴图方案替代SSAO Render Pass处理。
抗锯齿反走样优化
抗锯齿反走样方案发展
- 第一代:SSMA(超级采样抗锯齿Super-Samling Anti-Aliasing);
- 第二代:MSAA(多重采样抗锯齿Multi Sampling Anti-Aliasing)、FXAA(快速近似抗锯齿Fast Approximate Anti-Aliasing)、SMAA(增强子像素形变抗锯齿Enhanced Subpixel Morphological Anti-Aliasing);
- 第三代:TAA(时间序列抗锯齿Temporal Anti-Aliasing);
- 第四代:DLSS(基于深度学习的超级采样Deep Learning Super Sampling)。
Unity内置URP下的抗锯齿技术方案
- 效率:FXAA>SMAA>TAA>MSAA
- 质量:MSAA>SMAA>TAA>FXAA
SMAA进一步优化
- 通过配置SMAA的配置参数Quality,从而调整SMAA阈值与计算权重步长。
- 修改SMAA的Shader源码,通过调高SMAA预置和调低计算权重步长,可以进一步优化性能,但可能会带来视觉效果的损失。
Unity中AA方案优化总结
当项目渲染管线为前向渲染时,先使用MSAA,视负担情况酌情选择如下优化方案:
- 高端移动设备上采用优化后的SMAA或FXAA,Unity默认URP下的TAA成熟后,根据性能与表现均衡选择采用;
- 中端移动设备上,采用FXAA方式或关闭AA渲染;
- 低端移动设备上关闭AA渲染。
PostProcess 后处理优化
后处理效果分类
色彩校正与增强
-
Channel Mixer
通道混合器可以修改每个输入颜色通道对输出通道整体混合的影响。
例如,如果增加绿色通道对红色通道整体混合的影响,则最终图像中所有绿色(包括中性/单色)的区域都将偏红色。 -
Color Adjustment
颜色调整可以调整最终渲染的图像的整体色调、亮度和对比度。 -
Color Curves
颜色分级曲线是一种在特定范围调整色调、饱和度或亮度的高级方法。
通过调整八个可用图形中的曲线,即可实现特定色调替换或使某些亮度降低之类的效果。 -
Lift,Gamma,and Gain
提升、伽马、增益轨迹球效果可用于执行三向颜色分级。
使用Lift项、Gamma项和Gain项分别控制阴影、中间调、高光的颜色与亮度。 -
Shadows Midtones Hightlights
阴影、中间调、高光轨迹效果可用于执行三向颜色分级。
该效果与Lift,Gamma,and Gain表现几乎一致,但该效果额外提供参数配置,使得用户能够指定阴影、高光的范围定义。 -
Tonemapping
色调映射是将图像的HDR值重新映射到新的值范围的过程。
其最常见的用途是使动态范围较低的图像看起来具有较高的范围,亦或是是将高动态范围图像的动态范围压缩到普通显示设备可以显示的范围之内。
在HDR值映射的过程中最大程度得保留原始图像的颜色、亮度、对比度等细节信息,并且不产生其他伪像,如光晕、梯度翻转、颜色失真、边缘模糊等。 -
White Balance
白平衡效果可以用来消除不真实的偏色,通过调整色温与色彩补偿。
其使场景对象在最终图像中尽量渲染为真实世界中的颜色(往往以白色作为标准),还可以使用该功能在最终渲染中呈现更冷淡或更温暖的效果。 -
Split Toning
拆分着色效果可以根据亮度值对图像的不同区域进行着色。
可以使用此效果为场景中的阴影和高光添加不同的色调,同时可以通过平衡度设置控制阴影和高光的对比度。
画面效果增强
-
Bloom
泛光效果会产生从图像明亮区域边界向外延伸的光线条纹。这种效果给人的感觉是极其明亮的光线压制住了摄像机。泛光效果还具有镜头脏污 (Lens Dirt) 功能,该功能可用于应用全屏污迹或灰尘层来衍射泛光效果。
-
Chraomatic Aberration
色差效果沿着图像明暗分隔边界出现颜色条纹。它可以模仿真实摄像机在镜头无法将所有颜色融合到同一点时产生的颜色失真。 -
Depth Of Filed
景深效果可模拟摄像机镜头的焦点属性。在现实生活中,摄像机只能在特定距离的对象上清晰聚焦。距离摄像机更近或更远的对象会失焦。
失焦效果提供了两种实现模式,一种是“高斯”,一种是“散景”。前者实现简易、性能开销小、效果粗暴;后者模拟真实相机在失焦时的视觉瑕疵表现、性能开销大。 -
Film Grain
胶片颗粒效果模拟的是摄影胶片的随机光学纹理,这通常是由物理薄膜上存在的小颗粒引起的。 -
Motion Blur
运动模糊效果可模拟现实世界摄像机在拍摄运动速度比摄像机曝光时间更快的对象时出现在图像中的模糊情况。这种情况通常是由快速移动对象或长曝光时间引起的。
镜头效果
-
Lens Disortion
镜头失真效果通过扭曲最终渲染的图片来模拟真实摄像机镜头的形状,即例如鱼眼效果等镜头畸变。 -
Panini Projection
Panini投影用于修正高Fov相机画面中的边缘拉伸畸变效果,从而使得画面透视效果更正确。 -
Vignette
渐晕效果呈现出,相对于中心,图像边缘变得更暗或去饱和。 -
Lens Flare
Lens Flare组件可控制镜头光晕的位置、衰减以及镜头光晕是否考虑遮挡等属性。
其后处理效果需要和Lens Flare (SRP) Data资源配置使用。
后处理效果性能分析
后处理效果使用原则
在Universal Render Pipeline Asset中,存在后处理相关配置项以供调整。
- Grading Mode 色彩分级模式可以根据性能与效果可以设置为HDR(High Dynamic Range)或LDR(Low Dynamic Range)。
- LUT size 色彩查找表缓冲区大小与GradingMode对应,若HDR则设置32,若LDR则设置16。
- Fast sRGB/Linear conversions 在低端设备上,在sRGB和线性颜色空间的转换中,可以考虑选用更快速但质量略低的近似处理。
如果平台设备支持“浮点精度纹理”,则Grading Mode可以直接选用HDR,效率更高,详见Unity的SystemInfo.SupportsTextureFormat。
所有美术效果的实现还应尽量依靠原始美术素材,后处理效果仅做不得已的调整或不可替代的实现。
- 对于效果不明显的高开销后处理,进行移除,或者使用低开销后处理进行近似替代。
- 对于暂时不需要的后处理效果,应从场景中Remove而不是Disable。
本文整理自:Metaverse大衍神君《Unity性能优化》