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

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

基于 GPU 的验证目的

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

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

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

由于 GBV 需要能够执行着色器,因此 COPY 命令列表由 COMPUTE 命令列表模拟。 这可能会更改硬件执行副本的方式,但不应更改最终结果。 应用程序仍会发现这些是 COPY 命令列表,调试层会验证它们。

启用基于 GPU 的验证

GBV 可以通过强制 Direct3D 12 调试层强制使用 DirectX 控制面板(DXCPL),并强制进行基于 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 上完成执行。 由于这是 GPU 时间线,因此调试输出可能与其他 CPU 时间线验证一起异步。 应用程序开发人员可能需要注入自己的等待后才能同步调试输出。

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

示例调试消息

以下错误消息指示在着色器中以着色器资源的形式访问名为“主颜色缓冲区”的资源,但在 GPU 上运行着色器时处于无序访问状态。 还提供了其他信息,例如着色器源中的位置、命令列表的名称和绘图计数(绘图索引),以及相关 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,并引用以下接口的方法:

请参阅以下枚举和结构: