お願い
本記事では WebGLのデバッグでネイティブ向け3DAPIデバッガRenderDocが利用できるというTipsを紹介しております。しかし、
2023/08更新
現在のRenderDocではChromeに対するInjectionが使えなくなっているようです。ソースを見ると対策されてしまってますね。この記事の内容ももう役立たなくなってしまいました。
(古いバージョンのRenderDocか、ソースを修正してビルドすれば行けるとは思いますが)
RenderDocの方針としては、自分で開発したプログラムのデバッグに使うことを想定しているようで、Chromeのようなプロプライエタリ・ソフトウェアのデバッグは非サポートとのことです。ですので本記事で扱っているようなWebGL/WebGPUデバッグについての問い合わせをRenderDoc開発元にすることはしないでください。
以下のスレッドを見ても分かる通り、この手の問い合わせに開発元は相当辟易してしまっているようです。
https://github.com/baldurk/renderdoc/issues/810
https://github.com/baldurk/renderdoc/issues/1404
https://github.com/baldurk/renderdoc/issues/2030
これからは、代替としてPIXを使いましょう。
.
.
.
.
.
まぁ、見てくださいよ
ところで このデバッグ環境をみてくれ こいつをどう思う?
すごく・・・べんり・・・じゃん!!
と思ったので早速導入したところ、 おお、自己開発のオレWebGLライブラリでもフツーに値が取れるではないか!(感涙)
この感動をぜひ皆さんにも共有したく、私は新たなるQiitaポエム(本記事)を書こうと決意したのです。
本記事の狙い
WebGLのデバッグは辛いものです。CPU側つまりJavaScriptの処理はWebブラウザのデバッグ機能でいくらでもデバッグできます。
しかし、GPUに絡む処理はそうはいきません。
主に、デバッグ/チェックしたいと思う内容は次のようなものでしょう。
- GPU内部の各種GPUリソースの状態
- GPUの描画ステートの確認
- GPU内の各パイプラインステージのデータの流れ(頂点データやピクセルデータなど)
- シェーダーの計算内容
1,2までなら、Spector.js などのブラウザプラグインでなんとかなります。シェーダーコードも表示できます。
しかし、3や4のデバッグとなると、今までほぼ手段がありませんでした。
まぁ、4の方は、いわゆる色デバッグをすることで、なんとかやっているのが現状ではないでしょうか。
しかし、最近ではネイティブ3D開発で定番のデバッグツールRenderDocをWebGLでも使えないか、というトピックが密かに注目を集めているようです。
私も、昨年の @ukonpower さんの記事「WebGLデバッグに最強な「RenderDoc」」を読んだ時の衝撃と言ったらありません。
本記事では、@ukonpowerさんの記事をベースに、付加的なTipsをご紹介できればと思います。まぁそのつまり、なんだ、一から書くの面倒くさいんだ(´∀`)
RenderDocとは
WindowとLinuxで利用できる、3DAPI処理のデバッグツールです。
GPU処理にからむ多くの情報(テクスチャやレンダーバッファ、送信した頂点データ、シェーダーコードなどのGPUリソースや描画途中の状態など)を取得し、GPUを利用したリアルタイム3Dプログラミング時のデバッグ作業に役立てることができます。
あまりに定番過ぎて、最近のUnityやUnreal Engineのエディタと連携できたりもするんだって。すごいね!
(↑RenderDoc公式サイトトップページより。使用時のスクリーンショット)
また、GPUはしばらく前(GeForce 8800シリーズあたり?)の世代から、「割り込み処理」をサポートするようになっており、そのおかげでシェーダー変数の値をこのRenderDocデバッガでひとつひとつ確認することができます。
これこれ! これがWebGLで今までできなかったから、辛かったんです!
ぜひ、試してみましょう。
この記事を読むに当たっての前提
WebGLにおけるRenderDocの基本的な使い方については、
@ukonpower さんの記事「WebGLデバッグに最強な「RenderDoc」」に完全になげちゃいます。Windows環境ならあれでいけるはずなので、試してみてください(雑)
トラブルシュート
なんかうまくアタッチ・フレームをキャプチャできない
手順のコツとして、プロセスリスト中の当該プロセスの行をダブルクリックしてそのプロセスにアタッチできてから、Chromeのプロセス番号のダイアログを閉じる、という手順でないといけないみたい。先にダイアログの方を閉じてからプロセスアタッチしてもダメです。罠だね。まさにノウハウだね!
おそらく、GPU制御用のプロセスを生成して、帰ってきたプロセスIDをダイアログ表示。ユーザーがOKを押してダイアログを閉じてから実際のバックエンド3D APIのコンテキストを作成しているのでしょう。
ここらへんの処理タイミングは、もしかしたらこういうデバッグ用途を見越してGoogleの人がそうしたのかもしれませんね。
(ん? clike? clickの書き間違えやな爆)
途中から、batファイルをダブルクリック起動してもプロセス表示のダイアログが表示されなくなった
デバッグをいったん仕切り直す際は、Chromeの全プロセスを確実に終了させる必要があります。閉じ忘れたChromeウィンドウはないですか? 全て閉じてからやり直せばうまくいくはずです。それでもダメなら、タスクマネージャでゾンビ状態のChromeプロセスがないか探してあったら強制終了させましょう。
Chromeの起動オプションについて
本記事ではChromeに与える起動オプションとして --disable-direct-composition
の追加を推奨します。Chrome標準のコンポジション処理がデバッグ上、妨げになるようです。
https://groups.google.com/g/angleproject/c/Btbq9wZwslg/m/xjfzCVOMAwAJ
つまり、batファイルの中身はこんな感じです。
set RENDERDOC_HOOK_EGL=0
"C:\Users\ema_d\scoop\apps\googlechrome\current\chrome.exe" --disable-gpu-sandbox --gpu-startup-dialog --disable-direct-composition
(私はChromeをScoopでインストールしたのでパスが独特ですが)
さらには、「--in-progress-gpu」というオプションを付けることで、本来はタブのHTMLレンダリングプロセスとは独立したプロセスとして動作するGPU制御プロセスが、分離しなくなるようです(これについては、RenderDocを使う分には付けなくていいです)。
RenderDocではなく、VisualStudioのGPUデバッグ機能(Visual Studio Graphics Diagnostics)でデバッグしたい場合に、現時点では必要なオプションのようですね。
https://groups.google.com/g/angleproject/c/Btbq9wZwslg/m/9nPU886cAwAJ
https://bugs.chromium.org/p/chromium/issues/detail?id=961558
ここらへんは、また時間とともに状況が変わってくるのだと思います。
なお、起動オプションで --disable-gpu-sandbox
と付けているリスクを認識してください。サンドボックスによって守られなくなるので、GPU処理につけ込んだブラウザクラッシュやセキュリティ関連の攻撃に対して脆弱になります。
通常のWeb利用で使用するChromeではなく、別途デバッグ専用にChroniumなどをインストールして、そちらでRenderDocした方が安全だと思います。
ちなみに私はVivaldiというブラウザを常用しています。Vivaldiイイヨイイヨー!
制約
RenderDocのドキュメント
https://renderdoc.org/docs/how/how_debug_shader.html
によると、現時点では、シェーダーデバッグ機能はDirect3D11, Direct3D12のみのサポートのようです。
つまり、WebGLでシェーダーデバッグをやりたいのであれば、バックエンドがDirect3D11/12で動作するプラットフォームを選ぶ必要があるということですね。
Window版のChromeはそれに該当します。
シェーダーの変数の値の見方
さてお待ちかね。本題です。
ピクセルシェーダーの場合ですが、もうこのキャプチャ図を見てください(雑)
詳しくは、RenderDocのドキュメントの以下に、頂点シェーダの場合とピクセルシェーダの場合とそれぞれ方法が書かれています。
https://renderdoc.org/docs/how/how_debug_shader.html#debugging-a-vertex
ブラウザのデバッガとはやり方がだいぶ違いますね。
最初、「大量の頂点とピクセル、どうデバッグするんだ? 大量にある中「この頂点/ピクセル調べたい!」ってどうやって指定するん? 目的のモノが来るまでひたすら再生ボタン連打するんか?(汗)」とか思っていたんですが、
なるほど確かに、このやり方ならピンポイントで指定できますね。
しかも、シェーダーコード内をステップ実行することで、それぞれのコード実行の時点での値まで追って確認できてしまいます。神かな?
RenderDocの主な機能について
開発元がYoutubeチャンネルをやっていて、そこの動画でできることが大体わかります。
大体わかるというか、なにこれズル過ぎ。ネイティブガチ3D勢はこんな至れ尽せりな環境でデバッグしてたのかいo(`ω´ )o
いや実をいうと、だいぶ昔、あるプラットフォームで似たようなことはやってたんですが、このRenderDocそれ以上やな……。
技術的背景
そもそも、ブラウザで提供されているこの「WebGL」という3D APIは、非常に複雑な技術レイヤーで動いています。というのも、WebGLは実際にGPUを直接駆動しているAPIではないのです。
GPUを直接駆動できる(これもまた細かい話でいうと色々あるのですが)3DAPIは、今のところOpenGL, OpenGL ES, Direct3D 9/10/11/12, Metal, Vulkanのみです。これらを本記事ではネイティブ3D APIと呼びましょう。
WebGLは、実際はブラウザ内部の仕組みとして、JavaScriptで実行されたWebGL関数をこれらネイティブ3D APIの関数呼び出しに変えることで、GPUを駆動しています。
この表現も微妙なのですが、要はブラウザ内部にこうした各種ネイティブ3D APIを抽象化したレイヤーがあり、WebGLの関数を呼ぶとそのレイヤーの関数が動き、そして抽象化レイヤーの下の(いずれかの)ネイティブ3DAPIが動くことで、GPUを動かしているのです。
有名な抽象レイヤーとして、Googleが開発しているANGLEがあります。これはChromeだけでなくFirefoxにも採用されています。最近だとSafariでも採用されてきており、最近のニュースとしてSafariのWebGL2対応がこのANGLE採用によって一気に進展しました。
(↑ https://www.cs.uregina.ca/Links/class-info/390AN/WebGL/Lab1/ より図を引用)
この複雑さが、WebGLのシェーダーコードレベルのデバッガが登場しない理由の一つです。WebGLのデバッグなのに、Direct3Dのシェーダーコードが返ってきたらびっくりしますよね?(実はそういう事ができるWebGL拡張があったりもしますが…)
それだけでなく、セキュリティ的な理由もあったりします。あとは、こんな詳細デバッグが簡単に出来てしまうと、簡単に3Dデータをぶっこぬけてしまい、Webにおける3Dデータビジネス上危険という理由もあったりすると思います。
Future Work
HLSLのレベルでデバッグすることは可能か?
さて、試している最中で気が付かれたかとおもいますが、シェーダーコードの値見れると言っても……アセンブラやん……(´・ω・`)。
そう、GLSLやHLSLのようなシェーダーコードは、実際にはそれぞれのGPU向けの機械語にまでなって、実際には実行されます。その機械語に相当するアセンブリ言語として表示されてしまうんですね。
ただし、このドキュメント箇所を読むと、しかるべき設定をしてシェーダーデバッグ情報をうまく仕込むことができれば、HLSL言語レベルでデバッグすることも可能のようです。
https://renderdoc.org/docs/how/how_debug_shader.html#including-debug-info-in-shaders
例えばですが、Chromeのオープンソース版である、Chromiumをフォークして、ソースコードをいじってここらへんの対応を加えた野良ビルドを作ることで、HLSLデバッグなども出来てしまうかもしれませんね。これは今後の課題として取り組んでみたいと思います。
OpenGL ESのレベルでデバッグすることは可能か?
あと、 @ukonpower さんの記事「WebGLデバッグに最強な「RenderDoc」」で最初に作る.batファイルの1行目。
set RENDERDOC_HOOK_EGL=0
という環境変数ですが、これは1のときだとANGLEがエミュレートしているOpenGL ESのレベルでのデバッグが可能とのことです。このモードだと、WebGLに極めて近いOpenGL ESとしてデバッグできますから、通常のWebGLデバッガと似た感覚でデバッグができるかもしれません。
ただ、残念ながら、私の手元のWindows版Chromeでは、うまく動作してくれませんでした(コンテキストは認識するようなのですが、キャプチャボタンが有効になってくれません)
ですが、Linux環境であれば、Direct3DではなくOpenGLやOpenGL ESが直接のバックエンド環境なことが多いはずです。Linux上でLinux版RenderDocで試す、という手はいずれ試してみたいですね。
WebGPUはデバッグできるのか?
気になりますよね(笑) 原理的には可能な感じがします。これもそのうち試してみます!
2020/08/06追記:知人の報告によると、WebGPUでもある程度キャプチャができ、WebGL2のCompute Shaderの変数も見れた、とのことです。
RenderDocはどういう仕組みで動いているのか?
RenderDocはオープンソースソフトウェア(MITライセンス)です。ということは、ソースコードから様々なことを学べそうですね。これも時間があったらやってみたいですね。
注意
WebGLは非常に複雑な実装レイヤーによって実現されている(しかもプラットフォームによって大きな差異がある)3DAPIです。また、RenderDocはWebGLデバッグを公式サポートしていません。
それはどういうことかというと、デバッグすることによってPCに何らかの悪影響が起きたり、そもそもデバッグで取れる値や情報が100%信頼できるとは限らない、ということです。
こうしたプロダクトは、「できる」というのと「(十分な信頼性があると公式に言えるほど)問題なくできる」との間に大きな差があります。開発元が公式にサポートしていない条件であればなおのことです。
今回のデバッグ方法は、現時点でも極めて効果の高いデバッグ方法ではありますが、取れる値や情報の利用で何が起きても、最終的にはやった本人の自己責任です。開発元の責任ではありません。
そのリスクや限界を理解した上で試しましょう。
まとめ
いかがでしょう。「できる!」と気がついてから、衝動的に一気にその日のうちにこんな記事まで書いてしまいました。
まさしく「カッとなって」書いた記事なので、非常に荒く雑な記事になってしまい、大変恐縮です。
せっかくなので、この記事は長くメンテナンスしていければと思っています。
2023/08更新:
「お願い」の部分でも書きましたが、RenderDocでのデバッグはもうできなくなりました。
RenderDoc開発元はChromeでのWebGL/WebGPUデバッグをサポートしていませんので、くれぐれも開発元に迷惑をかけないようにしてください。