Open4

MiniShade: シェーダ命令セットの検討

okuokuokuoku

とりあえずUTS2シェーダを実行できるレベルを目指して、シェーダに必要な命令セットを決めたい。

目的

GPUを作りたい。 ... まぁ完全に作るかはともかく、自前のシェーダプロセッサを用意してパフォーマンス解析やリプレイに役立てたい。

例えばシェーダをlookup tableとか整数処理に変換して処理するといった"手抜き"の研究をしたいと考えている。

作戦

シェーダコンパイラを作るのは一見大変そうだが、

  • SPIR-Vは元々SSAに近い一時変数セマンティクスを持つ
  • SPIR-V Tools https://github.com/KhronosGroup/SPIRV-Tools にインライン化等の最適化機能が一通り揃っている
  • WebGL1では定数回数でないループは禁止されている(のでループは全てunrollでき、jumpは命令列のskipのみになる)

という性質があるためそこまで難しくない。はず。SPIR-Vをそのまま実行する形の実装はVulkanを使って作れているので、コンパイラを作る上で欠けているのはレジスタ割り付けの部分だけと言える。

ただシェーダ言語はSIMD的な意味のシャッフルが高機能だったりするので、命令のエンコードには気を使わないといけないかもしれない。

よって:

  1. 現状のWebGL1-on-Vulkan実装を改造して、SPIR-V命令列を分析できるようにする
  2. SPIR-V命令列をSPIR-V Toolsで処理し、インライン化によって関数定義やループ等を除去する
  3. 残った命令列をチェックし、インタプリタが実装するべき命令を列挙する

という流れで作業する。

okuokuokuoku

SPIR-V Toolsの最適化パス

... AggressiveDCE とか何回実行されるんだよ。。と、同時に割とそれぞれの最適化の制約が厳しいことも気になる。

また strength-reduction (2^nをビットシフトに変換する等)も -O に入っていないので、役に立ちそうな最適化を見繕って手動で有効にすることも考えた方が良いかもしれない。もっとも、WebGL1ではシェーダは整数を処理できないのでこれに関しては重要でない可能性が高いが。。

okuokuokuoku

最適化して逆アセンブルする

https://github.com/okuoku/yuniframe/commit/d32135d9007623d6141ba517bbfc49a222224ff0

https://github.com/okuoku/yuniframe/commit/2cfea9f7429d925de08de83c25d8bb89a2e8e8fc

適当なピクセルシェーダで逆アセンブルを取得してみた。

https://gist.github.com/okuoku/31818cf01e346fbfd2268f6973c22635

ここから、サポートすべき命令の洗い出しを行っていくことになる。SPIR-V自体にはかなりの数の命令が定義されているが、まぁ実際にサポートすべき命令は30〜40種類程度なのではないだろうか。