调试工具链:Frame Debugger、RenderDoc、编译产物

Unity 知识 · Shader 区域 · 性能与调试 · 第 2 篇 更新于 2026-10-15

shader 的 bug 和性能问题都发生在 GPU 上,肉眼看不见。这篇把四件工具按「回答什么问题」组织:Frame Debugger 回答「引擎画了什么」,RenderDoc 回答「GPU 怎么画的」,编译产物回答「你的代码变成了多少指令」,Profiler 回答「时间花在哪」。

Frame Debugger:引擎侧的逐 Draw 回放

Window → Analysis → Frame Debugger。把当前帧拆成 Draw Call 列表,逐个回放,每个 Draw 可看:

  • 用的哪个 shader 的哪个 Pass(LightMode 标签对不对,一眼可见——URP 物体不投影先来这查,见 /notes/unity/engineering-1/)。
  • 传入的全部材质参数实际值(「参数拖了没反应」在这看真值,见 /notes/unity/structure-4/)。
  • 渲染状态(Blend/ZWrite/Cull)、RT 与纹理绑定。
  • SRP Batcher 兼容性标记(不兼容原因直接写出来)。

局限:它看的是 Unity「决定画什么」,不是 GPU 实际执行;性能数据只有粗略统计。

Rendering Debugger:打包后的运行时入口

开发构建里运行时按 Ctrl+\(或代码 RuntimeAnalyzer)打开:FPS、渲染统计、SRP Batcher 状态、过draw 可视化(Overdraw 模式直接给 /notes/unity/performance-1/ 的账本配图)。真机上定位「哪个特效铺满屏」很直接。

RenderDoc:GPU 侧的真相

抓帧(PC 编辑器/开发构建、Android 开 GPU 调试均可)后:

  • Event Browser:API 级 Draw 列表与耗时(GPU timing),找到最贵的那几个 Draw。
  • Pipeline State:某个 Draw 时刻的完整状态——顶点输入、光栅化、混合、深度,与 Frame Debugger 交叉验证。
  • Mesh Viewer / Texture Viewer:看光栅化覆盖、看采样到的到底是哪张图的哪个 mip。
  • Pixel Debug:对单个像素单步执行你的 shader,逐指令看中间值——光照不对、溶解边缘错位这类「数学错」的终极武器(部分 API 支持)。

编译产物:改代码前先看指令数

Shader Inspector → Compile and show variants:逐变体、逐平台列出:

  • 指令数(ALU/TEX/SAMPLER 分类):成本模型的「每次代价」输入,见 /notes/unity/performance-1/。
  • 临时寄存器数:超限会 spill,性能断崖;移动端寄存器预算更紧。
  • 平台汇编(DXIL/SPIR-V/AGL/Metal):读不读得懂另说,指令直方图必读。

变体列表同时确认 /notes/unity/engineering-3/ 的裁剪结果:shader_feature 没用的组合应该不在列表里。

Profiler:时间归属

  • Render 模块:Draw Call 数、SetPass、顶点数——CPU 侧提交成本。
  • GPU Profiler / 硬件计数器(支持的平台):GPU 侧各阶段耗时。
  • Deep Profile 会失真渲染性能,定位 CPU 提交用,不用于 GPU 结论。

一条标准排查流程

  1. Profiler 定位:CPU 还是 GPU、哪个阶段(提交多 vs 单 Draw 贵)。
  2. Frame Debugger:这个材质的 Pass 数、状态、参数对不对。
  3. Compile and show variants:指令数/寄存器是否异常,变体是否爆炸。
  4. 数学错而非性能错:RenderDoc Pixel Debug 单步。
  5. 改完回到 1 复测——没有复测就没有优化结论。

自检三问

  • URP 物体不进深度图,第一件工具是什么、看什么?
  • 「光照结果不对」和「光照太慢」分别用哪件工具?
  • 寄存器数在哪看,它爆掉的症状是什么?