GPU 性能分析

GPU 有多个单元平行工作,不同单元在帧的不同位置常出现受限状况。 因此,在确定并查找 GPU 瓶颈时需要找到 GPU 消耗的来源。

GPU 消耗来源

使用 ProfileGPU 命令可快速确定多个通道的 GPU 消耗,有时可精确到绘制调用。 可使用鼠标 UI 或文本版本。可通过 r.ProfileGPU.ShowUI 对 UI 进行抑制。数据基于 GPU 时间戳,通常较为准确。部分优化将使数据的可靠性降低,需对其持保留态度。我们发现使用着色器数秒后部分驱动会对着色器进行优化。效果可能直观可见,有必要稍作等候,或另行测量以便确定。

ProfileGPU.png
CONSOLE: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 pass。DBuffer 贴图需要全 Z Pass。可通过 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、曲面细分、世界位置偏移使用)。 使阴影贴图渲染消耗出现变化的因素有:灯光数量、级联/立方体贴图数量、灯光视锥中的阴影投射物体数量。这是常见的瓶颈, 对内容进行较大变更方可减少消耗。

高度细分的网格体中线框显示为纯色,可能出现较差的四边形应用。原因 是 GPU 在 2x2 的像素块中对三角形进行处理,并在稍后拒绝三角形外的像素。这是 mip map 计算的条件。对于较大的三角形而言并不存在问题, 但如果三角形过小或过长,则性能可能受到影响(处理的像素过多,但对图像实际帮助不大)。延迟着色可改善此状况,因为 灯光上存在极好的四边形应用。此问题在基础通道中同样存在,因此复杂材质的渲染速度较慢。 解决方法是使用密度较低的网格体。通过 LOD 网格体仅可解决出现问题的区域(远距离)。

可对 r.EarlyZPass 进行调整,确认完整早期 Z 通道是否场景有所帮助(更多绘制调用、基础通道中较少的过度绘制)。

如改变分辨率后变化不大,则可能是受到顶点处理(顶点着色器或曲面细分)消耗的限制。 通常需要通过内容变更进行验证。典型因素包括:

  • 顶点过多(使用 LOD 网格体)

  • 复杂世界位置偏移/位移材质所使用纹理的 mip map 较差(调整材质)

  • 曲面细分(尽量避免出现,调整细分因子的最快方法:显示曲面细分,部分硬件在较大的细分等级下延展性非常差)

  • UV 或法线接缝过多,导致顶点过多(在展开的 UV 中许多岛状区的情况均很糟糕,平面着色的网格体每个三角形上存在 3 个顶点)

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

  • 确认顶点数量是否合理,部分导入器代码可能未将顶点接牢(组合拥有相同位置、UV 和法线的顶点)

还可能存在其他限制因素(几率较小)。包括:

  • 物体消耗(CPU 消耗的可能性较高,也会存在一些 GPU 消耗)

  • 三角形设置消耗(带较差顶点着色器的超高多边形网格体,如阴影贴图静态网格体,出现几率较低)

    • 使用 LOD 网格体

  • 视图消耗(如 HZB 遮蔽剔除)

  • 场景消耗(如 GPU 粒子模拟)