次の方法で共有


定数変数のパッキング 規則

パッキング ルールは、格納時にデータをどの程度厳密に配置できるかを決定します。 HLSL は、VS 出力データ、GS 入出力データ、および PS 入出力データのパッキング規則を実装します。 (IA ステージではデータをアンパックできないため、データは VS 入力用にパックされません)。

HLSL パッキング規則は、データを 4 バイト境界にパックする Visual Studio で #pragma パック 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; 
};

より積極的な梱包

配列をより積極的にパックできます。例を次に示します。 定数バッファーから次のような配列にアクセスするとします。

// Original array: not efficiently packed.
float2 myArray[32];

定数バッファーでは、上記の宣言は 32 個の 4 要素ベクトルを使用します。 これは、各配列要素がこれらのベクトルの先頭に配置されるためです。 ここで、これらの値を定数バッファーに (スペースなしで) 密にパックし、シェーダー内の配列に float2[32] 配列としてアクセスする場合は、代わりに次のように記述できます。

float4 packedArrayInCBuffer[16];
// shader uses myArray here:
static const float2 myArray[32] = (float2[32])packedArrayInCBuffer;

より厳密なパッキングは、アドレス計算のための追加のシェーダー命令の必要性に対するトレードオフです。