PIXでWebGLやWebGPUをデバッグする

## はじめに

以前、RenderDocでWebGLをデバッグするための記事を書きました。

しかし、RenderDocはWebGLのデバッグは本来サポートしておらず、多数の問い合わせに辟易した（？）RenderDoc公式により、現在はChromeへのデバッグ機能自体が塞がれてしまっている状態です。

https://qiita.com/emadurandal/items/abe3488300ec9dccf9fe

そこで、今回はPIXでWebGLとWebGPUをデバッグする方法を共有したいと思います。PIXを使いますので、環境としてはWindows限定です。

PIXは以下からダウンロードできます。

https://devblogs.microsoft.com/pix/download/

## WebGLのデバッグ

### 1.PIXからChromeを立ち上げる
まず、PIXを立ち上げ、Launch Win32タブを選択します。

次に、`Path to excecutable`欄にChrome(私の場合はChrome Canaryを使っています)実行バイナリへのパスを設定します。

次に`Command line arguments`に以下の引数を設定します。

```
--no-sandbox --disable-gpu-watchdog --disable-features=RendererCodeIntegrity  --enable-dawn-features=emit_hlsl_debug_symbols,disable_symbol_renaming
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/237f5edd-a553-7e2e-b4a2-5cbc615d4aaf.png)

そして、`Force D3D11On12`オプションにチェックをいれます。

そこまでできたら、Launchボタンを押して、Chromeを起動します。

### 2. ChromeでデバッグしたいWebGLコンテンツを表示する

立ち上がったChromeでデバッグしたいWebGLコンテンツを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/fbbcbc6d-55ee-8049-206f-9e083b457e37.png)

### PIXでフレームキャプチャを行う

PIXの画面でカメラのアイコンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/d49b46e0-cdf2-53d6-32b5-6dea00db174f.png)

この状態でPIXがキャプチャをしようとするのですが、キャプチャするにはChromeの描画処理を捉えなければならないので、そのため一旦Chromeのウィンドウを最前面に出してください。

その後、PIXに戻ると、キャプチャされたスクリーンショットが表示されます。このスクリーンショットのボタンを押してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/27986659-fccd-5a7b-40d1-ce2d3febe0a2.png)

すると、フレームデバッガウィンドウが新たに表示されます。

### 3.フレームデバッグを行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/c4ea1332-1e0e-3b80-d6a1-82aa0084a135.png)

画面左上を見ると、解析されたフレーム中に実行されたDirect3Dコマンドのリストが表示されています（WebGLは水面下ではANGLEという中間層によってDirect3Dコマンドに変換されて実行されます）。もし、こういう表示になっていない場合は、`Overview`タブの画面になっているかもしれません。画面上部の`Pipeline`タブを押すとこの表示になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/d3214219-7a9c-695a-9095-7b26b885be6d.png)

さて、この画面左上のリストのうち、どれでもいいので適当なコマンド行を選択してください。

すると、画面右下に`click here to start analysis.`という文章があるので、`click here`とリンクになっている部分をクリックします。ダイアログが出てくるので、Yesを選択します。

すると、すべてのコマンドの解析処理が始まるので、画面が落ち着くまで一旦待ちましょう。処理中にあれこれUIをいじるとエラーが起きる可能性があるので、じっと待ちましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/6d94853d-8b83-dddd-92dc-c56d318520da.png)

画面が落ち着いたら、画面左上からどれかドローコール系のコマンドを選択してみましょう。
すると画面左下にパイプライン中の各工程のリストが出てくるので、このリストの一番下の`OM`の配下にある`RTV0`をクリックします。すると、この描画時点でのフレームバッファの画像を確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/def1c18f-4f3a-38c1-95f1-caae7442c961.png)

こんな感じで、フレームデバッグすることができます。色々試して遊んでみてください。

## WebGPUの場合

WebGLの時と手順は同じです。ただし、一点だけ違う点があります。ChromeをLaunchする際に、`Force D3D11On12`オプションは外してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/d20851ed-7224-b71b-9a88-2204bf89e1c5.png)

## PIXの様々な機能

### 頂点デバッグ

画面左下のパイプライン工程リストで、`VS->Output`を選択します。すると画面右下に頂点シェーダーを通った後のポリゴンをビジュアルに確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/2182c6b0-9fe9-d5eb-dbde-cc0a5fca236b.png)

さらに、各ポリゴンを選択することができ、右クリックから各頂点のデバッグに移行することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/eaf25473-5dca-d3f7-4c57-de102333a7e3.png)

頂点シェーダーデバッグ画面が表示されたら、画面左上の緑色の実行ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/d3cd5b63-e521-889b-2990-ab01cb1dae91.png)

すると、シェーダーが実行され、main関数の冒頭で一旦止まるので、ステップ実行したり、ブレイクポイントを仕掛けてそこまで移動したりしてみましょう。
画面下には変数リストが表示され、各ステップにおける各変数の値を確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/6cd20e15-cd18-6645-c458-54df0457e5e8.png)

## ピクセルデバッグ

画面左下のパイプライン工程リストで、`OM->RTV0`を選択します。そして、画面右下のフレームバッファ画像のどこでもいいので、どこかのピクセルを左クリックして選択します。次に、画面右下端にある`Debug Pixel`ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/6e04303f-4335-1cb9-dfda-a33db04d880a.png)

すると、ピクセルシェーダーデバッグ画面が出てくるので、頂点シェーダーデバッグ画面の時と同様の操作感でデバッグできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/32058bcc-8d07-6d2a-a2a7-4929c5a8daa3.png)

## シェーダーデバッグできる言語レベルについて

WebGPUの場合はChrome内部のWebGPU実装レイヤーDawnがデバッグ情報も含めてシェーダーをコンパイルしているらしく、PIXでHLSLのレベルでシェーダーデバッグすることができます。

一方、WebGLの場合はデバッグ情報が生成されていないようで、アセンブラのレベルでしかシェーダーコードが追えません。デバッグ情報を含めるようにChromiumのソースコードを改変してビルドしたものを使えばその限りではないかもしれませんが、ハードルはかなり高そうですね。

## Chromeに渡すオプションについて

私よりも前にPIXによるWebGLデバッグを検証している方がいて、Chromeに渡すオプションを検証してくれています。以下のGistの内容も参考にして色々試すとさらに良いデバッグ体験ができるかもしれません。

[https://gist.github.com/Popov72/41f71cbf8d55f2cb8cae93f439eee347](https://gist.github.com/Popov72/41f71cbf8d55f2cb8cae93f439eee347)

## 最後に

PIXによるWebGL/WebGPUのデバッグのやり方を見てきました。
PIXではOpenGLのデバッグができないので、WebGLをデバッグするときは内部的なDirect3Dコマンドとの脳内での対応付けが必要になり、あまり直感的ではないかもしれません。

しかし、WebGL命令レベルのデバッグはSpector.jsでできますし、おそらくPIXに手を出す方はSpector.jsではできない、各頂点やピクセルの具体的な値を見たり、各種バッファの値を確認したい、というよりディープな部分を確認したいのだと思います。なので、APIの違いはあまり問題にはならないでしょう。

PIXを活用して、WebGL/WebGPUのデバッグを大いにはかどらせましょう！