Desktop GPU で Vertex Shader と Pixel Shader の仕様が完全に
統一されたのは Direct3D 10 の ShaderModel 4.0 からです。
それまでは使える命令や Constant 領域、レジスタ数、プログラムサイズ、
テクスチャ命令など様々な違いが残っていました。
Hardware の Unified Shader 化は ATI の Xbox360 GPU が先行しています。
これが今の Qualcomm Adreno に繋がっていきます。
その後一般の Desktop PC 向けにも NVIDIA GeForce 8800 (G80) が登場し、
以後 Unified Shader model が当たり前となっています。
OpenGL ES 2.0 の Shader 世代は Direct3D 9 の Shader Model 3.0 に相当
するのですが、Mobile GPU の多くはすでに Unified Shader です。
そのためあまり Vertex と Fragment Shader の機能差を意識する必要が
ありませんでした。
そんな中、Tegra2/3/4 は G70 ベースの GPU であり、Unified Shader 化する前の
制限が残っている珍しいケースとなっています。
コメントで Tegra の Fragment Shader は動的ループが使えないとの
指摘を頂いたので試してみました。
// (1) 動的ループ int loop= int( uniform_value ); for( int i= 0 ; i < loop ; i++ ){ ... }
↑ループ回数を動的に求めた場合、Vertex Shader は通りますが
Fragment Shader ではコンパイル時にエラーが発生します。
以前書いたように Uniform 配列の index アクセス ↓(2) も
Tegra の Fragment Shader ではエラーとなります。
どちらも Direct3D 9 世代の制限と考えられます。
// (2) Uniform 配列 uniform vec4 src_color[30]; ~ int index= int(tex_color.x); vec4 color= src_color[ index ]; // Tegra の Fragment Shader では Error
Tegra 4 でも同様なので、大幅に機能拡張されていても GPU のベースは
同じであることがわかります。
なお Tegra と同じように Discrete Type の Shader Unit を備える
Mai-400MP では動きました。
Vertex Shader Fragment Shader 動的Loop Uniform配列 動的Loop Uniform配列 ----------------------------------------------------------- Unified ◯ ◯ ◯ ◯ Mali-400MP ◯ ◯ ◯ ◯ Tegra2/3/4 ◯ ◯ ERROR ERROR
ただし Tegra でも動的分岐はできるので、実行時にループ回数が変動する
場合でも同等の処理を実現することは可能です。
// (3) Tegra向け 動的分岐によるループ for( int i= 0 ; i< 100 ; i++ ){ if( i >= Loop ){ break; } ~ 動的ループ相当 }
以下まとめ (いずれも Fragment Shader の場合)
コンパイル時にループ回数が定まらない場合はエラー。
// (4) ループ回数不定 -- Tegra で ERROR for( int i= start ; i< end ; i++ ){ ~ }
ループの範囲が決まっていればコンパイル可能。
// (5) 上限が決まってる場合 -- Tegra でも OK for( int i= 0 ; i< 100 ; i++ ){ if( i >= start && i < end ){ ~ 動的ループ相当 } }
おそらく下記のように展開されているものと考えられます。
i= 0; if( i >= start && i < end ){ ~ } i= 1; if( i >= start && i < end ){ ~ } ~ i= 99; if( i >= start && i < end ){ ~ }
Tegra K1 以降は ShaderModel 5.0 世代の GPU core になるので
このようなハードウエア的な制限はなくなるでしょう。
GPU 互換性など気軽に相談してください。
関連エントリ
・OpenGL ES 2.0 Adreno 330, Tegra 4 の GPU 速度
・OpenGL ES 2.0 で迷路シェーダー
・GLSL互換性
詳細なレポートありがとうございます!
大変勉強になりました。