2010-11-28 27 views
12

J'ai un fragment shader plutôt simple avec une branche et je ne sais pas comment il est géré par le compilateur GLSL et comment cela affecterait les performances.Comportement de branchement 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;   
} 

J'ai lu d'une AMDs document que, parfois, les deux branches sont exécutées, ce qui ne serait pas une bonne idée dans ce cas. Sans plus d'informations ni d'accès au démontage, je ne sais pas quoi penser de cela, et comment l'éviter si c'est un problème?

Et aussi d'après ce que je comprends d'une branche basée sur une variable uniforme ne subira pas de frais généraux importants car il est constant sur un seul passage?

Répondre

12

Ici vous avez:

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 

reformule un peu ce que dit Kos, ce qui importe est de savoir si la condition de garde peut être connu avant l'exécution. C'est le cas ici puisque les registres c1 et c0 sont constants (les registres constants commencent par la lettre 'c') et il en est de même de la valeur de registre r1.x. Cela signifie que cette valeur est la même pour tous les shaders de fragments invoqués, donc aucune divergence de thread ne peut se produire. Btw, j'utilise AMD GPU ShaderAnalyser pour transformer GLSL dans l'IL. Vous pouvez également générer un code d'assemblage GPU natif pour une génération spécifique (allant de HD29xx à HD58xx). C'est vraiment un bon outil!

+5

Dommage que ce soit Windows uniquement :( – ttvd

+0

+1 pour une réponse stricte et complète. :) – Kos

+0

Le lien est cassé –

5

Oui, l'IIRC ne génèrera aucun surcoût lié aux performances car tous les threads d'un seul lot (chaîne) sur un seul processeur GPU passeront par une seule branche. Par «fil», je veux dire «une seule ligne d'exécution du shader».

Le problème de l'efficacité se pose quand une partie de fils exécutés au moment donné par un processeur donné (which'd être jusqu'à 32 fils de discussion comme AFAIK, dépend du matériel, je donne les chiffres pour l'architecture G80) se branche en plusieurs branches - deux instructions différentes à la fois ne peuvent pas être exécutées par un processeur, donc premièrement la branche "if" serait exécutée par une partie des threads (et le reste attendrait), puis la branche "else" être exécuté par le reste.

Ce n'est pas le cas avec votre code, donc je crois que vous êtes en sécurité.