定数変数のパッキング規則 (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;
この高密度なパッキングでは、その代わりとして、アドレス計算のために追加のシェーダー命令が必要になります。