UE5 图形底层 Bug 不再靠猜:用 RHI Validation 和 D3D Debug 把错误写进 Log

在 UE5 中排查图形问题,最麻烦的情况往往不是直接崩溃,而是:

  • 画面偶发闪烁、黑块或白块
  • 某张纹理内容不正确
  • GPU 在某一帧突然挂掉
  • 换一张显卡或切换 DX11、DX12 后才复现
  • Debug 环境正常,打包后却出现随机问题
  • RenderDoc 中能看到结果异常,却很难找到是哪段代码破坏了资源状态

这类问题经常发生在 RHI、RDG 或图形 API 层。例如资源缺少状态转换、纹理被当成错误的用途访问,或者 SRV、UAV、Render Target 之间存在冲突。

正常运行时,驱动可能暂时容忍这些错误,也可能等到很晚才报错。最终看到问题的位置,往往已经不是错误真正发生的位置。

遇到这种情况,可以尝试在 UE5 启动时增加两个参数:

-RHIValidation -d3ddebug

它们可以开启两套不同层级的图形验证,把很多原本“静默发生”的底层错误直接输出到 UE Log 中。

两个参数分别做什么?

-RHIValidation:检查 UE 自己的 RHI 使用是否正确

RHI Validation 是 Unreal Engine 提供的一层验证机制。启用后,UE 会在真正的 D3D12、D3D11 或 Vulkan RHI 外面包一层 Validation RHI,对引擎发出的图形命令进行检查。

它比较擅长发现:

  • Texture、Buffer 的资源状态不正确
  • 缺少 Transition 或 Barrier
  • 资源当前状态与 SRV、UAV、Render Target 等用途不匹配
  • Graphics Queue 与 Async Compute Queue 之间的状态转换错误
  • CopyTexture、CopyBuffer 的参数或资源状态不合法
  • Shader Resource、Uniform Buffer 绑定异常
  • Transient Resource 的 Acquire、Discard、Aliasing 使用错误
  • 资源仍在命令流中使用时就被释放

简单来说,它检查的是:

UE 认为资源当前处于什么状态,以及代码接下来准备怎样使用它。

如果代码直接调用了底层 RHI,却没有按照 UE 的资源状态追踪规则补齐 Transition,RHI Validation 往往可以很快发现。

-d3ddebug:开启 Direct3D Debug Layer

-d3ddebug 开启的是 Direct3D Debug Layer,主要由 D3D11、D3D12 Runtime 对提交给图形 API 的操作进行检查。

它比较擅长发现:

  • D3D12 Resource State 不匹配
  • Command List 使用不合法
  • Descriptor、Resource View 参数异常
  • Copy 操作的范围、格式或状态错误
  • 已释放资源仍被 GPU 命令引用
  • D3D API 调用参数不符合规范
  • 部分资源泄漏和对象生命周期问题

它检查的是:

UE 最终提交给 Direct3D 的命令,是否满足 D3D API 的规则。

因此,-RHIValidation-d3ddebug 并不是重复功能。前者站在 UE RHI 的角度检查,后者站在 Direct3D Runtime 的角度检查。两者一起开启,通常能获得更完整的信息。

怎么使用?

以 Windows + D3D12 为例,可以这样启动编辑器:

UnrealEditor.exe "D:\Project\MyProject.uproject" -RHIValidation -d3ddebug -log

其中 -log 不是必须的,它只是额外打开一个实时日志窗口。

也可以修改编辑器快捷方式,在“目标”后面追加参数:

-RHIValidation -d3ddebug -log

如果要检查打包后的 Development 版本,也可以直接给游戏程序传参:

MyGame.exe -RHIValidation -d3ddebug -log

启动后,可以先在日志中确认功能是否已经开启。通常能够看到类似信息:

LogRHI: FValidationRHI on, intercepting D3D12 RHI!
LogD3D12RHI: InitD3DDevice: -D3DDebug = on

看到这些内容,说明验证层已经生效。

去哪里看错误?

编辑器中可以打开:

Window > Developer Tools > Output Log

也可以直接查看项目日志:

项目目录\Saved\Logs\项目名.log

建议优先搜索这些关键词:

