Czy kolejność wyrównania i kolejności mundurów ma znaczenie?


10

W rozdziale 6.4 Stałe bufory książki Practical Rendering & Computation with Direct3D 11 (strony 325, 326) wspomniano:

Domyślnie kompilator HLSL będzie próbował wyrównać stałe tak, aby nie obejmowały wielu rejestrów float4. [...] Pakowanie stałego bufora HLSL można również określić ręcznie za pomocą słowa kluczowego packoffset.

Zakładam, że podobna zasada będzie miała zastosowanie do równoważnika OpenGL, Uniform Buffer Objects, ponieważ są one odwzorowane na tę samą funkcję sprzętową.

A co z mundurami waniliowymi? Jakie zasady obowiązują przy deklarowaniu mundurów?

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?

Jeśli kompilator może przeprowadzić takie optymalizacje, to czy są one dobre? Czy możemy wyraźnie powiedzieć kompilatorowi, czy ma się spakować, czy nie, i kiedy powinniśmy?

Odpowiedzi:


4

Poszukałem odpowiedzi, więc pobrałem analizator cieniujący AMD, aby zobaczyć zestaw wyprodukowany podczas kompilacji dla GCN. W poniższym zestawie rejestry wektorowe to v #, a rejestry skalarne to s #.

Wydaje się, że mundury, nawet mundury wektorowe są przekazywane do modułu cieniującego jako osobne skalary, więc vec3 użyłby 3 rejestrów skalarnych. Bit, który uznałem za mylący, to v0 do v4, nie jestem pewien, czy v0 jest pełnym rejestrem 4 zmiennoprzecinkowym czy pojedynczym zmiennoprzecinkowym w rejestrze, z pełnym rejestrem wektorowym od v0 do v3. Tak czy inaczej nie wydawało się, aby zmieniało się między dwiema wersjami, więc mogę założyć, że kolejność definicji nie wpłynęła na zestaw.

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
Kolejność definicji wpłynęła na układ. Odpowiednią częścią tutaj są s_buffer_load_dwordinstrukcje - one czytają mundury wejściowe, a ostatnia liczba w hex jest przesunięciem do odczytu. Pokazuje, że w pierwszym przypadku xyjest z przesunięciem 0 i zwz przesunięciem 16. W drugim przypadku masz xyprzesunięcie 0, zprzesunięcie 16 i zwprzesunięcie 32. Wygląda na to, że wszystkie mundury są indywidualnie wyrównane 16-bajtowo i nie są pakowane razem lub ponownie uporządkowane.
Nathan Reed,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.