状況 #
一つのシェーダーを使いまわすより、別々にしたほうが楽だと考えて(instancingしたりしなかったりするのが難しい)、シェーダーを別に作って頂点シェーダーとバッファの構造を変更してwgpuのパイプラインも変更したら画面に何も表示されなくなった。
考えられる原因 #
原因としては
- 頂点、インデックスバッファが正しく積まれていない
- そもそも積み忘れている
- 積んだがdrawし忘れている
- drawされているが、座標が狂っていてカメラで捉えられない場所に描かれてしまっている
などが考えられる。
コードからデバッグするのは面倒だ。
カメラを動かして探すのもパット見で見つからなければそれ以上はやめておいたほうが良い。
見逃しと透明色で描かれている可能性があるからだ。
そこで、RenderDocというshaderや頂点などをデバッグできるスグレモノツールを利用する。
RenderDoc #
Windows, Linux向けのバイナリが↑から提供されている。
自分は環境のaptから入れた。
wgpuはバックエンドを選べるが、RenderDocは少なくともOpenGL, DirectX, Vulkanには対応している。
デバッグする #
RenderDocを起動してLaunch Applicationタブ
を開いてターゲットのバイナリ、オプションなどを設定する。
ターゲットの設定を保存/読み込みすることができる。
設定したらターゲットを起動。
正常に起動されれば左上に情報が表示されるはず。
デバッグしたいところまで進めてF12
を押すとフレームをキャプチャできる。
キャプチャされたフレームをダブルクリックするとオープンできる。
オープンすると色々見れるので今回はGPUのCallを漁ってDrawXXX
見たいなCallを探す。
当然関数名はバックエンド(Vulkan, DirectXなど)によって違う。
まあ知らなくても雰囲気で分かる。
vkCmdDrawIndexed
やvkCmdDrawXXX
などのDraw関連のCallを選択すると、右側に頂点、インデックスの一覧、右下にそれらの頂点を視覚化したものが表示される。
上の画像のvkCmdDrawIndexed
はegui(🔗https://github.com/emilk/egui)辺りがdrawしたものなので、目的のdrawを探して選択する。
結果、インスタンスが0になっていたので1つも描かれていなかった。
render_pass.draw_indexed(
0..(self.game_impl.current_objects.len() as u32
* OBJECT_LINE_LIST_INDICES.len() as u32),
0,
0..0, // <-- インスタンス数が0になっていた。
);
fn draw_indexed()
🔗https://docs.rs/wgpu/latest/wgpu/struct.RenderPass.html#method.draw_indexed
その他にもindicesの値の計算をミスっていて一部しか表示されないなどのバグがあったが、無事修正できた。
RenderDocがなければ今でも俺は3次元の暗闇を彷徨っていただろう。