GLSL разветвляющееся поведение - PullRequest
13 голосов
/ 29 ноября 2010

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

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

Ответы [ 2 ]

12 голосов
/ 29 ноября 2010

Вот оно:

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). Это действительно хороший инструмент!

5 голосов
/ 29 ноября 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...