ユニフォームの整列と宣言の順序は重要ですか?


10

Practical Rendering&Computation with Direct3D 11(pages 325、326)」のセクション6.4 Constant Buffersで言及されています。

デフォルトでは、HLSLコンパイラーは定数が複数のfloat4レジスターにまたがらないように定数を調整しようとします。[...] HLSL定数バッファーのパッキングは、packoffsetキーワードを使用して手動で指定することもできます。

同じハードウェア機能にマップするため、OpenGLの同等のUniform Bufferオブジェクトにも同様のルールが適用されると思います。

バニラのユニフォームはどうですか?ユニフォームを宣言するときに適用されるルールは何ですか?

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?

コンパイラーがそのような最適化を実行できる場合、それらはどの程度優れていますか?コンパイラーにパックするかどうかをコンパイラーに明示的に指示できますか?

回答:


4

答えを探しに行ったので、AMDのシェーダーアナライザーをダウンロードして、GCN用にコンパイルしたときに生成されたアセンブリを表示しました。以下のアセンブリでは、ベクトルレジスタはv#であり、スカラーレジスタはs#です。

ベクトルのユニフォームでさえユニフォームも個別のスカラーとしてシェーダーに渡されるように見えるため、vec3は3つのスカラーレジスタを使用します。混乱したビットはv0からv4でした。v0が完全な4浮動小数点レジスタであるか、レジスタ内の単一の浮動小数点であり、完全なベクトルレジスタがv0からv3に及ぶかどうかはわかりません。どういうわけか、2つのバージョン間で変更されているようには見えなかったため、定義の順序がアセンブリに影響を与えなかったと想定できます。

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指示です-それらは入力ユニフォームを読み込んでおり、16進数の最後の数字は読み込むオフセットです。最初のケースxyはオフセット0とzwオフセット16にあることを示しています。2番目のケースはxy、オフセット0、zオフセット16、zwオフセット32にあります。すべてのユニフォームは個別に16バイト境界で整列され、パックされていません。一緒にまたは再注文。
ネイサンリード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.