Costanti shader (HLSL)

Nel modello shader 4 le costanti shader vengono archiviate in una o più risorse del buffer in memoria. Possono essere organizzati in due tipi di buffer: buffer costanti (cbuffers) e buffer di trama (tbuffer). I buffer costanti sono ottimizzati per l'utilizzo di variabili costanti, caratterizzate dall'accesso a bassa latenza e dall'aggiornamento più frequente dalla CPU. Per questo motivo, le dimensioni, il layout e le restrizioni di accesso aggiuntive si applicano a queste risorse. I buffer delle trame sono accessibili come trame e offrono prestazioni migliori per i dati indicizzati in modo arbitrario. Indipendentemente dal tipo di risorsa usato, non esiste alcun limite al numero di buffer costanti o buffer di trama che un'applicazione può creare.

La dichiarazione di un buffer costante o di un buffer di trama è molto simile a una dichiarazione di struttura in C, con l'aggiunta delle parole chiave register e packoffset per l'assegnazione manuale dei registri o la compressione dei dati.

BufferType Name [: register(b#)] { VariableDeclaration [: packoffset(c#.xyzw)]; ... };

Parametri

BufferType

[in] Tipo di buffer.

BufferType Descrizione
cbuffer buffer costante
tbuffer buffer trama

Nome

[in] Stringa ASCII contenente un nome di buffer univoco.

register(b#)

[in] Parola chiave facoltativa, utilizzata per comprimere manualmente i dati costanti. Le costanti possono essere compresse in un registro solo in un buffer costante, in cui il registro iniziale viene assegnato dal numero di registro (#).

VariabileDeclaration

[in] Dichiarazione di variabile, simile a una dichiarazione di membro della struttura. Può trattarsi di qualsiasi tipo o oggetto effetto HLSL (ad eccezione di una trama o di un oggetto sampler).

packoffset(c#.xyzw)

[in] Parola chiave facoltativa, utilizzata per comprimere manualmente i dati costanti. Le costanti possono essere compresse in qualsiasi buffer costante, in cui il numero di registro è specificato da (#). La compressione dei componenti secondari (con scorrimento rapido xyzw) è disponibile per le costanti le cui dimensioni rientrano in un singolo registro (non superano un limite di registro). Ad esempio, un float4 non può essere compresso in un singolo registro a partire dal componente y perché non rientra in un registro a quattro componenti.

Osservazioni:

I buffer costanti riducono la larghezza di banda necessaria per aggiornare le costanti shader consentendo di raggruppare le costanti shader e di eseguirne il commit contemporaneamente anziché effettuare singole chiamate per eseguire il commit di ogni costante separatamente.

Un buffer costante è una risorsa buffer specializzata a cui si accede come un buffer. Ogni buffer costante può contenere fino a 4096 vettori. Ogni vettore contiene fino a quattro valori a 32 bit. È possibile associare fino a 14 buffer costanti per ogni fase della pipeline (2 slot aggiuntivi sono riservati per l'uso interno).

Un buffer di trama è una risorsa buffer specializzata a cui si accede come una trama. L'accesso alle trame (rispetto all'accesso al buffer) può offrire prestazioni migliori per i dati indicizzati in modo arbitrario. È possibile associare fino a 128 buffer di trama per ogni fase della pipeline.

Una risorsa buffer è progettata per ridurre al minimo l'overhead dell'impostazione delle costanti dello shader. Il framework degli effetti (vedere l'interfaccia ID3D10Effect) gestirà l'aggiornamento di buffer costanti e trame oppure è possibile usare l'API Direct3D per aggiornare i buffer (vedere Copia e accesso ai dati delle risorse (Direct3D 10) per informazioni. Un'applicazione può anche copiare dati da un altro buffer ,ad esempio una destinazione di rendering o una destinazione di output del flusso, in un buffer costante.

Per altre info sull'uso di buffer costanti in un'applicazione D3D10, vedi Tipi di risorse (Direct3D 10) e Creazione di risorse buffer (Direct3D 10).

Per altre informazioni sull'uso di buffer costanti in un'applicazione D3D11, vedere Introduzione ai buffer in Direct3D 11 e Procedura: Creare un buffer costante.

Un buffer costante non richiede l'associazione di una vista alla pipeline. Un buffer di trama, tuttavia, richiede una visualizzazione e deve essere associato a uno slot di trama (o deve essere associato a SetTextureBuffer quando si usa un effetto).

Esistono due modi per comprimere i dati delle costanti: usando le parole chiave register (DirectX HLSL) e packoffset (DirectX HLSL).

Differenze tra Direct3D 9 e Direct3D 10 e 11:

  • A differenza dell'allocazione automatica delle costanti in Direct3D 9, che non ha eseguito la compressione e ha invece assegnato ogni variabile a un set di registri float4, le variabili costanti HLSL seguono le regole di compressione in Direct3D 10 e 11.

Organizzazione di buffer costanti

I buffer costanti riducono la larghezza di banda necessaria per aggiornare le costanti shader consentendo di raggruppare le costanti shader e di eseguirne il commit contemporaneamente anziché effettuare singole chiamate per eseguire il commit di ogni costante separatamente.

Il modo migliore per usare in modo efficiente i buffer costanti consiste nell'organizzare le variabili shader in buffer costanti in base alla frequenza di aggiornamento. Ciò consente a un'applicazione di ridurre al minimo la larghezza di banda necessaria per aggiornare le costanti dello shader. Ad esempio, uno shader potrebbe dichiarare due buffer costanti e organizzare i dati in ognuno in base alla frequenza di aggiornamento: i dati che devono essere aggiornati per ogni oggetto (ad esempio una matrice globale) vengono raggruppati in un buffer costante che può essere aggiornato per ogni oggetto. Questo è separato dai dati che caratterizzano una scena ed è quindi probabile che venga aggiornato molto meno spesso (quando la scena cambia).

cbuffer myObject
{       
    float4x4 matWorld;
    float3   vObjectPosition;
    int      arrayIndex;
}
 
cbuffer myScene
{
    float3   vSunPosition;
    float4x4 matView;
}
        

Buffer costanti predefiniti

Sono disponibili due buffer costanti predefiniti, $Global e $Param. Le variabili inserite nell'ambito globale vengono aggiunte in modo implicito alla $Global cbuffer, usando lo stesso metodo di compressione usato per i cbuffers. I parametri uniformi nell'elenco di parametri di una funzione vengono visualizzati nel buffer costante $Param quando uno shader viene compilato all'esterno del framework degli effetti. Quando viene compilato all'interno del framework degli effetti, tutte le uniformi devono risolversi in variabili definite nell'ambito globale.

Esempi

Di seguito è riportato un esempio di Skinning10 Sample che è un buffer di trama costituito da una matrice di matrici.

tbuffer tbAnimMatrices
{
    matrix g_mTexBoneWorld[MAX_BONE_MATRICES];
};
      

Questa dichiarazione di esempio assegna manualmente un buffer costante per iniziare in un particolare registro e include anche elementi specifici per sottocomponenti.

cbuffer MyBuffer : register(b3)
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}
      

Modello shader 4