Condividi tramite


Sintassi delle variabili

Usare le regole di sintassi seguenti per dichiarare variabili HLSL.

[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset] [: Register]; [Annotazioni] [= Initial_Value]

Parametri

Storage_Class

Modificatori facoltativi della classe di archiviazione che forniscono agli hint del compilatore sull'ambito e sulla durata delle variabili; I modificatori possono essere specificati in qualsiasi ordine.

Valore Descrizione
extern Contrassegnare una variabile globale come input esterno per lo shader; si tratta del contrassegno predefinito per tutte le variabili globali. Impossibile combinare con statico.
nointerpolation Non interpolare gli output di un vertex shader prima di passarli a un pixel shader.
Preciso La parola chiave precisa quando applicata a una variabile limita tutti i calcoli usati per produrre il valore assegnato a tale variabile nei modi seguenti:
  • Le operazioni separate vengono mantenute separate. Ad esempio, dove un mul e un'operazione di aggiunta potrebbero essere stati fusi in un'operazione pazza, forza precisamente le operazioni a rimanere separate. È invece necessario usare in modo esplicito la funzione intrinseca mad.
  • L'ordine delle operazioni viene mantenuto. Se l'ordine delle istruzioni potrebbe essere stato riscritto per migliorare le prestazioni, garantisce che il compilatore mantenga l'ordine come scritto.
  • Le operazioni IEEE non sicure sono limitate. Se il compilatore potrebbe aver usato operazioni matematiche veloci che non riguardano i valori NaN (non un numero) e INF (infinito), forza i requisiti IEEE precisi relativi ai valori NaN e INF da rispettare. Senza precisione, queste ottimizzazioni e operazioni matematiche non sono sicure da IEEE.
  • La qualifica di una variabile precisa non effettua operazioni che usano la variabile precisa. Poiché si propagano in modo preciso solo le operazioni che contribuiscono ai valori assegnati alla variabile precisa, rendendo corretti i calcoli desiderati è difficile, quindi è consigliabile contrassegnare l'output dello shader in modo preciso in cui vengono dichiarati, sia che si tratti di un campo di struttura, sia su un parametro di output o su un parametro di output o il tipo restituito della funzione di immissione. La possibilità di controllare le ottimizzazioni in questo modo mantiene l'invarianza per la variabile di output modificata disabilitando le ottimizzazioni che potrebbero influire sui risultati finali a causa delle differenze di precisione accumulate. È utile quando si desidera che gli shader per la tessellazione mantengano i seam di patch stretti all'acqua o corrispondano ai valori di profondità su più passaggi. Codice di esempio:
    HLSLmatrix g_mWorldViewProjection;
    void main(in float3 InPos : Position, out precise float4 OutPos : SV_Position)
    {
    l'operazione è precisa perché contribuisce al parametro preciso OutPos
    OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
    }
condiviso Contrassegnare una variabile per la condivisione tra gli effetti; questo è un hint per il compilatore.
groupshared Contrassegnare una variabile per la memoria condivisa di thread-group per gli shader di calcolo. In D3D10 la dimensione totale massima di tutte le variabili con la classe di archiviazione groupshared è di 16 kb, in D3D11 la dimensione massima è di 32 kb. Vedere esempi.
static Contrassegnare una variabile locale in modo che venga inizializzata una sola volta e venga mantenuta tra le chiamate di funzione. Se la dichiarazione non include un inizializzatore, il valore è impostato su zero. Una variabile globale contrassegnata come statica non è visibile a un'applicazione.
uniform Contrassegnare una variabile i cui dati sono costanti durante l'esecuzione di uno shader (ad esempio un colore del materiale in un vertex shader); le variabili globali vengono considerate uniformi per impostazione predefinita.
volatile Contrassegnare una variabile che cambia spesso; questo è un hint per il compilatore. Questo modificatore della classe di archiviazione si applica solo a una variabile locale.
Nota: Il compilatore HLSL ignora attualmente questo modificatore della classe di archiviazione.

Type_Modifier

Modificatore di tipo variabile facoltativo.

Valore Descrizione
const Contrassegnare una variabile che non può essere modificata da uno shader, pertanto, deve essere inizializzata nella dichiarazione di variabile. Le variabili globali vengono considerate const per impostazione predefinita (eliminare questo comportamento fornendo il flag /Gec al compilatore).
row_major Contrassegnare una variabile che archivia quattro componenti in una singola riga in modo che possano essere archiviati in un singolo registro costante.
column_major Contrassegnare una variabile che archivia 4 componenti in una singola colonna per ottimizzare la matematica della matrice.

Nota

Se non si specifica un valore del modificatore di tipo, il compilatore usa column_major come valore predefinito.

Digitare

Qualsiasi tipo HLSL elencato nei tipi di dati (DirectX HLSL).

Name[Index]

Stringa ASCII che identifica in modo univoco una variabile shader. Per definire una matrice facoltativa, usare l'indice per le dimensioni della matrice, ovvero un intero positivo = 1.

Semantica

