2010-11-28 15 views
12

ブランチ付きのかなりシンプルなフラグメントシェーダがあります.GLSLコンパイラによってどのように処理されるのか、そしてパフォーマンスにどのように影響するのかは少し不明です。GLSLブランチの振る舞い

uniform sampler2D sampler; 
uniform vec2 texSize; 
uniform vec2 targetSize; 

void main()    
{     
    vec4 color; 
    if(texSize == targetSize) 
     color = texture2DNearest(sampler, gl_TexCoord[0]); 
    else 
     color = texture2DBicubic(sampler, gl_TexCoord[0]); 
    gl_FragColor = color;   
} 

私は、この場合には良い考えではないでしょう時には両方の分岐が実行されているAMDs documentから読みました。それ以上の情報や分解へのアクセスがなければ、私はこれについて何を考えるべきか、それが問題であれば避ける方法は不明です。

また、一貫性のある変数をベースにしたブランチは、一回の通過で一定であるため、大きなオーバーヘッドは発生しません。

答えて

12

あなたはそれを持っている:

il_ps_2_0 
dcl_input_generic_interp(linear) v1 
dcl_resource_id(0)_type(2d)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float) 
eq r2.xy__, c1.xyyy, c0.xyyy 
imul r5.x___, r2.x, r2.y 
mov r1.x___, r5.x 
if_logicalnz r1.x 
    sample_resource(0)_sampler(0) r6, v1.xyyy 
    mov r7, r6 
else 
    sample_resource(0)_sampler(0) r8, v1.xyyy 
    mov r7, r8 
endif 
mov r9, r7 
mov oC0, r9 
endmain 

はコスが言ったビットを修正してくださいするには、どのような重要なのガード条件は、実行前に知ることができるかどうかを知ることです。これは、c1c0のレジスタが一定であるため(定数レジスタは文字:'c'で始まります)、r1.xレジスタ値です。

これは、呼び出されたすべてのフラグメントシェーダーでこの値が同じであることを意味します。つまり、スレッドの相違は発生しません。

Btw、私はAMD GPU ShaderAnalyserを使ってGLSLをILに変換しています。 特定の世代(HD29xxからHD58xxまで)のネイティブGPUアセンブリコードを生成することもできます。これは本当に便利なツールです!

+5

あまりにも悪いのは窓だけです:( – ttvd

+0

+1厳密で完全な答えです:) – Kos

+0

リンクが壊れています –

5

はい、IIRCでは、単一のGPUプロセッサ上の単一のバッチ(ワープ)内のすべてのスレッドが単一の分岐を通過するため、パフォーマンスオーバーヘッドにはなりません。 「スレッド」とは、「シェーダの1つの実行ライン」を意味します。

与えられたプロセッサによって与えられた時間にスレッドの一部が実行された場合、効率の問題が発生します(これは32スレッドAFAIKに似ています;ハードウェアに依存します、私はG80アーキテクチャの番号を与えます)一度に2つの異なる命令を1つのプロセッサで実行することはできないため、最初に "if"ブランチがスレッドの一部によって実行され(残りは待機する)、次に "else"ブランチが実行されます残りの者によって実行される。

あなたのコードではそうではありません。あなたは安全だと思います。ここで