Language:
Page Info
Engine Version:
Share

GPU分析

GPU有许多并行工作的单元,框架的不同部分被不同的单元绑定是常见现象。 正因为如此,在寻找瓶颈时,了解GPU成本的去向以及GPU瓶颈是什么具有重要意义。

GPU成本的去向

ProfileGPU命令允许您快速识别各种传递的GPU成本,有时甚至可以具体至绘制调用。 您可以使用基于鼠标的UI或文本版本。您可以使用 r.ProfileGPU.ShowUI 来禁用UI。数据基于GPU时间戳, 通常非常准确。然而某些优化会降低数字的可靠性,因此最好以批判性的态度审视任何数字。我们发现一些驱动程序 倾向于在使用着色器几秒钟后对着色器成本进行优化。这种情况可能会很明显,因此等待一段时间或再测量一次以获得更高的置信度可能是有益的做法。

ProfileGPU.png

控制台:ProfileGPU

快捷方式:Ctrl+Shift+,

...
 1.2% 0.13ms   透明半透明体积光源 1 绘制 128 图元 256 顶点
42.4% 4.68ms   光源 0 绘制 0 图元 0 顶点
   42.4% 4.68ms   直接光源 0 绘制 0 图元 0 顶点
       0.8% 0.09ms   非阴影光源 0 绘制 0 图元 0 顶点
          0.7% 0.08ms   标准延迟光源 3 绘制 0 图元 0 顶点
          0.1% 0.01ms   注入非阴影半透明光源 6 绘制 120 图元 240 顶点
      12.3% 1.36ms   渲染测试贴图。不可移动的定向性光源_1 1 绘制 0 图元 0 顶点
          1.4% 0.15ms   半透明阴影贴图生成 0 绘制 0 图元 0 顶点
...

ProfileGPU显示了光源名称,这使得艺术家更容易优化正确的光源。

查看每一帧的高水平成本,并了解其中合理的内容(例如,绘制调用沉重、复杂的材质、密集的三角形网格体、远视图距离)具有重要意义:

  • EarlyZPass:默认情况下,我们使用部分Z通道。DBuffer贴花需要完整Z通道。这可使用 r.EarlyZPassr.EarlyZPassMovable 自定义。

  • 基本通道:当使用延迟光源时,简单的材质可以有带宽限制。实际的顶点和像素着色器在材质图表中定义。动态对象上的间接照明需要额外的成本。

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

  • 阴影投射/过滤:在大部分光源上使用 r.ShadowQuality.Disable 阴影投射调整着色器的成本。考虑静态或静止光源。

  • 遮挡剔除:HZB遮挡具有较高固定成本,但每个目标的成本较低。切换 r.HZBOcclusion 以查看不启用它时您是否可以取得更好的效果。

  • 延迟光源:这随着接触像素数量的增加而增加,在使用光源函数、IES配置文件、阴影接收、区域光源和复杂的着色模型时更昂贵。

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

  • 环境反射:切换 r.NoTiledReflections 以使用非平铺方法,这种方法通常比较慢,但您使用很少量探头时除外。

  • 环境遮挡:质量可以调整,您可以使用多个通道来实现高效的大范围效应。

  • 后期处理:有些通道是共享的,那么切换显示标记以查看用效果换取性能是否值得。

有些通道会对后面的通道产生影响。一些示例包括:

  • 一个完整的EarlyZ通道需要更多的绘制调用和一些GPU成本,但是它避免了基本通道中的像素处理,可以大大降低其中的成本。

  • 优化HZB可以使剔除更加保守。

  • 如果屏幕的大部分处于阴影中,启用阴影可以降低光源的照明成本。

什么是GPU瓶颈?

通常,性能成本随像素数量的增加而增加。若要测试这一点,您可以使用 r.SetRes 改变渲染分辨率或在编辑器中缩放视口。 虽然使用 r.ScreenPercentage 更方便,但是请切记,一旦使用该特性,就会增加一些额外的增采样成本。

如果您看到一个可测量的性能变化,那么您将受到与像素相关项的约束。通常,它要么是内存带宽(读写),要么是数学限制(ALU),但在极少数情况下, 某些特定的单元是饱和的(例如MRT导出)。如果您能够降低相关通道的内存(或数学)并查看性能差异,您就会知道它受内存带宽(或ALU单元)所限制。 变化不必如出一辙 - 毕竟这只是一次测试。现在您已意识到您必须降低成本来提高性能。

虽然阴影贴图的分辨率与屏幕分辨率不成比例(使用 r.Shadow.MaxResolution),但除非您有非常大面积的阴影投影遮罩或半透明材料, 否则您将不受像素着色器限制。阴影贴图渲染通常受顶点处理或三角形处理限制(原因:密集网格体、无LOD、曲面细分、使用WorldPositionOffset)。 阴影贴图渲染成本与灯光的数量、级联/立方体贴图的边数以及光源视锥中投影对象的数量成比例。这是十分常见的瓶颈, 只有更大的内容更改才能降低成本。

高度曲面细分的网格体(其中的线框显示为纯色)可能会受到较低四边形利用率的困扰。这是 因为GPU在2x2像素块中处理三角形,稍后会拒绝三角形之外的像素。这是mip映射计算所需要的。对于较大的三角形,这不是问题, 但如果三角形很小或很长,性能可能会受到影响,因为虽然处理的像素很多,但实际上其中只有很少的像素对图像作出贡献。延迟着色改善了这种情况, 因为我们得到了很好的四边形照明利用率。这个问题将会在基本通道期间继续存在,所以复杂的材质渲染可能会相当慢。 解决这个问题的方法是使用密度较小的网格体。如果是细节层级网格体,这只能在问题发生处(在远处)完成。

您可调整_r.EarlyZPass_以查看您的场景是否会受益于一个完整的早期Z通道(基本通道期间有更多的绘制调用和更少的过度绘制)。

如果更改分辨率不会产生太大的影响,您可能会受到顶点处理(顶点着色器或曲面细分)成本的限制。 通常,您必须更改内容来验证这一点。典型的原因包括:

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

  • 复杂的世界场景位置偏移/位移材质使用纹理与不良的MIP映射。(调整材质)

  • 曲面细分(尽可能避免,调整曲面细分因子 - 最快的方法:显示曲面细分,有些硬件在更大的曲面细分级别下扩展性很差)

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

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

  • 验证顶点数量是否合理,一些导入器代码可能没有焊接顶点。(合并具有相同位置、UV和法线的顶点)

在较为少见的情况下,您会被某些其他因素所约束。它们可能是:

  • 对象成本(更有可能是CPU成本,但也可能是一些GPU成本)

  • 三角形设置成本(非常昂贵的多边形网格体与一个便宜的顶点着色器,例如阴影贴图静态网格体,很少是这个问题)

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

  • 视图成本(例如HZB遮挡剔除)

  • 场景成本(例如GPU粒子模拟)

实时GPU分析器

实时GPU分析器为主要的渲染类别提供实时的逐帧统计信息。若要使用实时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。