渲染调试与抓帧
自动关联目录:渲染调试与抓帧
覆盖说明:官方调试内容分散于 TSR、RDG、VSM 等各篇(本篇汇总了那些篇里已核实的部分),引擎机制部分按源码与控制台工具组织。
1. 定位
渲染问题最难的地方不是修,是定位——因为一帧里有上百个 pass,且 CPU(三个线程)与 GPU 是流水并行的,stat gpu 里看到的数字往往不能直接归因。
一句话定位:先分清"哪个线程慢",再用对应工具抓那一层。工具选错,一天也查不出来。
2. 分层与对应工具
| 层 | 工具 |
|---|---|
| CPU:三个线程谁慢 | stat unit / stat unitgraph(见 管线与渲染线程) |
| CPU:Draw 线程细节 | stat sceneupdate、stat scenerendering |
| GPU:总览 | stat gpu、profilegpu |
| GPU:抓一帧看每个 pass | RenderDoc / PIX / Xcode / AGI、GPU Visualizer |
| GPU:引擎中间资源 | DumpGPU |
| 图结构与资源生命周期 | RDG Insights(见 RDG 渲染图) |
| 时域累积类问题 | DumpGPU 多帧 + TSR 可视化(见 TSR) |
| 内存 | memreport -full、LLM(见 Profile) |
3. 常用命令速查
CPU / 帧构成
| 命令 | 看什么 |
|---|---|
stat unit | Game / Draw / GPU / RHIT 四项时间 |
stat unitgraph | 同上,图形化,看抖动比数字直观 |
stat game | 游戏线程细分 |
stat sceneupdate | 场景更新(剔除、变换推送) |
stat scenerendering | 场景渲染各阶段 |
stat rhi | draw call、三角形、RT 数量 |
stat streaming | 流式加载(见 资源加载) |
stat anim | 动画 |
stat tsr | TSR feed 与 1spp(见 TSR) |
stat PSOPrecache | PSO 预缓存统计(见 PSO 预缓存) |
GPU
| 命令 | 看什么 |
|---|---|
profilegpu | 抓一帧,按 pass 列出 GPU 耗时 |
stat gpu | GPU 各分类耗时(CPU-bound 时不可靠) |
DumpGPU | 导出中间渲染资源,用 DumpGPU Viewer 查看 |
vis | 列出可可视化的纹理(Development 构建下 RDG 发布所有 UAV/RTV 写入) |
r.RDG.AsyncCompute 0 | profile 时关闭异步计算,得到可信计时(发布版绝不能关) |
r.ShaderPrintEnable 1 | 启用屏幕文字输出(某些统计依赖它) |
可视化视图
| 视图 | 用途 |
|---|---|
| Shader Complexity | 材质指令数(绿→红) |
| Quad Overdraw | 过度绘制,半透明性能第一视图 |
| Light Complexity | 光照重叠 |
| Lightmap Density | 光照贴图密度 |
| Nanite Visualization | Nanite 三角形/簇(见 Nanite) |
| Virtual Shadow Map | Cached Page / ShadowCasters 等(见 VSM) |
| Temporal Upscaler I/O / TSR | 时域超分输入与内部状态 |
| Motion Blur / Reprojection | 运动向量与重投影是否正确 |
vis SceneDepthZ 等 | 指定纹理 |
4. DumpGPU
已核实(TSR 篇)的推荐配置:
r.DumpGPU.Root="*TemporalSuperResolution*" ; 或 *PostProcessing* 限定范围
r.DumpGPU.FrameCount=30 ; 时域问题必须多帧
r.DumpGPU.Stream=1 ; 异步流式落盘,更快
r.DumpGPU.FixedTickRate=30 ; 固定 tick,避免抓取本身拖慢帧率
r.DumpGPU.Delay=3 ; 留时间复现
r.DumpGPU.CameraCut=1- 改了渲染分辨率后用
r.ResetRenderTargetsExtent让内部 RT 对齐 - 动态分辨率开启时可用
r.DynamicRes.TestScreenPercentage锁定渲染分辨率(内部 RT 大小仍由r.DynamicRes.MaxScreenPercentage控制) - 提交给 Epic 时用 7z 压缩 dump 目录
5. 平台工具
| 平台 | 工具 |
|---|---|
| Windows | RenderDoc、PIX、GPU Visualizer、Unreal Insights |
| Android | Android GPU Inspector (AGI)、Adreno Profiler、Mali Graphics Debugger、Simpleperf |
| iOS / macOS | Xcode Instruments、Metal GPU Capture |
| 主机 | 厂商自有工具 |
抓帧工具的通用用法:抓一帧 → 按 pass 看耗时 → 找到最贵的那个 → 回到引擎侧对应笔记查是哪一类问题。
6. 代价与权衡
| 手段 | 收益 | 代价 | 注意 |
|---|---|---|---|
stat unit | 零成本、立刻分层 | 只到线程粒度 | 必须先做这一步 |
profilegpu | 精确到 pass | 抓帧期间会慢 | 结果代表抓的那一帧 |
| DumpGPU | 能看到中间资源,跨帧比对 | 数据量大、生成慢 | Stream=1 + 限定 Root |
| RenderDoc | 最细,能看到实际 API 调用 | 学习成本、抓帧慢 | 开发机上用 |
| RDG Insights | 看图结构与生命周期 | 轨迹数据量很大 | 回答"为什么没并行/没重叠" |
| 可视化视图 | 直观 | 会轻微但可测量地影响性能 | profile 前务必关掉 |
r.RDG.AsyncCompute 0 | 计时可信 | 不代表真实发布性能 | 仅用于分析 |
7. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
| 用 GPU 思路优化 Game 线程 | 白费力气 | stat unit 先看四项谁高 |
stat gpu 数字忽高忽低 | 异步计算开着 | r.RDG.AsyncCompute 0 再测 |
| 开着可视化视图测性能 | 结果偏高 | 关掉所有 Show > Visualize |
CPU-bound 时信 stat gpu | 官方明确说不可靠 | 用 profilegpu 或平台工具 |
| 只抓一帧看时域问题 | 看不出累积过程 | r.DumpGPU.FrameCount=30 |
| 抓帧时没固定帧率 | 抓取本身改变了时序 | r.DumpGPU.FixedTickRate |
| 编辑器里流畅、打包后卡 | 编辑器配置不同 | 必须用打包版本测 |
没开 -clearPSODriverCache | 卡顿测不出来 | 见 PSO 预缓存 |
| 高核机器上测不出问题 | 与用户机器不符 | -corelimit=8 |
| 找不到崩溃的 setup 位置 | 栈是执行期 | r.RDG.ImmediateMode + r.RHICmdBypass |
8. 固定排查顺序
1. stat unit → 分清 Game / Draw / GPU / RHIT
2. Game 高 → 不是渲染问题,去 Profile
3. Draw 高 → stat sceneupdate → 剔除与代理更新
4. GPU 高 → 关可视化 + r.RDG.AsyncCompute 0 → profilegpu / 平台工具定位 pass
5. 特定伪影 → 选对应的可视化视图(TSR / VSM / Quad Overdraw / Shader Complexity)
6. 时域问题 → DumpGPU 多帧
7. 结构问题 → RDG Insights
8. 都不高但慢 → 同步点:Flush、加载、VSync参考
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/1209f5ca.html
更新于:2026年10月10日