2012-01-09 22 views
2

新しいシェーダの1つで問題が発生しました。OpenGL ES 2.0 NVIDIA TEGRA 2アンロール

さまざまなデバイスでシェーダを試してみると、シェイダーはコンパイルされてスムーズに実行されます。

私はNVIDIAのTegra 2 GPU上でそれをしようとすると、ネイティブコードを実行している、私は以下のコンパイルエラーを取得:

シェーダは、コンパイルに失敗しました。頂点シェーダ (0):エラーC6002:256の命令制限を超えました。プログラムをコンパイルするために532命令が必要86行、1エラー。

私はNVIDIAのgcgコンパイラが実行しているいくつかの種類のアンロールによるものだと思いますが、この状況をどのように解決するかわかりません。

ここでif/elseステートメントのタイプを減らすことを試みました。単純な連続したifsの連鎖(問題が解決されたかどうかを確認するだけですが)があっても機能しませんでした。

私はすべてのif条件を1つだけ残してシェーダをうまくコンパイルしようとしましたが(実際には必要ありませんが)

これは私の頂点シェーダのコードです。フラグメントシェーダはgl_color情報を含んでいて、うまくコンパイルできます。

void main(){ 

//Converto direttamente in int, cosi le divisioni dopo sono piu veloci 
int_character_position = int(character_position); 

uniform_reference = (int_character_position/4); 

uniform_reference_sub_item = int(mod(character_position,4.0)); 

if(uniform_reference == 0) {   
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item];  
} else if(uniform_reference == 1) {  
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item];    
} else if(uniform_reference == 2) { 
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference == 3) { 
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference == 4) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 5) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 6) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 7) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 8) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 9) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 10) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 11) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 12) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 13) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 14) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 15) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 16) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 17) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 18) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 19) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 20) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 21) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 22) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 23) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
}     
v_texCoord.y = a_texture.y; 
v_texCoord.x = a_texture.x + (0.0105 * float(working_float)); 
gl_Position = myMVPMatrix * myVertex; 

答えて

2

のOpenGL ES 2.0実装では、通常、それらがサポートする命令の最大数を持っているが、それは非現実的であるように、最小数は、APIによって義務付けられていません。 Nvidia Tegraの実装はソースを532命令にコンパイルします。これは最大限を超えています。唯一の可能性は、(OpenGL ES 2.0の実装を変更することを除けば)より少ない命令でコンパイルできるようにシェーダを書き換えることです。

Nvidia実装の詳細を知らないと、working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item];のようなステートメントは、分岐と組み合わさって最終的に複数の命令(減算、ロード、格納、配列のインデックス作成が行われます)を行います。コンパイラは、異なるコードフローのために複数の命令を並列に実行することができない可能性があるため、一般的に問題になることが多い。

あなたの場合 - それ以外は場合 - コードはまだ同じ意味を持ちながら、それは以下の指示にコンパイルすることができるように書き換えることはとても簡単であれば、他のことは:

if(uniform_reference < 4) {   
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference < 8) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference < 12) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference < 16) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference < 20) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference < 24) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} 

すでに256命令の制限に合うかもしれません。 (シェーダコードでは、ルールの大まかな点は、GLSLコードのサイズが命令の数を概ね定義しているということです)。これにより、いくつかの指示も保存されます。最終的にはcharsequence_ [123456]の値を配列に入れ、uniform_referenceを定数で割った値とcharsequenceを添えてインデックスすることができます。

working_float = charsequence[uniform_reference/4][uniform_reference - uniform_reference_sub_item][uniform_reference_sub_item]; 

uniform_referenceuniform_reference_sub_itemでインデックス付けされた2つの配列をマージして、1つのレベルのインデックス作成も取り除くこともできます。

+0

ありがとうございます。私は私の要求を公表した直後に私のif文を修正しました。私はここで問題の解決に関するコミュニティを更新しました。 あなたの答えはとにかく素晴らしいです。あなたの親切な援助をありがとうございます。シェーダコードはかなりのプロトタイプで、最終的に実際に必要だったよりはるかに複雑でした:) ありがとうたくさんの男。 –