定数変数のパッキング規則 (DirectX HLSL)

パッキング規則は、データを格納するときにデータをどれだけ密接にアレンジするかを指示します。HLSL では、VS 出力データ、GS 入力データと GS 出力データ、および PS 入力データと PS 出力データのパッキング規則を実装します (IA ステージではデータをアンパックできないため、VS 入力のデータはパックされません)。

HLSL パッキング規則は、Visual Studio での #pragma pack 4 の実行と似ています。これにより、データは 4 バイト境界にパックされます。また、HLSL は 16 バイト境界を越えないようにデータをパックします。変数は、その変数が 4 ベクトル境界にまたがるまで、指定の 4 要素ベクトルにパックされます。次の変数は、次の 4 要素ベクトルにバウンスされます。

各構造体は、次の変数に次の 4 成分ベクトルを開始させます。これは、構造体の配列にパディングを生成する場合があります。いずれの構造体の結果のサイズも、必ず sizeof(4 要素ベクトル) によって均一に割り切ることができます。

配列は既定では HLSL ではパックされません。オフセット計算で発生する ALU オーバーヘッドをシェーダーで引き受けないようにするために、配列のすべての要素を 4 要素ベクトルに格納します。キャスト処理を使用することで、配列のパッキングを実現できます (これによってアドレス指定計算が行われます) 。

次に、構造体とそれに対応するパック サイズの例を示します (float1 が 4 バイトを占有すると想定)。

 //  2 x 16byte elements cbuffer IE {     float4 Val1;     float2 Val2;  // starts a new vector     float2 Val3; };  //  3 x 16byte elements cbuffer IE {     float2 Val1;     float4 Val2;  // starts a new vector     float2 Val3;  // starts a new vector };  //  1 x 16byte elements cbuffer IE {     float1 Val1;     float1 Val2;     float2 Val3; };  //  1 x 16byte elements cbuffer IE {     float1 Val1;     float2 Val2;     float1 Val3; };  //  2 x 16byte elements cbuffer IE {     float1 Val1;     float1 Val1;     float1 Val1;     float2 Val2;    // starts a new vector };   //  1 x 16byte elements cbuffer IE {     float3 Val1;     float1 Val2; };  //  1 x 16byte elements cbuffer IE {     float1 Val1;     float3 Val2; };  //  2 x 16byte elements cbuffer IE {     float1 Val1;     float1 Val1;     float3 Val2;        // starts a new vector };   // 3 x 16byte elements cbuffer IE {     float1 Val1;      struct     {         float4 SVal1;    // starts a new vector         float1 SVal2;    // starts a new vector     } Val2; };  // 3 x 16byte elements cbuffer IE {     float1 Val1;       struct     {         float1 SVal1;     // starts a new vector         float4 SVal2;     // starts a new vector     } Val2; };  // 3 x 16byte elements cbuffer IE {     struct     {         float4 SVal1;         float1 SVal2;    // starts a new vector     } Val1;      float1 Val2;   // starts a new vector }; 

高密度なパッキング

より高密度に配列をパックできます。たとえば、次のような float 変数の配列があるとします。

 float4 array[16]; 

配列にまったくスペースが存在しないようにして、この配列を次のようにパックできます。

 static float2 aggressivePackArray[32] = (float2[32])array;  

この高密度なパッキングでは、その代わりとして、アドレス計算のために追加のシェーダー命令が必要になります。