Condividi tramite


Modello shader 3 (riferimento HLSL)

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

La semantica usata negli output del vertex shader deve essere usata negli input del pixel shader. La semantica viene usata per eseguire il mapping degli output del vertex shader agli input del pixel shader, in modo analogo al modo in cui la dichiarazione del vertice viene mappata ai registri di input del vertex shader e ai modelli di shader precedenti. Vedere Match Semantics on vs 3.0 and ps 3.0 shader (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 ilD3DRS_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 di vertex shader 3_0 (vs_3_0) si espande sulle funzionalità di vs_2_0 con indicizzazione del registro più potente, un set di registri di output semplificati, la possibilità di campionare una trama in un vertex shader e la possibilità di controllare la frequenza con cui vengono inizializzati gli input shader.

Indicizzare qualsiasi registro

Tutti i registri( registro di input e registri di output) possono essere indicizzati usando registro contatori cicli (è possibile indicizzare solo registri costanti nelle versioni precedenti).

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

È consentito indicizzare solo un intervallo continuo di registri; ovvero non è possibile indicizzare tra registri che non sono stati dichiarati. Anche se questa restrizione può risultare scomoda, consente l'ottimizzazione dell'hardware. Il tentativo di indicizzare tra registri non contigui produrrà risultati non definiti. La convalida dello 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 posizione, 2 per colore, 8 per trama e 1 per la dimensione nebbia o punto. Questi registri interpolano tutti i dati che contengono per il pixel shader. Le dichiarazioni dei registri di output sono obbligatorie e la semantica viene assegnata a ogni registro.

I registri possono essere suddivisi nel modo seguente:

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

Per un elenco dei registri, vedere Registers - vs_3_0.

Esempio di trama in un vertex shader

Vertex shader 3_0 supporta la ricerca delle trame nel vertex shader usando texldl - vs.

Funzionalità del modello pixel shader 3

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

I registri costanti dello shader possono essere impostati usando:

Semantica di corrispondenza in vs_3_0 e shader di ps_3_0

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 dello shader che corrisponde a una semantica usata in un output dello shader.

Ad esempio, questo pixel shader include 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 denominare v0.x e v0.yz con semantica diversa (multipla) a causa dell'uso della maschera di scrittura.

Dato il pixel shader, non è possibile associarlo al vs_3_0 shader seguente:

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

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

Riscrivere il vertex shader in questo modo per evitare la collisione semantica:

vs_3_0 
... 
dcl_texcoord2 o3 
dcl_texcoord3 o9 
...

Analogamente, un nome semantico dichiarato in registri di input diversi nel pixel shader (v0 e v1 nel pixel shader) non può essere usato 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 entrambi i registri di input del 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 dello 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 dei triangoli, gli attributi con D3DDECLUSAGE_COLOR vengono interpolati come ombreggiati flat. Se tutti i componenti di un registro vengono dichiarati con una semantica dei colori, ma altri componenti dello stesso registro hanno una semantica diversa, l'interpolazione di ombreggiatura piatta (lineare o flat) non sarà definita nei componenti di tale registro senza una semantica di colore.

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

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

Per supportare queste modifiche sono stati aggiunti i valori seguenti:

// 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 avviene a precisione e intervalli diversi (16 bit, 24 bit e 32 bit) in parti diverse della pipeline. Un valore maggiore dell'intervallo dinamico della pipeline che entra in tale 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 un comportamento prevedibile, è necessario bloccare tale valore al massimo dell'intervallo dinamico.

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

  • Quando si verifica un mova - vs istruzione.
  • Durante l'indirizzamento delle trame.
  • 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 Pieno fp32 o superiore
x Precisione parziale fp16=s10e5
x x Pieno fp24=s16e7 o versione successiva
x x Precisione parziale fp16=s10e5

 

ps_3_0 supporta una maggiore precisione rispetto a ps_2_0. Per impostazione predefinita, tutte le operazioni vengono eseguite a livello di precisione completa.

Precisione parziale (vedere Pixel Shader Register Modifiers) viene richiesta aggiungendo il modificatore _pp al codice shader (purché l'implementazione sottostante la supporti). Le implementazioni sono sempre libere di ignorare il modificatore ed eseguire le operazioni interessate con precisione completa.

Il modificatore _pp può verificarsi in due contesti:

  • In una dichiarazione di coordinata della trama per passare coordinate di trama con precisione parziale al pixel shader. Ciò può essere usato quando le coordinate della trama inoltrano i dati di colore al pixel shader, che possono essere più veloci con precisione parziale rispetto a quella con precisione completa in alcune implementazioni.
  • In qualsiasi istruzione per richiedere l'uso della precisione parziale, incluse le istruzioni di caricamento delle trame. 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 con precisione completa (indipendentemente dalla precisione degli operandi di input).

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

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

In tutti questi casi lo sviluppatore può scegliere di specificare la precisione parziale per elaborare i dati, sapendo che non viene persa alcuna precisione dei dati di input. In alcuni casi, uno 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 una precisione più che parziale.

Vertex software e pixel shader

Le implementazioni software (runtime e riferimento per vertex shader e riferimenti per pixel shader) di shader versione 2_0 e versioni successive hanno alcune convalide rilassate. Ciò è utile per scopi di debug e creazione di prototipi. L'applicazione indica al runtime o all'assembler che richiede una parte della convalida rilassata usando il flag _sw nell'assembler (ad esempio, vs_2_sw). Uno shader software non funzionerà con l'hardware.

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

Modello shader Risorsa Limite
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Conteggi istruzioni Illimitato
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 Illimitato
vs_2_sw istruzioni ed etichette per il controllo del flusso Illimitato
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw Avvio/passaggio/conteggi del ciclo Le dimensioni dei passaggi di avvio e iterazione per le istruzioni del repository e del ciclo sono numeri 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 delle porte I limiti delle porte 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 14(16-2) registri di input per ps_3_sw.

 

shader Model 3 (DirectX HLSL)