AGAL入門 #3 : AGALMiniAssemblerのassemble時のエラー文言詳細

第三弾です。AGALMiniAssemblerの中を覗きつつ、バイトコード生成時にエラーになるパターンを確認したので、まとめてみます。なお、AGALMiniAssemblerはStarling2.0に付属してきたものを見ています。

下記、エラーテキスト内の数字部分は見つかった行数などを示すので、場合によるものとします。

#そもそも使い方違うよ編

* mode needs to be "fragment" or "vertex" but is ... 
断片(fragment)シェーダーか頂点(vertex)シェーダーを指定してくれ

* opcode is only allowed in vertex programs.
頂点シェーダーでしか使えない命令をつかっている

* opcode is only allowed in fragment programs.
断片シェーダーでしか使えない命令をつかっている

* register operand 0 (...) only allowed in vertex programs.
その引数レジスタは頂点シェーダーでしか使えない

* register operand 0 (...) only allowed in fragment programs.
その引数レジスタは断片シェーダーでしか使えない

* opcode requires version 2.
AGALバージョン2でしか使えない命令を使っている

* too many opcodes. maximum is 2048.
命令が長すぎる (AGAL1では200token、AGAL2では1024tokenが最長のはずですが、AGAL3の2048で判定されているようなので、AGAL3未満ではエラー文言を見る前に上手く動かなくなりそうなので注意)

#各命令編

* register operand 0 (80) index exceeds limit of 8.
その番号のレジスタはない、数字が大きすぎる
 
* wrong number of operands. found 3 but expected 2.
引数に指定したレジスタ数がおかしい、(もしくはレジスタ名が不正)

* could not parse operand 1 (...).
レジスタ名が不正、(具体的にこれを起こさせるレジスタ指定は不明)

* could not find register name for operand 1 (ot0).
レジスタ名がおかしい (数字は場合による、ここでは不正なレジスタ名`ot0`を指定した)

#Relative Addressing編
以下は相対アドレス指定を行った場合のみ起こるエラー 

※ 頂点シェーダーのみ、vc[vt0.y]のような形でvcレジスタの値を別のレジスタの値を用いて参照できるようです。
`vt0={0,1,2,3}`の場合`vc[vt0.y]`は`vc1`を参照することになります。vc[vt0.z+10]のような形でさらにオフセットを指定することもできるようです。まだ、オフセットがなにか確認できていないのですが、`vc[vt0.z+10]`はvc12を指すと言うことでしょうか。

* register operand 1 (....) relative adressing not allowed in fragment programs.
相対アドレス指定は断片シェーダーでは使えない _(adressingってタイポだよな..)_

* relative can not be destination
相対アドレス指定は出力指定レジスタには使えない

* bad index register
相対指定につかったレジスタ名がおかしい （[]内部の方)
(このエラー再現できず)

* bad index register select" （[]内部の方でxyzw部分)
相対指定につかったレジスタのコンポーネント指定がおかしい
(このエラー再現できず)

* index offset ... out of bounds. [0..255]
相対インデックスの指定の+n部分で指定したオフセット値が正しい数値範囲でない
`vc[vt0.z+10]`の`+10`部分です。

#Warning編

* warning: bad line 5: ...
その行の命令は、知らない/おかしい、(ので無視します)

# Program3D.upload時に出るエラー
* Bad AGAL source operands. Both are constants (this must be precomputed) at token 1 of fragment program.
定数同士を演算しようとした。 absの引数に定数を持ってきても出るようです。(一度テンポラリレジスタに移動する必要あり。）

* Temporary register read without being written to for source operand 1 at token 1 of fragment program.
値が設定されていないレジスタにアクセスしようとした。(コンポーネント要素ごとに初期化が必要な模様。wだけ書き込んでなくてもこのエラーがでた。)

* Can not read from output register for source operand 1 at token 13 of fragment program.
出力レジスタの値を参照しようとした 

* Constant registers can not be written to for destination operand at token 13 of fragment program.
定数レジスタに書き込もうとした

* Varying registers can only be read in fragment programs for source operand 1 at token 6 of vertex program.
Fragmentシェーダーでvレジスタに書き込もうとした。（Fragmentシェーダーでは読み込み専用になる。）

* Attribute registers can not be written to for destination operand at token 10 of vertex program.
vaレジスタに書き込もうとした。

* Color output written to multiple times. At token 22 of fragment program.
Fragmentシェーダーでocに２回出力した。

ここは、まだまだありそうです。

# おかしいのにエラーにならない編
* `ft0.sss` 存在しないプロパティ指定
* `ft0.xxxxxx` 長すぎるプロパティ指定
* `mov ft1, ftt0` fttはft0と認識されている模様

#まとめ
シンタックス的なチェックはAGALMiniAssembler側で、意味合い的なチェックはProgram3D側で行われているようです。xyzwのコンポーネント側はあまりきちんとエラーチェックされていない模様。また、AGALMiniAssemblerは高度なことをやっている反面、ソースを読み込むとあまり丁寧に作られていないような印象を受けます。チラホラとバグがありそうです。

vcレジスタの相対参照機能なのですが、これはAGALMiniAssemblerの機能ではなく、Stage3D側の機能のようです。ソースを解析していて見つけたのですが、どこにドキュメントがあるんでしょう。。。とりあえず動いたので、複雑な頂点シェーダを書く際には役に立ちそうです。別途、記事にした方がいいのかな。

さて、tipsなのですが、Starlingをswcで読み込んでいる場合でも、AGALMiniAssembler.asをソース側に置いておくとそれが使われるので、ブレークポイント仕込む場合などに有効でした。これはAGALMiniAssembler以外でも使えるテクですね。

他、なにかあれば随時追記します。では。