Подтвердить что ты не робот

Поведение ветвления 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, который иногда выполняет обе ветки, что в этом случае было бы неплохо. Без дополнительной информации или доступа к разборке я не уверен, что об этом думать и как ее избежать, если это проблема?

А также из моего понимания ветвь, основанная на единой переменной, не будет нести каких-либо значительных накладных расходов, поскольку она является постоянной за один проход?

4b9b3361

Ответ 1

Здесь у вас есть:

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 регистрируется.

Это означает, что это значение одинаково для всех выделенных шейдеров фрагментов, поэтому не может произойти расхождение потоков.

Btw, я использую AMD GPU ShaderAnalyser для преобразования GLSL в IL. Вы также можете генерировать собственный код сборки GPU для определенного поколения (от HD29xx до HD58xx). Это действительно хороший инструмент!

Ответ 2

Да, IIRC вы не нажмете накладные расходы на производительность, так как все потоки в одной партии (warp) на одном процессоре GPU будут проходить через одну ветвь. Под "нитью" я имею в виду "одну строку выполнения шейдера".

Проблема эффективности возникает, когда часть потоков, выполняемых в заданное время данным процессором (который был бы таким же, как 32 потока AFAIK, зависит от оборудования, я даю номера для архитектуры G80) будет входить в несколько ветвей - две разные команды одновременно не могут быть выполнены одним процессором, поэтому сначала ветвь "if" будет выполняться частью потоков (а остальные будут ждать), а затем ветвь "else" будет выполняться посредством остальные.

Это не так с вашим кодом, поэтому я считаю, что вы в безопасности.