Modello shader 3 (riferimento HLSL)

I vertex shader e pixel shader sono semplificati notevolmente dalle versioni precedenti dello shader. Se si implementano shader nell'hardware, non è possibile usare vs_3_0 o ps_3_0 con altre versioni di shader e non è possibile usare alcun tipo shader con la pipeline di funzione fissa. Queste modifiche consentono di semplificare i driver e il runtime. L'unica eccezione è che è possibile usare vs_3_0 shader solo software con qualsiasi versione del pixel shader. Inoltre, se si usa un vs_3_0 shader solo software con una versione precedente di pixel shader, il vertex shader può usare solo semantiche di output compatibili con codici FVF (Flexible Vertex Format).

La semantica usata negli output del vertex shader deve essere usata negli input pixel shader. La semantica viene usata per eseguire il mapping degli output del vertex shader agli input pixel shader, analogamente al modo in cui la dichiarazione del vertice viene mappata ai registri di input del vertex shader e ai modelli di shader precedenti. Vedere Semantica di corrispondenza in vs 3.0 e ps 3.0 Shader.

Altri stati di rendering della modalità di wrapping sono stati aggiunti per coprire la possibilità di coordinate di trama aggiuntive in questo nuovo schema. Gli attributi con D3DDECLUSAGE_TEXCOORD e indice di utilizzo da 0 a 15 vengono interpolati in modalità di wrapping quando viene impostato il D3DRS_WRAP corrispondente* .

Funzionalità del modello Vertex Shader 3

I tipi di registro di output del vertex shader sono stati compressi in dodici registri (vedere Registri di output). Ogni registro usato deve essere dichiarato usando l'istruzione dcl e una semantica (ad esempio, dcl_color0 o0.xyzw).

Il modello vertex shader 3_0 (vs_3_0) si espande sulle funzionalità di vs_2_0 con indici di registrazione più potenti, un set di registri di output semplificati, la possibilità di campione di una trama in un vertex shader e la possibilità di controllare la frequenza in cui vengono inizializzati gli input shader.

Indicizzare qualsiasi registro

Tutti i registri( Registri di input e Registri di output) possono essere indicizzati tramite Registro contatore cicli (solo i registri costanti possono essere indicizzati nelle versioni precedenti).

È necessario dichiarare i registri di input e output prima di indicizzarli. Tuttavia, è possibile non indicizzare alcun registro di output dichiarato con una semantica di posizione o dimensione del punto. Infatti, se l'indicizzazione viene usata rispettivamente la semantica di posizione e psize deve essere dichiarata rispettivamente nei registri o0 e o1.

È consentito indicizzare solo un intervallo continuo di registri; ovvero, non è possibile indicizzare tra i registri che non sono stati dichiarati. Anche se questa restrizione può essere scomoda, consente l'ottimizzazione dell'hardware. Il tentativo di indicizzazione tra registri non contigui produrrà risultati non definiti. La convalida shader non applica questa restrizione.

Semplificare i registri di output

Tutti i vari tipi di registri di output sono stati compressi in dodici registri di output: 1 per la posizione, 2 per il colore, 8 per la trama e 1 per le dimensioni della nebbia o del punto. Questi registri interpoleranno tutti i dati che contengono per il pixel shader. Le dichiarazioni di registrazione di output sono necessarie e la semantica viene assegnata a ogni registro.

I registri possono essere suddivisi come segue:

  • Almeno un registro deve essere dichiarato come registro di posizione a quattro componenti. Si tratta dell'unico registro vertex shader richiesto.
  • I primi dieci registri utilizzati da uno shader possono usare fino a quattro componenti (xyzw) massimo.
  • L'ultimo registro (o twelfth) può contenere solo un scalare (ad esempio le dimensioni del punto).

Per un elenco dei registri, vedere Registri - vs_3_0.

Esempio di trama in un vertex shader

Vertex shader 3_0 supporta la ricerca della trama nel vertex shader usando texldl - vs.

Funzionalità del modello Pixel Shader 3

I registri del pixel shader e delle trame sono stati compressi in dieci registri di input (vedere Tipi di registro di input). Il Registro viso è un registro scalare a virgola mobile. Solo il segno di questo registro è valido. Se il segno è negativo la primitiva è un viso indietro. Questo può essere usato all'interno di un pixel shader per ottenere un'illuminazione a due lati, ad esempio. Il registro posizione fa riferimento ai pixel correnti (x,y).

I registri costanti shader possono essere impostati usando:

Match Semantics on vs_3_0 and ps_3_0 Shader

