基于 GPU 的验证和 Direct3D 12 调试层

本主题介绍如何充分利用 Direct3D 12 调试层。 基于 GPU 的验证 (GBV) 在 GPU 时间线上启用验证方案,在 CPU 上的 API 调用期间是不可能实现的。 GBV 从图形工具Windows 10周年更新开始可用。

基于 GPU 的验证的用途

基于 GPU 的验证有助于识别以下错误:

  • 在着色器中使用未初始化或不兼容的描述符。
  • 使用描述符引用着色器中已删除的资源。
  • 升级的资源状态和资源状态衰减的验证。
  • 索引超出着色器中描述符堆的末尾。
  • 处于不兼容状态的资源的着色器访问。
  • 在着色器中使用未初始化或不兼容的采样器。

GBV 的工作原理是创建已修补的着色器,这些着色器具有直接添加到着色器的验证。 修补的着色器检查在着色器执行期间访问的根参数和资源,并将错误报告给日志缓冲区。 GBV 还会将额外的操作和调度调用注入应用程序命令列表,以验证和跟踪 GPU 时间线命令列表施加的资源状态更改。

由于 GBV 需要执行着色器的功能,因此 COPY 命令列表由 COMPUTE 命令列表模拟。 这可能会改变硬件执行复制的方式,尽管最终结果不应更改。 应用程序仍会察觉到这些是 COPY 命令列表,调试层会对其进行验证。

启用基于 GPU 的验证

可以使用 DirectX 控制面板 (DXCPL) 强制启用 GBV,方法是在 Direct3D 12 调试层上强制启用 GBV,并在控制面板) (新选项卡强制启用基于 GPU 的验证。 启用后,GBV 将保持启用状态,直到发布 Direct3D 12 设备。 或者,可以在创建 Direct3D 12 设备之前以编程方式启用 GBV:

void EnableShaderBasedValidation()
{
    CComPtr<ID3D12Debug> spDebugController0;
    CComPtr<ID3D12Debug1> spDebugController1;
    VERIFY(D3D12GetDebugInterface(IID_PPV_ARGS(&spDebugController0)));
    VERIFY(spDebugController0->QueryInterface(IID_PPV_ARGS(&spDebugController1)));
    spDebugController1->SetEnableGPUBasedValidation(true);
}

通常,应在大多数时间启用调试层的情况下运行代码。 但是,GBV 可能会减慢速度。 开发人员可以考虑使用较小的数据集启用 GBV, (例如,引擎演示或具有较少 PSO 和资源的小型游戏级别) 或在早期应用程序启动期间启用 GBV,以减少性能问题。 如果内容较大,请考虑在夜间测试阶段在一台或两台测试计算机上启用 GBV。

调试输出

ExecuteCommandLists 的 调用在 GPU 上完成执行后,GBV 会生成调试输出。 由于这是在 GPU 时间线因此调试输出可能与其他 CPU 时间线验证是异步的。 应用程序开发人员可能希望注入自己的执行后等待以同步调试输出。

GBV 输出标识着色器中出错的位置,以及当前绘制/调度计数和相关对象的标识 (,例如命令列表、队列、PSO 等) 。

示例调试消息

以下错误消息指示名为“主颜色缓冲区”的资源在着色器中作为着色器资源进行访问,但着色器在 GPU 上运行时处于无序访问状态。 还提供了其他信息,例如着色器源中的位置、命令列表的名称和 Draw count (Draw Index) ,以及相关的 D3D 接口对象的名称。

D3D12 ERROR: Incompatible resource state: Resource: 0x0000016F61A6EA80:'Main Color Buffer', 
Subresource Index: [0], 
Descriptor heap index: [0], 
Binding Type In Descriptor: SRV, 
Resource State: D3D12_RESOURCE_STATE_UNORDERED_ACCESS(0x8), 
Shader Stage: PIXEL, 
Root Parameter Index: [0], 
Draw Index: [0], 
Shader Code: E:\FileShare\MiniEngine_GitHub_160128\MiniEngine_GitHub\Core\Shaders\SharpeningUpsamplePS.hlsl(37,2-59), 
Asm Instruction Range: [0x138-0x16b], 
Asm Operand Index: [3], 
Command List: 0x0000016F6F75F740:'CommandList', SRV/UAV/CBV Descriptor Heap: 0x0000016F6F76F280:'Unnamed ID3D12DescriptorHeap Object', 
Sampler Descriptor Heap: <not set>, 
Pipeline State: 0x0000016F572C89F0:'Unnamed ID3D12PipelineState Object',  
[ EXECUTION ERROR #942: GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE]

调试层 API

若要启用调试层,请调用 EnableDebugLayer

若要启用基于 GPU 的验证,请调用 SetEnableGPUBasedValidation,并引用以下接口的方法:

请参阅以下枚举和结构: