catalinaの備忘録

ソフトウェアやハードウェアの備忘録。後で逆引きできるように。

DirectXのHLSLシェーダーをデバッグする

DirectXデバッグが捗る便利な機能があるのを知りました。かたりぃなです。

その名も「VisualStudio Graphics Analyzer」。

VisualとGraphicって似たような意味だと思ってしまう私は英語が苦手です。

環境

公式ドキュメント https://msdn.microsoft.com/ja-jp/library/hh873197.aspx

DirectXグラフィクスデバッガでできること

DirectXグラフィクスデバッガを使って次のことができました

これはデバッグが捗りますね。

DirectXグラフィックスデバッガを起動する

VisualStudio2015communityでは次の手順で起動できました

画面上部のメニューから、デバッグ->グラフィックス->グラフィックスデバッグの開始の順に選択。

メニューから操作はこんな感じです。 f:id:Catalina1344:20170526214208p:plain

キーボードショートカットは手元の環境ではAlt+F5でした。(古いVisualStudioのキーバインドにしているので、ほかの環境だと違うかもしれません。)

無事起動すると、上記スクリーンショットでメニューの後ろに見えているタブが開きます。

Graphics Analyzerを起動する

新しく開いたタブの画面下部のカメラアイコン「フレームのキャプチャ」をクリックすると、フレームがキャプチャできます。 キャプチャしたフレーム画像をダブルクリックすると、以下のような画面が起動します。

f:id:Catalina1344:20170526214523p:plain

DirectXに慣れてる人であれば、あとはもう直観で使えそうな見た目ですね。

レンダリングの命令が期待通りに呼び出されていることを確認する

まず画面左の「イベント一覧」ペインは名前のまんまですが、わかりやすくいうと 「C++から呼び出した関数のうち、GPUに設定が行われたもの」と考えておけばよさそうです。 DrawIndexedInstancedとかUpdateSubresourceとか並んでいますね。 まずはここで期待した命令が順序通りに呼び出されているか確認できます。 たとえば、

  • テクスチャの更新(UpdateSubresource)の呼び出しを確認
  • 行列の設定(UpdateSubresource)の呼び出しを確認
  • レンダリング処理(DrawIndexedInstanced)の呼び出しを確認

などがあります。 スクリーンショットの時点でジオメトリ情報がおかしそうという推測はできるので、さらに詳細を見るために次のステップに進みます

レンダリングパイプラインを確認する

先の画面でDrawIndexedInstancedの関数をクリック選択すると、レンダリングパイプラインが表示されます。 どうやら、このレンダリング命令で実行されたパイプラインのようです。

f:id:Catalina1344:20170526214245p:plain

パイプラインの各シェーダーオブジェクトをクリックすると、入出力パラメータが表示されます。 実行されなかったパイプラインステージは「ステージが実行されませんでした。(理由)」と表示されるのでわかりやすいです。 パイプラインステージの実行をデバッガで追いたいときは、右矢印ボタンを押すとデバッガが起動します。 デバッガはVisualStudioでC++デバッグするのと同じように操作できました。

レンダリングに関連するオブジェクトを確認する

GPUに転送したデータが期待したものかどうか確認したいことって多々あります。 頂点バッファ、インデックスバッファ、テクスチャ…。 Graphic Analyzerではこれも確認できました。 先ほど開いたパイプラインステージの表示で、左に「オブジェクトテーブル」があります。これに切り替えると、こんな画面になりました。

f:id:Catalina1344:20170526214551p:plain

GPU側へ設定したものが一通り載ってますね。便利。

ここまでの手順で、入力アセンブラの段階で頂点データがおかしそうというのが見えているので、頂点バッファとインデックスバッファを確認してみたいところです。

とりあえずBlendStateとか今は関係ないので、バッファだけ表示させます。

f:id:Catalina1344:20170526214800p:plain

これでバッファだけ表示されます。C++からみた変数名では引けないのでC++側から識別する情報を見ます。 C++のデバッガで確認してサイズを照らし合わせて、どっちのバッファが何を表しているかを確認しました。

この図でサイズの大きいほうが頂点バッファ、小さいほうはインデックスバッファのようです。

頂点バッファの中身を確認する

頂点バッファの中身も見れます。

先の手順で表示されたオブジェクトテーブルの中から、見たいバッファをダブルクリックするとバイナリで表示してくれます。

この頂点バッファビューはデフォルトでは16bit幅区切りの16進数表示です。 インデックスバッファは整数値だからこれでいいでしょうけれども、今見たいのは頂点バッファなので浮動小数点数です。 浮動小数点数を16進数でさらっと読めるほど私は訓練されていないので、もうちょっと見やすくします。 「形式」のところに型を指定するっぽいのでfloat3と入力してみました。

f:id:Catalina1344:20170526215159p:plain

すごく読みやすくなりました。 型がわからないときはドロップダウンにプリセットがあるので、適当に選択してそれっぽい型を選べばよさそうです。

感想

デバッガを使って確認すると作業早く進むのでいいですね。

今回悩んでいたバグの原因は頂点バッファの入力が正しくGPUに渡っていないようです。

今やっているのは複数個のモデルを表示するところなので、そのあたりの関連が怪しいですね。

ありがとうMicrosoftデバッグが捗ります。