Esistono alcune restrizioni sull'utilizzo semantico con vs_3_0 e ps_3_0. In generale, è necessario prestare attenzione quando si usa una semantica per un input shader che corrisponde a una semantica utilizzata in un output shader.

Ad esempio, questo pixel shader contiene più nomi in un unico registro:

ps_3_0 
dcl_texcoord0 v0.x 
dcl_texcoord1 v0.yz // Valid to pack multiple names into one register 
dcl_texcoord2_centroid v1.w
...

Ogni registro ha una semantica diversa. Si noti che è anche possibile assegnare un nome v0.x e v0.yz con semantiche diverse (multiple) a causa dell'uso della maschera di scrittura.

Dato lo shader pixel, il vs_3_0 shader seguente non può essere associato a esso:

vs_3_0 
... 
dcl_texcoord0 o5.x 
dcl_texcoord1 o6.yzw 
...

Questi due shader sono in conflitto con l'uso della semantica D3DDECLUSAGE_TEXCOORD0 E D3DDECLUSAGE_TEXCOORD1 .

Riscrivere il vertex shader come questo per evitare la collisione semantica:

vs_3_0 
... 
dcl_texcoord2 o3 
dcl_texcoord3 o9 
...

Analogamente, non è possibile usare un nome semantico dichiarato in registri di input diversi nel pixel shader (v0 e v1 nel pixel shader) in un singolo registro di output in questo vertex shader. Ad esempio, questo vertex shader non può essere associato al pixel shader perché D3DDECLUSAGE_TEXCOORD1 viene usato per i registri di input pixel shader (v0, v1) e il registro di output del vertex shader o3.

vs_3_0 
... 
dcl_texcoord0 o3.x 
dcl_texcoord1 o3.yz 

dcl_texcoord2 o3.w // BAD! Would be valid if this were not o3 
dcl_texcoord3 o9 ... 

D'altra parte, questo vertex shader non può essere associato al pixel shader perché la maschera di output per un parametro con una determinata semantica non fornisce i dati richiesti dal pixel shader:

vs_3_0 
... 
dcl_texcoord0 o5.x 
dcl_texcoord1 o5.yzw 
dcl_texcoord2 o7.yz // BAD! Would be valid if w were included 
dcl_texcoord3 o9 
... 

Questo vertex shader non fornisce un output con uno dei nomi semantici richiesti dal pixel shader, quindi l'associazione shader non è valida:

vs_3_0 
... 
dcl_texcoord0 o5.x 
dcl_texcoord1 o5.yzw 
dcl_texcoord3 o9 
// The pixel shader wants texcoord2, with a w component, 
// but it isn't output by this vertex shader at all! 
... 

Modifiche alla modalità nebbia, profondità e ombreggiatura

Quando D3DRS_SHADEMODE è impostato per l'ombreggiatura piatta durante il ritaglio e la rasterizzazione del triangolo, gli attributi con D3DDECLUSAGE_COLOR vengono interpolati come ombreggiatura piatta. Se tutti i componenti di un registro vengono dichiarati con una semantica del colore, ma altri componenti dello stesso registro vengono dati semantici diversi, l'interpolazione di ombreggiatura flat (lineare e flat) non verrà definita nei componenti di tale registro senza una semantica del colore.

Se il rendering della nebbia è desiderato, vs_3_0 e ps_3_0 shader devono implementare la nebbia. Non vengono eseguiti calcoli di nebbia all'esterno degli shader. Non è presente alcun registro di nebbia in vs_3_0 e altre semantiche D3DDECLUSAGE_FOG (per il fattore di fusione nebbia calcolata per vertice) e D3DDECLUSAGE_DEPTH (per passare un valore di profondità al pixel shader per calcolare il fattore di fusione della nebbia) sono state aggiunte.

Lo stato della fase trama D3DTSS_TEXCOORDINDEX viene ignorato quando si usa pixel shader 3.0.

I valori seguenti sono stati aggiunti per gestire queste modifiche:

// Fog and Depth usages
D3DDECLUSAGE_FOG 
D3DDECLUSAGE_DEPTH 

// Additional wrap states for vs_3_0 attributes with D3DDECLUSAGE_TEXCOORD 
D3DRS_WRAP8 
D3DRS_WRAP9 
D3DRS_WRAP10 
D3DRS_WRAP11 
D3DRS_WRAP12 
D3DRS_WRAP13 
D3DRS_WRAP14 
D3DRS_WRAP15

Conversioni a virgola mobile e integer

