我有一个带分支的相当简单的片段着色器,我有点不确定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读到有时两个分支都被执行,在这种情况下这不是一个好主意。如果没有进一步的信息或访问反汇编,我不确定该怎么想,以及如果出现问题该如何避免呢?
根据我的理解,基于统一变量的分支不会产生任何显着的开销,因为它在一次传递中是恒定的吗?
答案 0 :(得分: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
重新说一下科斯所说的,重要的是知道在执行之前是否可以知道保护条件。这是这种情况,因为c1
和c0
寄存器是常量(常量寄存器以字母'c'
开头),因此r1.x
寄存器值。
这意味着所有调用的片段着色器的值都相同,因此不会发生线程分歧。
顺便说一句,我正在使用AMD GPU ShaderAnalyser将GLSL转换为IL。 您还可以为特定代(从HD29xx到HD58xx)生成本机GPU汇编代码。这真是一个很好的工具!
答案 1 :(得分:5)
是的,IIRC你不会遇到性能开销,因为单个GPU处理器上单个批处理(warp)中的所有线程都将通过一个分支。 'thread'我的意思是'着色器的单个执行行'。
当给定处理器在给定时间执行一部分线程时出现效率问题(它最多可能是32个线程AFAIK;取决于硬件,我给出了G80架构的数字) 会分支到几个分支 - 一次两个不同的指令不能由一个处理器执行,所以首先“if”分支将由一部分线程执行(剩下的将等待),然后“否则“分支会由其他人执行。
你的代码不是这样,所以我相信你是安全的。