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 は動的ループが使えないとの
指摘を頂いたので試してみました。
↑ループ回数を動的に求めた場合、Vertex Shader は通りますが
Fragment Shader ではコンパイル時にエラーが発生します。
以前書いたように Uniform 配列の index アクセス ↓(2) も
Tegra の Fragment Shader ではエラーとなります。
どちらも Direct3D 9 世代の制限と考えられます。
Tegra 4 でも同様なので、大幅に機能拡張されていても GPU のベースは
同じであることがわかります。
なお Tegra と同じように Discrete Type の Shader Unit を備える
Mai-400MP では動きました。
ただし Tegra でも動的分岐はできるので、実行時にループ回数が変動する
場合でも同等の処理を実現することは可能です。
以下まとめ (いずれも Fragment Shader の場合)
コンパイル時にループ回数が定まらない場合はエラー。
ループの範囲が決まっていればコンパイル可能。
おそらく下記のように展開されているものと考えられます。
Tegra K1 以降は ShaderModel 5.0 世代の GPU core になるので
このようなハードウエア的な制限はなくなるでしょう。
GPU 互換性など気軽に相談してください。
関連エントリ
・OpenGL ES 2.0 Adreno 330, Tegra 4 の GPU 速度
・OpenGL ES 2.0 で迷路シェーダー
・GLSL互換性
統一されたのは 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互換性