制服的排列和申报顺序重要吗?


10

在部分6.4恒定的缓冲器本书的实用渲染和计算用的Direct3D 11(325页,326)中提到:

默认情况下,HLSL编译器将尝试对齐常量,以使它们不跨越多个float4寄存器。[...] HLSL常量缓冲区的打包也可以通过packoffset关键字手动指定。

我假设类似的规则将适用于OpenGL等效的统一缓冲区对象,因为它们映射到相同的硬件功能。

香草制服呢?宣布制服时适用哪些规则?

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?

如果编译器可以进行此类优化,那么它们有多好?我们可以明确地告诉编译器是否打包,我们什么时候应该打包?

Answers:


4

我一直在寻找答案,所以我下载了AMD的着色器分析器,以查看为GCN编译时生成的程序集。在下面的汇编中,向量寄存器为v#,标量寄存器为s#。

似乎均匀甚至矢量均匀都作为单独的标量传递到着色器中,因此vec3将使用3个标量寄存器。我发现令人困惑的位是v0到v4,我不确定v0是完整的4浮点寄存器还是寄存器中的单个浮点,而完整的向量寄存器跨越v0到v3。在两个版本之间似乎并没有改变的一种或另一种方式,因此我可以假设定义顺序不影响程序集。

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
定义顺序确实影响了布局。这里的相关部分是s_buffer_load_dword指令-那些正在读取输入的制服,十六进制的最后一个数字是要读取的偏移量。在第一种情况下,它显示xy为偏移量0,zw在偏移量16处。在第二种情况下xy,偏移量为0,z偏移量为16,zw偏移量为32。似乎所有制服都分别按16字节对齐,并且未打包一起或重新排序。
内森·里德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.