2013-09-01 8 views
8

私の9600GTが嫌いです。必要に応じてGLSLシェーダがアンロールループにならない

フラグメントシェーダ:

#version 130 

uint aa[33] = uint[33](
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0 
); 

void main() { 
    int i=0; 
    int a=26; 

    for (i=0; i<a; i++) aa[i]=aa[i+1]; 

    gl_FragColor=vec4(1.0,0.0,0.0,1.0); 

} 

a=25プログラムは、3000 fpsで実行される場合。
a=26プログラムが20 fpsで動作する場合。
サイズがaa < = 32の場合は表示されません。
ビューポートのサイズは1000x1000です。
問題が発生するのは、aaのサイズが32より大きい場合だけです。
しきい値としてのaの値は、ループ内の配列への呼び出しによって異なります(aa[i]=aa[i+1]+aa[i-1]の期限が異なります)。
私はgl_FragColorが推奨されていません。しかしそれは問題ではない。

GLSLは、ループが> 25でサイズ(aa)> 32の場合、ループを自動的にアンロールしません。なぜ。配列の大きさに依存する理由は、人類には知られていません。

非常に類似した挙動は、ここで説明:
ループの巻き戻し http://www.gamedev.net/topic/519511-glsl-for-loops/

を手動aaサイズは> 32であったとしても、問題(3000 FPS)を解くん:

aa[0]=aa[1]; 
    aa[1]=aa[2]; 
    aa[2]=aa[3]; 
    aa[3]=aa[4]; 
    aa[4]=aa[5]; 
    aa[5]=aa[6]; 
    aa[6]=aa[7]; 
    aa[7]=aa[8]; 
    aa[8]=aa[9]; 
    aa[9]=aa[10]; 
    aa[10]=aa[11]; 
    aa[11]=aa[12]; 
    aa[12]=aa[13]; 
    aa[13]=aa[14]; 
    aa[14]=aa[15]; 
    aa[15]=aa[16]; 
    aa[16]=aa[17]; 
    aa[17]=aa[18]; 
    aa[18]=aa[19]; 
    aa[19]=aa[20]; 
    aa[20]=aa[21]; 
    aa[21]=aa[22]; 
    aa[22]=aa[23]; 
    aa[23]=aa[24]; 
    aa[24]=aa[25]; 
    aa[25]=aa[26]; 
    aa[26]=aa[27]; 
    aa[27]=aa[28]; 
    aa[28]=aa[29]; 
    aa[29]=aa[30]; 
    aa[30]=aa[31]; 
    aa[31]=aa[32]; 
    aa[32]=aa[33]; 
+0

だからあなたの質問は何ですか? –

+1

@NicolBolas a = 26のフレームレートが大幅に低下するのはなぜですか? – user2464424

+1

あなたが知っている唯一の人はOpenGLコンパイラを実装した人です。 –

答えて

5

私は入れていますここのコメントの要約的回答では、これはもはや未回答のようには見えません。

"の#pragma optionNV(すべてをアンロール)"

修正NVIDIAの即時問題。

一般に、GLSLコンパイラは実装に非常に依存します。ちょうど32のところにドロップがある理由は、「32よりも長いループをアンロールしない」のようなコンパイラヒューリスティックを打つことで簡単に説明できます。ダイナミックループにはアドレス可能なアレイメモリが必要ですが、巨大な速度差は定数を使ったアンロールループから来るかもしれません。もう一つの理由は、デッドコードの除去を解除するときに、ループ全体を無制限にするという一定のフォールディングが起きるということです。

これを修正する最もポータブルな方法は、実際に手動でアンローリングすることです。外部で計算できるフラグメントシェーダの定数を計算することは常に疑問です。いくつかのドライバはそれをキャッチすることもありますが、それに頼らない方が良いでしょう。

+1

ループの長さは32ではなく26であることを指摘します.32は配列のサイズです。基本的に、これは地獄の極端なケースです。互いに衝突する少なくとも3つの要素があります。1)ループがアンロールされた場合にのみデッドコードを削除するコンパイラ。 2)32個の浮動小数点の後にVRAM割り当てアレイに変わる定数配列。 3)自動的に展開される前のループの長さのしきい値は、ループ自体に含まれる変数の種類によって異なります。結論:私が掲載したコードは非常に悪い習慣であり、実際のシナリオでは決して使用しないでください。 – user2464424

関連する問題