GPU分析

如何优化游戏的GPU需求。

Choose your operating system:

Windows

macOS

Linux

GPU有许多并行运行的单元,在帧的不同序列上被不同的单元绑定很常见。由于存在这种性质的行为,在搜寻瓶颈时确定GPU开销的去向以及了解GPU瓶颈是什么很有帮助。

[Unreal Insights](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/Overview)
是一款帮助开发人员识别瓶颈的应用程序,在优化性能时很有用。大致来说,Unreal Insights是一个独立的分析系统,它与虚幻引擎集成,可以收集、分析和可视化引擎发出的数据。

如何设置Unreal Insights

Unreal Insights工具随虚幻引擎一起提供。你可以在 Engine/Binaries/Win64 的引擎源目录文件夹,或启动程序引擎目录 Program Files/EpicGames/EngineVersion/Engine/Binaries/Win64/UnrealInsights.exe 中找到 UnrealInsights.exe

UnrealInsights.png

如果你下载UE源代码,并在本地编译,通过在开发(Development)或发布(Shipping)模式下构建整个解决方案,或通过直接构建 UnrealInsights 项目,你可以编译它。

UnrealInsightsBuild.png

你找到或构建编译的程序(UnrealInsights.exe)后,在你要用于记录数据或查看实时会话的设备上运行它。

记录GPU追踪数据

[追踪](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/Reference/Trace)
是一种结构化的日志记录框架,用于追踪正在运行流程中的仪表测量事件。Insights包含默认预设(-trace=default),可以自动追踪有关CPU、帧、日志和书签的信息,这些信息可以帮助你识别需要优化的其他区域。

要追踪项目的GPU追踪数据,请使用命令行参数启动你的项目(在独立或打包构建中)。

-trace= default, gpu

或者,按波浪号(~)键并输入命令,找到控制台的命令窗口

Trace.Start[gpu]

查看GPU追踪数据

追踪数据存储在 UnrealInsights/Saved/TraceSeissons 文件夹的追踪存储目录(Trace Store Directory)中,你可以在其中查看。

TraceStoreDirectory.png

你也可以在Unreal Insights应用程序中双击实时会话,打开 Insights Viewer

TraceSessionsInsights.png

分析GPU追踪数据

Insights Viewer 包含用于浏览和可视化性能数据的 Timing Insights 窗口。在Timing Insights窗口中,你将看到CPU和GPU的逐帧性能数据。你可以查看渲染(Rendering)和RHI线程(RHI Thread)轨道上的CPU计时事件,它们是可以与GPU计时事件关联的最重要事件。

GpuTrack.png

计时(Timing)面板 将显示单个追踪事件,并提供亚微秒级精度的时间测量。这些事件垂直堆叠,从而指示范围并并使用单独的轨道显示不同线程上的活动。在轨道显示中,事件按线程分解,垂直划分以便显示范围,并根据它们的开始和结束时间水平定位。

TimingPanel.jpg

将鼠标悬停在计时(Timing)面板(1)中的计时器事件上时出现的提示文本。同一线程上的嵌套事件堆栈(2)。

日志(Log)面板 将显示UE4会话中的所有日志(由UE_LOG调用生成)。日志可以按冗长度和类别筛选,就像编辑器的输出日志窗口(Output Log)一样。

LogPanel.jpg

日志提供在计时(Timing)视图中显示为垂直标识线的功能。默认情况下,仅书签显示为标识线。但是,这可以使用快捷键 M ,或通过右键点击 书签(Bookmarks) 轨道并从上下文菜单中选择 日志(Logs) 来更改。

BookMarks.png

找到Insights浏览器(Insights Browser),显示日志类别。(1). 书签轨道。(2). 上下文菜单将筛选你的书签轨道显示。

Unreal Insights提供强大的

[动画](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/AnimationInsights)
[网络](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/NetworkingInsights)
[UI](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/SlateInsights)
分析功能。

虚幻前端

下面的信息详细说明了用于使用虚幻前端分析GPU开销的命令。此工具的分析功能已被

[Unreal Insights](TestingAndOptimization/PerformanceAndProfiling/UnrealInsights/Overview)
取代。

虚幻前端是一款旨在简化和加快日常视频游戏开发和测试任务的工具,例如准备游戏版本、将它们部署到设备以及启动它们。

ProfileGPU命令

ProfileGPU命令可以识别各种通道的GPU开销,有时甚至是绘制调用的开销。 你可以使用基于鼠标的UI或文本版本。你可以使用 r.ProfileGPU.ShowUI 抑制UI。数据基于GPU时间戳, 通常非常准确。某些优化可能会降低数据的可靠性,所以对所有数据都保持质疑是一件好事。我们发现,一些驱动程序 倾向于在使用着色器几秒钟后优化着色器成本。这点可能很明显,等待片刻或换个时间再次测量很有帮助,从而更有把握。

