Regole di compressione per le variabili costanti

Le regole di compressione determinano la disposizione dei dati strettamente quando vengono archiviati. HLSL implementa regole di compressione per i dati di output di Visual Studio, i dati di input e output GS e i dati di input e output di PS. I dati non vengono compressi per gli input di Visual Studio perché la fase IA non può decomprimere i dati.

Le regole di compressione HLSL sono simili all'esecuzione di un #pragma pack 4 con Visual Studio, che inserisce i dati in limiti a 4 byte. Inoltre, HLSL include i dati in modo che non attraversi un limite di 16 byte. Le variabili vengono raggruppate in un vettore a quattro componenti specificato fino a quando la variabile non si disorienterà in un limite di 4 vettori; le variabili successive verranno rimbalzate al vettore a quattro componenti successivo.

Ogni struttura forza l'avvio della variabile successiva nel vettore a quattro componenti successivo. In alcuni casi viene generata la spaziatura interna per le matrici di strutture. Le dimensioni risultanti di qualsiasi struttura saranno sempre divisibile in modo uniforme per sizeof(vettore a quattro componenti).

Per impostazione predefinita, le matrici non vengono compresse in HLSL. Per evitare di forzare il sovraccarico ALU per i calcoli di offset, ogni elemento in una matrice viene archiviato in un vettore a quattro componenti. Si noti che è possibile ottenere la compressione per le matrici (e incorrere nei calcoli di indirizzamento) usando il cast.

Di seguito sono riportati alcuni esempi di strutture e le corrispondenti dimensioni compresse (dato: un float1 occupa 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; 
};

Imballaggio più aggressivo

È possibile comprimere una matrice in modo più aggressivo; ecco un esempio. Si supponga di voler accedere a una matrice simile alla seguente dal buffer costante:

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

Nel buffer costante, la dichiarazione precedente utilizzerà 32 vettori a 4 elementi. Questo perché ogni elemento della matrice verrà posizionato all'inizio di uno di questi vettori. Ora, se si desidera che questi valori vengano compressi strettamente (senza spazi) nel buffer costante e si vuole comunque accedere alla matrice nello shader come float2[32] matrice, è possibile scrivere invece quanto segue:

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

La compressione più stretta è un compromesso rispetto alla necessità di istruzioni aggiuntive dello shader per il calcolo degli indirizzi.