Open2
MiniShade: 制御命令の確認
シェーダコンパイラは可能な限り関数やループをフラットな形に変換する(関数はインライン化し、ループはアンロールする)。このため、実装すべき制御構造は非常にシンプルなものになる。
調査によって、 実装の必要がある制御命令は以下の6種類 ということがわかった:
例
OpReturn
以外はこのsnippetに全て出てくる:
3037: 7(fvec3) CompositeInsert 2549 432 0
1357: 6(float) Load 1356(vs_TEXCOORD5)
1358: 387(bool) FOrdLessThan 1357 43
SelectionMerge 1363 None
BranchConditional 1358 1362 1366
1362: Label
1365: 7(fvec3) VectorShuffle 1351 1351 1 2 3
Branch 1363
1366: Label
Branch 1363
1363: Label
2764: 7(fvec3) Phi 1365 1362 3037 1366
OpSelectionMerge
はWebGL1の制約では関係が無いので安全に無視できる。
OpBranchConditional
は2方向分岐。更にweightを設定できるが今回は無視する。
OpBranch
は単なるジャンプ。
OpPhi
は特殊なmove命令で、
2764: 7(fvec3) Phi 1365 1362 3037 1366
の場合、 2764
は 1365
(ラベル 1362
から始まるブロックを実行した場合) または 3037
(ラベル 1366
から始まるブロックを実行した場合) が代入される。SPIR-Vの一時変数はSSA(Static Single Assignment -- 単一静的代入)原則に従うため、 2764
への代入を2箇所に書くことができない 。
/* a = condition ? 100 : 200 を分岐を使って表現した場合 */
if(condition){
a = 100;
}else{
a = 200; // ★ 2箇所目の代入になるためSSAにならない
}
この制約を回避するためにSSAにはφ(ファイ)ノードと呼ばれる概念があり、 OpPhi
はそれを表現している。