Aturan pengemasan untuk variabel konstanta

Aturan pengemasan menentukan bagaimana data yang ketat dapat diatur saat disimpan. HLSL menerapkan aturan pengemasan untuk data output VS, data input dan output GS, serta data input dan output PS. (Data tidak dikemas untuk input VS karena tahap IA tidak dapat membuka kemasan data.)

Aturan pengemasan HLSL mirip dengan melakukan #pragma paket 4 dengan Visual Studio, yang mengemas data ke dalam batas 4 byte. Selain itu, HLSL mengemas data sehingga tidak melewati batas 16 byte. Variabel dikemas ke dalam vektor empat komponen tertentu sampai variabel akan melekat pada batas 4 vektor; variabel berikutnya akan dipantulkan ke vektor empat komponen berikutnya.

Setiap struktur memaksa variabel berikutnya untuk memulai pada vektor empat komponen berikutnya. Ini terkadang menghasilkan padding untuk array struktur. Ukuran struktur apa pun yang dihasilkan akan selalu dapat dibagi secara merata berdasarkan ukuranof (vektor empat komponen).

Array tidak dikemas dalam HLSL secara default. Untuk menghindari memaksa shader mengambil overhead ALU untuk komputasi offset, setiap elemen dalam array disimpan dalam vektor empat komponen. Perhatikan bahwa Anda dapat mencapai pengemasan untuk array (dan menimbulkan perhitungan alamat) dengan menggunakan transmisi.

Berikut adalah contoh struktur dan ukuran kemasan yang sesuai (diberikan: float1 menempati 4 byte):

//  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; 
};

Pengemasan yang lebih agresif

Anda dapat mengemas array dengan lebih agresif; berikut adalah contohnya. Katakanlah Anda ingin mengakses array seperti ini dari buffer konstanta:

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

Dalam buffer konstanta, deklarasi di atas akan mengonsumsi 32 vektor 4 elemen. Itu karena setiap elemen array akan ditempatkan di awal salah satu vektor ini. Sekarang, jika Anda ingin nilai-nilai ini dikemas dengan erat (tanpa spasi) di buffer konstanta, dan Anda masih ingin mengakses array di shader sebagai float2[32] array, maka Anda dapat menulis ini sebagai gantinya:

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

Pengemasan yang lebih ketat adalah tradeoff versus kebutuhan untuk instruksi shader tambahan untuk komputasi alamat.