L'allineamento e l'ordine delle dichiarazioni delle uniformi sono importanti?


10

Nella sezione 6.4 Buffer costanti del libro Rendering e calcolo pratici con Direct3D 11 (pagine 325, 326) è menzionato:

Per impostazione predefinita, il compilatore HLSL tenterà di allineare le costanti in modo che non si estendano su più registri float4. [...] L'imballaggio per un buffer costante HLSL può anche essere specificato manualmente tramite la parola chiave packoffset.

Presumo che una regola simile si applicherà all'equivalente OpenGL, Uniform Buffer Objects, poiché si associano alla stessa funzionalità hardware.

E le uniformi alla vaniglia? Quali sono le regole che si applicano quando si dichiarano le uniformi?

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?

Se il compilatore può fare tali ottimizzazioni, quanto sono buone? Possiamo dire esplicitamente al compilatore di impacchettare o no, e quando dovremmo?

Risposte:


4

Ho cercato una risposta, quindi ho scaricato l'analizzatore di shader AMD per visualizzare l'assemblaggio prodotto durante la compilazione per GCN. Nell'assieme in basso i registri vettoriali sono v # e i registri scalari sono s #.

Sembrerebbe che le uniformi anche le uniformi vettoriali vengano passate nello shader come scalari separati, quindi un vec3 userebbe 3 registri scalari. Il bit che ho trovato confuso è stato da v0 a v4, non sono sicuro se v0 sia un registro float completo 4 o un singolo float in un registro, con un registro vettoriale completo che vaga da v0 a v3. In un modo o nell'altro non sembrava cambiare tra le due versioni, quindi posso presumere che l'ordine di definizione non abbia influenzato l'assemblaggio.

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

2
L'ordine di definizione ha influito sul layout. La parte rilevante qui sono le s_buffer_load_dwordistruzioni: quelle stanno leggendo le uniformi di input, e l'ultimo numero in esadecimale è l'offset da cui leggere. Mostra che nel primo caso xyè nell'offset 0 e zwnell'offset 16. Nel secondo caso hai l' xyoffset 0, l' zoffset 16 e l' zwoffset 32. Sembra che tutte le uniformi siano allineate singolarmente a 16 byte e non impacchettate insieme o riordinati.
Nathan Reed,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.