分析着色器性能

通过 AGI 帧分析器,您可以从我们的渲染通道中选择一个绘制调用,然后通过流水线窗格的顶点着色器部分或片段着色器部分来检查着色器。

在这里,您会找到着色器代码静态分析得出的有用统计信息,以及我们的 GLSL 已编译成的标准可移植中间表示 (SPIR-V) 汇编代码。还有一个选项卡可用于查看原始 GLSL 的表示形式(其中包含编译器为变量、函数等生成的名称),这些内容已通过 SPIR-V Cross 反编译,以便为 SPIR-V 提供额外的上下文。

静态分析

CAPTION
图 1. 说明?

使用静态分析计数器来查看着色器中的低级操作。

  • ALU 指令:此计数显示着色器中正在执行的 ALU 操作(加法、乘法、除法等)的数量,是衡量着色器复杂度的良好指标。请尝试最大程度地减少此值。

    重构常见计算或简化着色器中进行的计算有助于减少所需的指令数量。

  • 纹理指令:此计数显示纹理采样在着色器中发生的次数。

    • 纹理采样可能很耗时,具体取决于采样的纹理类型,因此,将着色器代码与描述符集部分中找到的绑定纹理进行交叉引用可以提供有关所用纹理类型的更多信息。
    • 采样纹理时避免随机访问,因为这种行为不利于纹理缓存。
  • 分支指令:此计数显示着色器中的分支操作数量。在 GPU 等并行处理器上,最大程度地减少分支是理想选择,甚至可以帮助编译器找到额外的优化项。

    • 使用 minmaxclamp 等函数可避免对数值进行分支。
    • 测试计算成本高于分支。由于在许多架构中,分支的两个路径都会执行,因此在许多情况下,始终执行计算比通过分支跳过计算要快。
  • 临时寄存器:这些是快速的核心上寄存器,用于保存 GPU 上计算所需的中间操作结果。计算可用的寄存器数量是有限的,超出此限制后,GPU 必须溢出到其他核外内存来存储中间值,从而降低整体性能。(此限制因 GPU 型号而异。)

    如果着色器编译器执行诸如循环展开等操作,则使用的临时寄存器数量可能会高于预期,因此最好将此值与 SPIR-V 或反编译的 GLSL 进行交叉引用,以查看代码正在执行的操作。

着色器代码分析

调查反编译的着色器代码本身,以确定是否有可能进行任何改进。

CAPTION
图 2. 说明?
  • 精度:着色器变量的精度可能会影响应用的 GPU 性能。
    • 尽可能在变量上使用 mediump 精度修饰符,因为中精度 (mediump) 16 位变量通常比全精度 (highp) 32 位变量更快且更省电。
    • 如果您在变量声明或着色器顶部没有看到带有 precision precision-qualifier​ type​ 的任何精度限定符,则默认为全精度 (highp)。请务必也查看变量声明。
    • 出于上述相同原因,也建议对顶点着色器输出使用 mediump,这还有助于减少内存带宽和插值所需的临时寄存器使用量。
  • 统一缓冲区:尝试将统一缓冲区的大小保持在尽可能小的范围内(同时保持对齐规则)。这有助于使计算更兼容缓存,并可能允许统一数据提升到更快的核上寄存器。
  • 移除未使用的顶点着色器输出:如果您发现片段着色器中未使用顶点着色器输出,请将其从着色器中移除,以释放内存带宽和临时寄存器。

  • 将计算从片段着色器移到顶点着色器:如果片段着色器代码执行的计算独立于着色片段特有的状态(或可以正确插值),则将其移到顶点着色器是理想的选择。原因在于,在大多数应用中,顶点着色器的运行频率远低于片段着色器。