Apakah keselarasan dan deklarasi urutan seragam itu penting?

10

Di bagian 6.4 Buffer Konstan dari buku Rendering Praktis & Komputasi dengan Direct3D 11 (halaman 325, 326) disebutkan:

Secara default, kompiler HLSL akan berusaha untuk menyelaraskan konstanta sehingga mereka tidak menjangkau beberapa register float4. [...] Pengepakan untuk buffer konstan HLSL juga dapat secara manual ditentukan melalui kata kunci paket.

Saya berasumsi aturan serupa akan berlaku untuk OpenGL, Uniform Buffer Objects, karena mereka memetakan ke fitur perangkat keras yang sama.

Bagaimana dengan seragam vanila? Apa aturan yang berlaku saat mendeklarasikan seragam?

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?

Jika kompiler dapat melakukan optimasi seperti itu, seberapa baik mereka? Bisakah kita secara eksplisit memberitahu kompiler untuk berkemas atau tidak, dan kapan kita harus?

Julien Guertault
sumber

Jawaban:

4

Saya mencari jawaban, jadi saya mengunduh penganalisa shader AMD untuk melihat perakitan yang dihasilkan saat dikompilasi untuk GCN. Dalam rakitan di bawah ini register vektor adalah v # dan register skalar adalah s #.

Akan terlihat bahwa seragam bahkan seragam vektor dilewatkan ke shader sebagai skalar yang terpisah, sehingga vec3 akan menggunakan 3 register skalar. Bit yang saya temukan membingungkan adalah v0 ke v4, saya tidak yakin apakah v0 adalah register float 4 penuh atau float tunggal dalam register, dengan register vektor penuh yang mencakup v0 ke v3. Salah satu cara atau yang lain itu tampaknya tidak berubah di antara dua versi sehingga saya dapat menganggap urutan definisi tidak mempengaruhi perakitan.

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
sumber
2
Urutan definisi memang memengaruhi tata letak. Bagian yang relevan di sini adalah s_buffer_load_dwordinstruksi - mereka membaca seragam input, dan angka terakhir dalam hex adalah offset untuk dibaca. Ini menunjukkan dalam kasus pertama xyadalah pada offset 0 dan zwpada offset 16. Dalam kasus kedua Anda memiliki xypada offset 0, zpada offset 16, dan zwpada offset 32. Tampaknya semua seragam secara individual 16-byte-sejajar, dan tidak dikemas bersama atau memesan kembali.
Nathan Reed