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.