RHI validation failed
LogRHI: Error
LogD3D12RHI
[D3DDebug]
Resource State
Transition
Barrier
SRV
UAV
CopyTexture

D3D Debug Layer 输出的错误通常带有这样的前缀:

LogD3D12RHI: Error: [D3DDebug] ...

RHI Validation 的错误通常出现在 LogRHI 分类中:

LogRHI: Error: RHI validation failed: ...

一个很重要的排查技巧是:

优先看第一次出现的错误,不要先看最后一次。

资源状态一旦被破坏,后面可能产生大量连锁报错。最早出现的 Validation Error,通常最接近真正的错误源头。

为什么它对底层图形 Bug 特别有用?

图形 API 很多操作都是异步执行的。

CPU 提交一个错误命令后,GPU 不一定马上执行。等到 GPU 真正访问错误资源时,CPU 可能已经跑过了几百甚至几千个函数。

因此,最终的 GPU Crash、Device Removed 或画面异常位置,未必是问题产生的位置。

Validation Layer 的价值,就是尽可能在错误命令被创建或提交时立刻指出问题,把排查范围从“整个渲染流程”缩小到某个资源、某次 Transition 或某次 API 调用。

例如,代码中直接复制一张纹理:

RHICmdList.CopyTexture(SourceTexture, DestTexture, CopyInfo);

如果 Source Texture 和 Dest Texture 没有进入正确的 Copy 状态,某些驱动上可能暂时看不出问题,换一张显卡后却出现白块、黑屏或随机闪烁。

开启验证后,日志可能直接告诉你:

  • 哪个 Resource 的当前状态不正确
  • 期望的状态是什么
  • 错误发生在 Copy、Draw 还是 Dispatch
  • 是否缺少对应的 Transition

这比从最终的错误画面反推原因,要高效得多。

几个需要注意的地方

1. 不要拿它做性能测试

Validation 会增加大量 CPU 检查,并可能改变线程时序。开启后的帧率和耗时不能代表正常运行性能。

它适合复现和定位问题,不适合长期默认开启。

2. -d3ddebug 需要安装 Windows Graphics Tools

如果启动时提示缺少 D3D Debug Interface,需要在 Windows 的“可选功能”中安装:

Graphics Tools

安装完成后重新启动编辑器即可。

3. -RHIValidation 通常用于 Debug 或 Development

RHI Validation 一般只会编译进 Debug、Development 等开发配置,Shipping 版本通常不会包含这套验证逻辑。

建议使用 Development Editor 或 Development Game 复现问题。

4. -d3ddebug 只针对 Direct3D

它适用于 Windows 下的 D3D11、D3D12。

如果问题只在 Vulkan 或 Android 上出现,需要使用 Vulkan Validation Layer、RenderDoc、厂商 GPU 工具或其他对应平台的调试能力。

5. Validation 不是万能的

它很擅长发现“操作不合法”,但不一定能判断“结果是否符合业务预期”。

例如:

  • Shader 算法本身写错
  • 材质参数传错
  • 光照公式不正确
  • 数据虽然合法,但内容不是想要的结果

这些问题仍然需要结合 RenderDoc、PIX、GPU Capture、Shader Debug 或代码日志进一步分析。

进阶:把 Warning 也输出出来

默认的 -d3ddebug 主要关注 Error。如果希望把 D3D Warning 也写入日志,可以增加:

-d3dlogwarnings

例如:

-RHIValidation -d3ddebug -d3dlogwarnings -log

不过 Warning 数量可能非常大,建议先只使用:

-RHIValidation -d3ddebug

如果没有找到线索,再进一步开启 Warning。

总结

以后在 UE5 中遇到难以解释的图形异常,尤其是修改了 RHI、RDG、Render Pass、纹理复制、Compute Shader 或资源状态转换之后,可以先带上:

-RHIValidation -d3ddebug

然后重新复现一次问题,重点查看 Log 中最早出现的:

RHI validation failed
[D3DDebug]

很多原本需要反复猜测、抓帧、换显卡才能定位的底层问题,可能会直接变成一条明确的资源状态或 API 使用错误。

这两个参数不能解决所有图形 Bug,但它们非常适合作为 UE5 底层图形问题排查的第一步。