CPU 侧(11030 篇)搞完,轮到 GPU。GPU 剖析的工具链分两层:stat gpu 和 RDG 的 GPU 时间戳告诉你哪个 Pass 贵;RenderDoc 这类帧抓取工具告诉你这个 Pass 里哪次绘制贵、为什么。两层信息互补,只看一层容易走弯路。
第一层:stat gpu 与 GPU 时间戳
stat gpu 输出的是 RDG 各 Pass 的耗时聚合,数据源是 GPU timestamp query——RDG 在每个 Pass 前后插入时间戳对,驱动执行完一轮后回读相减。RDG 的好处是 Pass 结构天然带语义名(BasePass、Lighting、PostProcessing),拿到的是"光照 4ms、后处理 2ms"这种可直接行动的数字。
用之前先知道它的三个坑:
- 时间戳粒度:timestamp 的精度取决于 GPU 和驱动,常见分辨率是微秒级到几十微秒级。0.05ms 的 Pass 测出来是 0.03 还是 0.07 别太当真,看 0.5ms 以上的量级;
- 异步重叠失真:compute/async copy 和 graphics 并行执行时,时间戳对测的是"这两个时间点之间 GPU 走了多久",不是"这个 Pass 占了多少 GPU"。开了 Lumen/Niagara GPU sim 的项目,把 async 通道的耗时和 graphics 直接相加会重复计数。RDG 的
stat gpu输出里 async 类 Pass 单独分组,就是提醒你这件事; - 分辨率耦合:Pass 耗时和渲染分辨率强绑定,pixel-bound 的 Pass 近似满足
$$T_{pixel} \propto N_{pixel} \times c_{shader}$$
$N_{pixel}$ 是着色像素数,$c_{shader}$ 是单像素开销。所以"降分辨率帧率涨多少"本身就是最好的 pixel-bound 判定实验:分辨率减半、某 Pass 耗时也减半,它就是像素瓶颈,优化方向在着色器质量和 overdraw;耗时几乎不变,它是顶点/固定功能瓶颈,方向在 draw call 和几何。
ProfileGPU 命令(r.ProfileGPU)把同一套时间戳落成 HTML 报告,抓完帧自动打开,适合留档和对比优化前后。
第二层:RenderDoc 抓帧
stat gpu 说"BasePass 6ms",这 6ms 花在哪儿还得下钻。RenderDoc 抓一帧,能看到每一次 draw call 的管线状态、绑定的纹理、shader 源码和耗时占比。和 UE 的接法:启用官方 RenderDoc 插件(编辑器插件列表里搜 RenderDoc)后可直接从编辑器抓取,或外挂 RenderDoc 注入进程。抓 Development/Test 构建,Shipping 的优化和裁剪会让抓取信息残缺。
抓帧里看什么,按效率排:
- 按耗时排序的绘制列表:最贵的几十个 draw 直接列出来,十有八九是超大网格 + 复杂材质的组合。对策不是砍美术,是问"这个物体为什么用了 400 个指令的 shader"——常见原因是材质里堆了没用上的特性(开关开了但没连节点也会进 permutation);
- 纹理尺寸:一张没必要的 4K 纹理既占带宽又占显存,RenderDoc 里看绑定纹理的实际尺寸和格式,顺手查有没有该压缩没压缩的(RGBA8 的 4K 纹理在移动端是灾难);
- 重复状态:同管线同纹理的连续小 draw 没被合批,说明合批机会没抓住——这是 11070 篇 Draw Call 优化的活,RenderDoc 负责提供证据。
过度绘制:Pass 耗时的隐藏乘数
两个像素工作量相同但 overdraw 差十倍的场景,stat gpu 数字天差地别。查 overdraw 用引擎自带的视图模式:Shader Complexity(看单像素指令复杂度)和 Quad Overdraw(看 2×2 像素 quad 的重复覆盖,更贴近真实代价)。植被、粒子、半透明 UI 是三大 overdraw 源,它们的共同点是"单看每个对象都合理,叠起来每个像素被刷了七八次"。
移动端的特别说明
上面的经验值以 PC(立即模式渲染)为基准。移动端 GPU 是 tiling 架构:没有传统意义上的 on-chip 深度缓冲往返,"降分辨率省时间"和 overdraw 的代价模型都不一样,更关键的是时间戳在部分移动端驱动上不可靠。移动端项目的 GPU 剖析换厂商工具:iOS 用 Xcode 的 GPU Frame Capture,Android 用 AGI。stat gpu 在移动端只能当粗筛。
闭环流程
一次完整的 GPU 定位通常是这样:stat unit 确认 Frame 跟 GPU 走 → stat gpu 圈出最贵的两三个 Pass → 分辨率实验判定 pixel-bound 与否 → RenderDoc 在贵 Pass 里找具体 draw 和纹理 → Shader Complexity/Quad Overdraw 补内容侧证据 → 改完用 ProfileGPU 落报告对比。每一步的工具各司其职,混用层级(拿时间戳的零头争论、拿 RenderDoc 的单帧当统计)是最常见的弯路。