GPU ベースの検証とDirect3D 12デバッグ レイヤー

このトピックでは、Direct3D 12 デバッグ レイヤーを最大限に活用する方法について説明します。 GPU ベースの検証 (GBV) を使用すると、CPU での API 呼び出し中に不可能な GPU タイムラインでの検証シナリオが可能になります。 GBV は、Windows 10 Anniversary Update 用のグラフィックス ツールから入手できます。

GPU ベースの検証の目的

GPU ベースの検証は、次のエラーを特定するのに役立ちます。

  • シェーダーでの初期化されていない記述子または互換性のない記述子の使用。
  • シェーダーで削除されたリソースを参照する記述子の使用。
  • 昇格されたリソース状態とリソース状態の減衰の検証。
  • シェーダー内の記述子ヒープの末尾を超えたインデックス作成。
  • 互換性のない状態のリソースのシェーダー アクセス。
  • シェーダーでの初期化されていない、または互換性のないサンプラーの使用。

GBV は、シェーダーに検証が直接追加されたパッチ適用されたシェーダーを作成することによって機能します。 パッチが適用されたシェーダーは、シェーダーの実行中にアクセスされたルート引数とリソースを検査し、ログ バッファーにエラーを報告します。 また、GBV は追加の操作を挿入し、ディスパッチ呼び出しをアプリケーション コマンド リストに挿入して、GPU タイムラインのコマンド リストによって課されるリソース状態の変更を検証および追跡します。

GBV にはシェーダーを実行する機能が必要であるため、COPY コマンド リストは COMPUTE コマンド リストによってエミュレートされます。 これにより、ハードウェアがコピーを実行する方法が変更される可能性がありますが、最終的な結果は変更しないでください。 アプリケーションでは、これらは COPY コマンド リストであると認識され、デバッグ レイヤーはそれらをそのように検証します。

GPU ベースの検証を有効にする

GBV は、Direct3D 12 デバッグ レイヤーを強制的に実行し、さらに GPU ベースの検証 (コントロール パネルの新しいタブ) を強制的に実行することで、DirectX コントロール パネル (DXCPL) の使用を強制できます。 有効にすると、DIRECT3D 12 デバイスが解放されるまで GBV は有効なままになります。 または、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 では処理速度が大幅に低下する可能性があります。 開発者は、パフォーマンスの問題を減らすために、小規模なデータ セット (エンジン デモや PSO とリソースが少ない小規模なゲーム レベルなど) または早期アプリケーションの起動中に GBV を有効にすることを検討できます。 コンテンツが大きい場合は、夜間テスト パスで 1 台または 2 台のテスト マシンで GBV をオンにすることを検討してください。

デバッグ出力

GBV は、 ExecuteCommandLists の呼び出しが GPU での実行を完了した後にデバッグ出力を生成します。 これは GPU タイムラインであるため、デバッグ出力は他の CPU タイムライン検証と非同期になる可能性があります。 アプリケーション開発者は、デバッグ出力を同期するために、独自の wait-after-execute を挿入できます。

GBV 出力は、シェーダーでエラーが発生した場所と、関連オブジェクトの現在の描画/ディスパッチ数と ID (コマンド リスト、キュー、PSO など) を識別します。

デバッグ メッセージの例

次のエラー メッセージは、"Main Color Buffer" という名前のリソースがシェーダー リソースとしてシェーダーでアクセスされたが、シェーダーが 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 を呼び出し、次のインターフェイスのメソッドを参照します。

次の列挙体と構造体を参照してください。