| ProfileGPU.png |

| 控制台:ProfileGPU |

| 快捷键:Ctrl+Shift+, |

...

 1.2% 0.13ms   ClearTranslucentVolumeLighting 1 draws 128 prims 256 verts

42.4% 4.68ms   Lights 0 draws 0 prims 0 verts

   42.4% 4.68ms   DirectLighting 0 draws 0 prims 0 verts

       0.8% 0.09ms   NonShadowedLights 0 draws 0 prims 0 verts

          0.7% 0.08ms   StandardDeferredLighting 3 draws 0 prims 0 verts

          0.1% 0.01ms   InjectNonShadowedTranslucentLighting 6 draws 120 prims 240 verts

      12.3% 1.36ms   RenderTestMap.DirectionalLightImmovable_1 1 draws 0 prims 0 verts

          1.4% 0.15ms   TranslucencyShadowMapGeneration 0 draws 0 prims 0 verts

...

ProfileGPU将显示光源名称,这样美术师可以更轻松地优化正确的光源。

查看每帧的大概成本,并确定合理项(例如,绘制调用量大、材质复杂、三角形网格体密集、视图距离远):

EarlyZPass

默认情况下,我们使用部分z通道。DBuffer贴花需要完整的Z通道。你可以使用 r.EarlyZPassr.EarlyZPassMovable 进行自定义。

基础通道(Base Pass)

使用延迟着色时,简单的材质可能会受到带宽限制。实际的顶点和像素着色器在材质图表中定义。动态对象上的间接光照会产生额外成本。

阴影贴图渲染(Shadow map rendering)

实际的顶点和像素着色器在材质图表中定义。像素着色器仅用于遮罩材质或半透明材质。

阴影投影/过滤(Shadow projection/filtering)

调整着色器开销,在大多数光源上投射 r.ShadowQuality.Disable 阴影。考虑静态光源或固定光源。

遮蔽剔除(Occlusion culling)

HZB遮蔽具有较高的恒定开销,但每个对象的开销较小。切换 r.HZBOcclusion 可以查看不打开它是否会更佳。

延迟光照(Deferred lighting)

这与接触的像素成比例,并且在光照函数、IES配置文件、阴影接收、区域光照和复杂着色模型方面的开销更高。

平铺延迟光照(Tiled deferred lighting)

切换 r.TiledDeferredShading 可以禁用GPU光源,或使用 r.TiledDeferredShading.MinimumCount 定义何时使用平铺方法或非延迟方法。

环境反射(Environment reflections)

切换 r.NoTiledReflections 可以使用非平铺方法,除非你的探针很少,否则这种方法通常较慢。

环境光遮蔽(Ambient occlusion)

可以调整质量,你可以使用多个通道来实现高效的大规模效果。

后期处理(Post-processing)

一些通道是共享的,因此切换显示标记可以查看效果是否匹配性能。

某些通道可能会对之后的通道产生影响。示例如下:

  • 全部EarlyZ通道会导致更多的绘制调用和一些GPU开销,但它避免了基础通道中的像素处理,可以大幅降低这部分开销。

  • 优化HZB可能会导致剔除更加保守。

  • 如果屏幕上大部分区域处于阴影中,启用阴影可以降低灯光源的光照开销。

什么是GPU瓶颈?

通常,性能开销会随着像素的数量变化而变化。若要测试,你可以使用 r.SetRes 改变渲染分辨率,或在编辑器中缩放视口。

使用 r.ScreenPercentage 更加方便,但请记住,一旦使用该功能,就会增加一些额外的上取样开销。

如果你看到明显的性能变化,则意味着你受到了像素相关因素的限制。通常是内存带宽(读写)或数学限制(ALU),但在极少数情况下,某些特定单元已饱和(例如,MRT导出)。如果你可以降低相关通道的内存(或数学计算)并看到性能差异,你就会知道它是受内存带宽(或ALU单元)的限制。

变化不一定相同,这只是测试。现在你知道了,必须降低开销才能提高性能。

阴影贴图分辨率不随屏幕分辨率的变化而变化(使用 r.Shadow.MaxResolution ),但是除非你的阴影投射遮罩材质或半透明材质区域非常大,否则不受像素着色器限制。通常,阴影贴图渲染受顶点处理或三角形处理的约限制(原因:网格体密集、没有LOD、曲面细分、WorldPositionOffset使用)。

阴影贴图渲染开销会因光源数量、立方体贴图边数和光视锥体中投射阴影对象数量的变化而变化。这是非常常见的瓶颈,仅较大的内容更改才能降低开销。

高度曲面细分的网格体(其中线框显示为纯色)可能会导致四边形利用率低下。这是因为GPU在2x2像素块中处理三角形,并稍后拒绝三角形外的像素。这是mipmap计算所必需的。对于较大的三角形,这不是问题,

但是如果三角形很小或很细长,性能会受到影响,因为处理的像素很多,但实际上对图像有贡献的像素很少。延迟着色可以改善这种情况,因为我们对光照获得了非常好的四边形利用率。基础通道期间问题仍将存在,因此复杂材质的渲染可能会相当慢。

解决方案是使用密度较小的网格体。有了细节级别网格体,这只能在有问题的地方(远距离)完成。

你可以调整_r.EarlyZPass_,查看你的场景是否会从完整的早期Z通道中受益(更多的绘制调用,在基础通道期间减少过度绘制)。

如果更改分辨率无关紧要,你可能会受到顶点处理(顶点着色器或曲面细分)开销的限制。

通常,你必须更改内容才能验证这一点。通常原因包括:

  • 顶点太多(使用细节级别网格体)。

  • 复杂的世界位置偏移/置换材质,使用具有较差MIP映射的纹理(调整材质)。

  • 曲面细分(尽可能避免,调整曲面细分因子,最快的方法:显示曲面细分,一些硬件在较大的曲面细分级别下会严重缩放)。

  • 许多UV或法线接缝会导致顶点更多(查看展开的UV - 许多岛状区很糟糕,平面着色网格体每个三角形有3个顶点)。

  • 顶点属性过多(额外的UV通道)。

  • 验证顶点数是否合理,某些导入程序代码可能未焊接顶点(组合具有相同位置、UV和法线的顶点)。

较少情况下,你会受到其他因素的限制。可能包括:

  • 对象开销(很有可能是CPU开销,但可能也有一些GPU开销)。

  • 三角形设置开销(具有低价顶点着色器的高精度多边形网格体(例如阴影贴图静态网格体)很少出现此问题)。

  • 使用细节级别(LOD)网格体。

  • 视图开销(例如,HZB遮蔽剔除)。

  • 场景开销(例如GPU粒子模拟)。

实时GPU分析器

实时GPU分析器将为主要渲染类别提供实时的逐帧统计数据。要使用实时GPU分析器,请按 反引号(Backtick) 键打开控制台,然后输入 统计数据GPU(stat GPU) ,并按 Enter 。你还可以通过 视口选项(Viewport Options) 下拉菜单中的 统计数据(Stat) 子菜单,启动实时GPU分析器。

GPU_Stats.png

统计数据是累加且不分层级的,因此你无需深入挖掘事件树即可查看主要类别。例如,阴影投影(Shadow Projection) 是所有视图中所有光源的所有阴影投影的总和。当你的作品运行时,屏幕上的GPU统计数据提供了GPU负载的简单可视化细分。统计数据也可用于即时衡量变化的影响;例如,在更改控制台变量、在编辑器中修改材质或动态修改和重编译着色器(重编译着色器已更改)时的影响。当作品运行以供稍后分析时,GPU统计数据可以记录到文件中。

与现有统计数据一样,你可以使用控制台命令 stat startfilestat stopfile 将统计数据记录到 ue4stats 文件中,然后通过在虚幻前端工具中打开文件来查看统计数据。

Saved_Profile.png

使用虚幻前端分析GPU。界面上将显示总时间、后处理时间和基本通道时间。

统计数据在代码中声明为浮点计数器,例如:

DECLARE_FLOAT_COUNTER_STAT(TEXT("Postprocessing"), Stat_GPU_Postprocessing, STATGROUP_GPU);

然后可以使用引用这些统计数据名称的SCOPED_GPU_STAT宏检测渲染线程上的代码块。这些工作类似于SCOPED_DRAW_EVENT。例如:

SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Postprocessing);

未明确检测的GPU工作将包含在全面的[未说明]统计数据中。如果它变得太高,则表明需要一些额外的 SCOPED_GPU_STAT 事件来处理丢失的工作。

值得注意的是,与绘制事件不同,GPU统计数据是累加的。你可以为同一统计数据添加多个条目,这些条目会在整个框架中聚合。在某些受CPU限制的情况下,GPU计时可能会受到CPU瓶颈(气泡)的影响,此时GPU正在等待CPU追上。因此如果在绘制线程时间很长的情况下看到意外结果,请考虑这种可能性。在PlayStation 4上,我们通过从计时中排除命令列表提交之间的时间来更正这些气泡。在未来的版本中,我们会将该功能扩展到其他现代渲染API。

本文基于此前的虚幻引擎版本编写,未针对当前的虚幻引擎5.0版本更新过。