L'ordre d'alignement et de déclaration des uniformes est-il important?

10

Dans la section 6.4 Constant Buffers du livre Practical Rendering & Computation with Direct3D 11 (pages 325, 326), il est mentionné:

Par défaut, le compilateur HLSL tentera d'aligner les constantes de sorte qu'elles ne s'étendent pas sur plusieurs registres float4. [...] L'emballage d'un tampon de constantes HLSL peut également être spécifié manuellement via le mot clé packoffset.

Je suppose qu'une règle similaire s'appliquera à l'équivalent OpenGL, Uniform Buffer Objects, car ils correspondent à la même fonctionnalité matérielle.

Et les uniformes vanille? Quelles sont les règles qui s'appliquent lors de la déclaration d'uniformes?

uniform vec2 xy; // Can we expect the compiler to pack xy
uniform vec2 zw; // into a same four component register?

uniform vec2 rg;
uniform float foo; // Will this prevent from packing rg and ba?
uniform vec2 ba;   // If so, will foo eat up a full four components register?

Si le compilateur peut faire de telles optimisations, à quel point sont-elles bonnes? Pouvons-nous dire explicitement au compilateur de compresser ou non, et quand le devrions-nous?

Julien Guertault
la source

Réponses:

4

Je suis allé chercher une réponse, j'ai donc téléchargé l'analyseur de shaders d'AMD pour voir l'assemblage produit lors de la compilation pour GCN. Dans l'assemblage ci-dessous, les registres vectoriels sont v # et les registres scalaires sont s #.

Il semblerait que les uniformes, même les uniformes vectoriels, soient passés dans le shader en tant que scalaires séparés, donc un vec3 utiliserait 3 registres scalaires. Le bit que j'ai trouvé confus était le v0 à v4, je ne sais pas si v0 est un registre à 4 flotteurs complet ou un seul flottant dans un registre, avec un registre vectoriel complet s'étendant de v0 à v3. D'une manière ou d'une autre, il ne semble pas avoir changé entre les deux versions, je peux donc supposer que l'ordre de définition n'a pas affecté l'assembly.

http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/07/AMD_GCN3_Instruction_Set_Architecture.pdf

#version 450

uniform vec2 xy; 
uniform vec2 zw;

out vec4 v;

void main(){ 
    v.xy = xy; 
    v.zw = zw; 
}

shader 
  asic(VI)
  type(VS)

  v_cndmask_b32  v0, s0, v0, vcc               
  v_mov_b32     v0, 0                          
  v_mov_b32     v1, 1.0                        
  exp           pos0, v0, v0, v0, v1 done      
  s_andn2_b32   s0, s5, 0x3fff0000             
  s_mov_b32     s1, s0                         
  s_mov_b32     s2, s6                         
  s_mov_b32     s3, s7                         
  s_mov_b32     s0, s4                         
  s_buffer_load_dwordx2  s[4:5], s[0:3], 0x00  
  s_buffer_load_dwordx2  s[0:1], s[0:3], 0x10  
  s_waitcnt     expcnt(0) & lgkmcnt(0)         
  v_mov_b32     v0, s4                         
  v_mov_b32     v1, s5                         
  v_mov_b32     v2, s0                         
  v_mov_b32     v3, s1                         
  exp           param0, v0, v1, v2, v3         
end

#version 450

uniform vec2 xy;
uniform float z;
uniform vec2 zw;

out vec4 v;

void main(){ 
    v.xy = xy; 
    v.zw = zw;
    v.w += z;
}

shader 
  asic(VI)
  type(VS)

  v_cndmask_b32  v0, s0, v0, vcc              
  v_mov_b32     v0, 0                         
  v_mov_b32     v1, 1.0                       
  s_andn2_b32   s0, s5, 0x3fff0000            
  exp           pos0, v0, v0, v0, v1 done     
  s_mov_b32     s1, s0                        
  s_mov_b32     s2, s6                        
  s_mov_b32     s3, s7                        
  s_mov_b32     s0, s4                        
  s_buffer_load_dword  s4, s[0:3], 0x10       
  s_buffer_load_dwordx2  s[6:7], s[0:3], 0x00 
  s_buffer_load_dwordx2  s[0:1], s[0:3], 0x20 
  s_waitcnt     expcnt(0) & lgkmcnt(0)        
  v_mov_b32     v0, s4                        
  v_add_f32     v0, s1, v0                    
  v_mov_b32     v1, s6                        
  v_mov_b32     v2, s7                        
  v_mov_b32     v3, s0                        
  exp           param0, v1, v2, v3, v0        
end
Joshua Waring
la source
2
L'ordre de définition a affecté la mise en page. La partie pertinente ici est les s_buffer_load_dwordinstructions - celles-ci lisent les uniformes d'entrée, et le dernier nombre en hexadécimal est le décalage à lire. Il montre dans le premier cas xyest à l'offset 0 et zwà l'offset 16. Dans le second cas, vous avez xyà l'offset 0, zà l'offset 16 et zwà l'offset 32. Il apparaît que tous les uniformes sont individuellement alignés sur 16 octets et non emballés ensemble ou réorganisé.
Nathan Reed