La matematica a virgola mobile si verifica in diverse parti della pipeline (a 16 bit, a 24 bit e a 32 bit) in diverse parti della pipeline. Un valore maggiore dell'intervallo dinamico della pipeline che entra nella pipeline (ad esempio, una mappa trama float a 32 bit viene campionata in una pipeline float a 24 bit in ps_2_0) crea un risultato non definito. Per il comportamento prevedibile, è consigliabile bloccare tale valore al massimo dell'intervallo dinamico.

La conversione da un valore a virgola mobile a un numero intero si verifica in diverse posizioni, ad esempio:

  • Quando si verifica un mova - vs istruzioni.
  • Durante l'indirizzamento della trama.
  • Quando si scrive in una destinazione di rendering non a virgola mobile.

Specifica della precisione completa o parziale

Sia ps_3_0 che ps_2_x forniscono supporto per due livelli di precisione:

ps_3_0 ps_2_0 Precisione Valore
x Full fp32 o superiore
x Precisione parziale fp16=s10e5
x x Full fp24=s16e7 o versione successiva
x x Precisione parziale fp16=s10e5

 

ps_3_0 supporta maggiore precisione rispetto a ps_2_0. Per impostazione predefinita, tutte le operazioni si verificano a livello di precisione completa.

Precisione parziale (vedere Modificatori di registrazione Pixel Shader) viene richiesta aggiungendo il modificatore _pp al codice shader (a condizione che l'implementazione sottostante lo supporti). Le implementazioni sono sempre gratuite per ignorare il modificatore ed eseguire le operazioni interessate con precisione completa.

Il modificatore _pp può verificarsi in due contesti:

  • In una dichiarazione di coordinata trama per passare coordinate di trama di precisione parziale al pixel shader. Ciò può essere usato quando le coordinate della trama inoltrano i dati del colore al pixel shader, che possono essere più veloci con precisione parziale rispetto a con precisione completa in alcune implementazioni.
  • In qualsiasi istruzione per richiedere l'uso di precisione parziale, incluse le istruzioni di caricamento della trama. Ciò indica che l'implementazione può eseguire l'istruzione con precisione parziale e archiviare un risultato di precisione parziale. In assenza di un modificatore esplicito, l'istruzione deve essere eseguita a precisione completa (indipendentemente dalla precisione degli operandi di input).

Un'applicazione potrebbe scegliere deliberatamente di scambiare precisione per le prestazioni. Esistono diversi tipi di dati di input shader che sono candidati naturali per l'elaborazione di precisione parziale:

  • Gli iteratori di colore sono ben rappresentati dai valori di precisione parziale.
  • I valori di trama della maggior parte dei formati possono essere rappresentati con precisione parziale (i valori campionati da trame a 32 bit, formato a virgola mobile sono un'eccezione ovvia).
  • Le costanti possono essere rappresentate dalla rappresentazione di precisione parziale in base alle esigenze del shader.

In tutti questi casi lo sviluppatore può scegliere di specificare precisione parziale per elaborare i dati, sapendo che non viene persa alcuna precisione dei dati di input. In alcuni casi, un shader può richiedere che i passaggi interni di un calcolo vengano eseguiti con precisione completa anche quando i valori di input e output finale non hanno più precisione parziale.

Vertex software e Pixel Shader

Implementazioni software (runtime e riferimento per vertex shader e riferimenti per pixel shader) di shader versione 2_0 e versioni successive hanno alcune convalida rilassate. Ciò è utile per eseguire il debug e la prototipazione. L'applicazione indica al runtime/assembler che necessita di alcune delle convalida rilassate usando il flag di _sw nell'assembler ( ad esempio, vs_2_sw). Un software shader non funzionerà con l'hardware.

vs_2_sw è un relax per le estremità massime di vs_2_x; analogamente, ps_2_sw è un relax ai limiti massimi di ps_2_x. In particolare, le convalida seguenti sono rilassate:

Modello shader Risorsa Limite
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Conteggi delle istruzioni Nessuna limitazione
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Registri costanti float 8192
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Registri costanti integer 2048
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Registri costanti booleani 2048
ps_2_sw Profondità di lettura dipendente Nessuna limitazione
vs_2_sw istruzioni e etichette del controllo del flusso Nessuna limitazione
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Avvio ciclo/passaggio/conteggio L'iterazione iniziale e le dimensioni dei passaggi di iterazione per le istruzioni del repository e del ciclo sono interi con segno a 32 bit. Il conteggio può essere fino a MAX_INT/64.
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Limiti di porta I limiti di porta per tutti i file di registrazione sono rilassati.
vs_3_sw Numero di interpolatori 16 registri di output in vs_3_sw.
ps_3_sw Numero di interpolatori Registri di input 14(16-2) per ps_3_sw.

 

Modello shader 3 (DirectX HLSL)