Informazioni facoltative sull'utilizzo dei parametri, usate dal compilatore per collegare input e output shader. Esistono diverse semantiche predefinite per vertex e pixel shader. Il compilatore ignora la semantica a meno che non vengano dichiarati in una variabile globale o un parametro passato in uno shader.

Packoffset

Parola chiave facoltativa per la compressione manuale delle costanti shader. Vedere packoffset (DirectX HLSL).

Registro

Parola chiave facoltativa per l'assegnazione manuale di una variabile shader a un determinato registro. Vedere registrare (DirectX HLSL).

Annotazioni

Metadati facoltativi, sotto forma di stringa, collegati a una variabile globale. Un'annotazione viene usata dal framework degli effetti e ignorata da HLSL; per visualizzare una sintassi più dettagliata, vedere sintassi dell'annotazione.

Initial_Value

Valori iniziali facoltativi; il numero di valori deve corrispondere al numero di componenti in Tipo. Ogni variabile globale contrassegnata da extern deve essere inizializzata con un valore letterale; ogni variabile contrassegnata statica deve essere inizializzata con una costante.

Le variabili globali non contrassegnate come statiche o extern non vengono compilate nello shader. Il compilatore non imposta automaticamente i valori predefiniti per le variabili globali e non può usarli nelle ottimizzazioni. Per inizializzare questo tipo di variabile globale, usare reflection per ottenere il valore e quindi copiare il valore in un buffer costante. Ad esempio, è possibile usare il metodo ID3D11ShaderReflection::GetVariableByName per ottenere la variabile, usare il metodo ID3D11ShaderReflectionVariable::GetDesc per ottenere la descrizione della variabile shader e ottenere il valore iniziale dal membro DefaultValue della struttura D3D11_SHADER_VARIABLE_DESC . Per copiare il valore nel buffer costante, è necessario assicurarsi che il buffer sia stato creato con l'accesso in scrittura della CPU (D3D11_CPU_ACCESS_WRITE). Per altre informazioni su come creare un buffer costante, vedere Procedura: Creare un buffer costante.

È anche possibile usare il framework degli effetti per elaborare automaticamente la riflessione e impostare il valore iniziale. Ad esempio, è possibile usare il metodo ID3DX11EffectPass::Apply .

Esempio

Ecco alcuni esempi di dichiarazioni di variabili shader.

float fVar;
float4 color;
float fVar = 3.1f;

int iVar[3];

int iVar[3] = {1,2,3};

uniform float4 position : SV_POSITION; 
const float4 lightDirection = {0,0,1};
      

Gruppo condiviso

HLSL consente ai thread di un compute shader di scambiare valori tramite memoria condivisa. HLSL fornisce primitive di barriera come GroupMemoryBarrierWithGroupSync e così via per garantire l'ordinamento corretto delle letture e delle scritture nella memoria condivisa nello shader e per evitare race dei dati.

Nota

L'hardware esegue thread in gruppi (distorsioni o fronti d'onda) e la sincronizzazione delle barriere può talvolta essere omessa per aumentare le prestazioni quando solo la sincronizzazione dei thread appartenenti allo stesso gruppo è corretta. Ma sconsigliamo vivamente questa omissione per questi motivi:

  • Questa omissione comporta codice non portabile, che potrebbe non funzionare su un hardware e non funziona su rasterizzatori software che in genere eseguono thread in gruppi più piccoli.
  • I miglioramenti delle prestazioni che è possibile ottenere con questa omissione saranno minori rispetto all'uso della barriera all-thread.

In Direct3D 10 non è presente alcuna sincronizzazione dei thread durante la scrittura in gruppi condivisi, pertanto ogni thread è limitato a una singola posizione in una matrice per la scrittura. Usare il valore di sistema SV_GroupIndex per eseguire l'indicizzazione in questa matrice durante la scrittura per garantire che nessun thread possa entrare in conflitto. In termini di lettura, tutti i thread hanno accesso all'intera matrice per la lettura.

struct GSData
{
    float4 Color;
    float Factor;
}

groupshared GSData data[5*5*1];

[numthreads(5,5,1)]
void main( uint index : SV_GroupIndex )
{
    data[index].Color = (float4)0;
    data[index].Factor = 2.0f;
    GroupMemoryBarrierWithGroupSync();
    ...
}

Compressione

Comprimere sottocomponenti di vettori e scalari le cui dimensioni sono sufficienti per impedire l'attraversamento dei limiti del registro. Ad esempio, questi sono tutti validi:

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

Impossibile combinare tipi di imballaggio.

Analogamente alla parola chiave register, un packoffset può essere specifico di destinazione. La compressione del sottocomponente è disponibile solo con la parola chiave packoffset, non con la parola chiave register. All'interno di una dichiarazione cbuffer, la parola chiave register viene ignorata per le destinazioni Direct3D 10 perché si presuppone che sia per la compatibilità multipiattaforma.

Gli elementi compressi possono sovrapporsi e il compilatore non restituisce alcun errore o avviso. In questo esempio Element2 e Element3 si sovrappongono a Element1.x e Element1.y.

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

Un esempio che usa packoffset è : Esempio HLSLWithoutFX10.

Variabili (DirectX HLSL)