Specifica delle firme radice in HLSL
La specifica delle firme radice nel modello HLSL Shader 5.1 è un'alternativa a specificarli nel codice C++.
- Un esempio di firma radice HLSL
- RootFlags
- Costanti radice
- Visibilità
- CBV a livello radice
- SRV a livello radice
- UAV a livello radice
- Tabella descrittore
- Sampler statico
- Compilazione di una firma radice HLSL
- Modifica delle firme radice con il compilatore FXC
- Note
- Argomenti correlati
Un esempio di firma radice HLSL
Una firma radice può essere specificata in HLSL come stringa. La stringa contiene una raccolta di clausole delimitate da virgole che descrivono i componenti costitutivi della firma radice. La firma radice deve essere identica tra shader per qualsiasi oggetto stato della pipeline (PSO). Esempio:
Firma radice versione 1.0
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1), " \
"SRV(t0), " \
"UAV(u0, visibility = SHADER_VISIBILITY_GEOMETRY), " \
"DescriptorTable( CBV(b0), " \
"UAV(u1, numDescriptors = 2), " \
"SRV(t1, numDescriptors = unbounded)), " \
"DescriptorTable(Sampler(s0, numDescriptors = 2)), " \
"RootConstants(num32BitConstants=1, b9), " \
"DescriptorTable( UAV(u3), " \
"UAV(u4), " \
"UAV(u5, offset=1)), " \
"StaticSampler(s2)," \
"StaticSampler(s3, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
Questa definizione darà la firma radice seguente, notando:
- Uso dei parametri predefiniti.
- b0 e (b0, space=1) non sono in conflitto
- u0 è visibile solo al geometry shader
- u4 e u5 vengono aliasati allo stesso descrittore in un heap
Firma radice versione 1.1
La versione radice della firma 1.1 abilita le ottimizzazioni dei driver nei descrittori e nei dati della firma radice.
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1, flags = DATA_STATIC), " \
"SRV(t0), " \
"UAV(u0), " \
"DescriptorTable( CBV(b1), " \
"SRV(t1, numDescriptors = 8, " \
" flags = DESCRIPTORS_VOLATILE), " \
"UAV(u1, numDescriptors = unbounded, " \
" flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
"RootConstants(num32BitConstants=3, b10), " \
"StaticSampler(s1)," \
"StaticSampler(s2, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
Il linguaggio di firma radice HLSL corrisponde strettamente alle API della firma radice C++ e ha una potenza espressiva equivalente. La firma radice viene specificata come sequenza di clausole, separate da virgole. L'ordine delle clausole è importante, poiché l'ordine di analisi determina la posizione dello slot nella firma radice. Ogni clausola accetta uno o più parametri denominati. L'ordine dei parametri non è tuttavia importante.
RootFlags
La clausola RootFlags facoltativa accetta 0 (il valore predefinito per indicare nessun flag) o uno o più dei valori dei flag radice predefiniti, connessi tramite l'operatore OR '|'. I valori del flag radice consentiti sono definiti da D3D12_ROOT_SIGNATURE_FLAGS.
Ad esempio:
RootFlags(0) // default value – no flags
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS)
Costanti radice
La clausola RootConstants specifica le costanti radice nella firma radice. Due parametri obbligatori sono: num32BitConstants e bReg (il registro corrispondente a BaseShaderRegister nelle API C++) del cbuffer. Lo spazio (RegisterSpace nelle API C++) e la visibilità (shaderVisibility in C++) sono facoltativi e i valori predefiniti sono:
RootConstants(num32BitConstants=N, bReg [, space=0,
visibility=SHADER_VISIBILITY_ALL ])
Ad esempio:
RootConstants(num32BitConstants=3, b3)
Visibilità
La visibilità è un parametro facoltativo che può avere uno dei valori di D3D12_SHADER_VISIBILITY.
SHADER_VISIBILITY_ALL trasmette gli argomenti radice a tutti gli shader. In alcuni hardware questo non ha costi, ma in altri hardware è previsto un costo per fork dei dati in tutte le fasi dello shader. L'impostazione di una delle opzioni, ad esempio SHADER_VISIBILITY_VERTEX, limita l'argomento radice a una singola fase dello shader.
L'impostazione degli argomenti radice su fasi di single shader consente di usare lo stesso nome di associazione in fasi diverse. Ad esempio, un'associazione SRV di t0,SHADER_VISIBILITY_VERTEX
e un'associazione SRV di t0,SHADER_VISIBILITY_PIXEL
sarebbe valida. Tuttavia, se l'impostazione di visibilità era t0,SHADER_VISIBILITY_ALL
per una delle associazioni, la firma radice non sarebbe valida.
CBV a livello radice
La CBV
clausola (visualizzazione buffer costante) specifica una voce b-register Reg del buffer a livello radice. Si noti che si tratta di una voce scalare; non è possibile specificare un intervallo per il livello radice.
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
SRV a livello radice
La SRV
clausola (visualizzazione risorse shader) specifica una voce SRV t-register Reg a livello radice. Si noti che si tratta di una voce scalare; non è possibile specificare un intervallo per il livello radice.
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
UAV a livello radice
La UAV
clausola (visualizzazione accesso non ordinata) specifica una voce UAV a livello radice di registrazione u-register Reg. Si noti che si tratta di una voce scalare; non è possibile specificare un intervallo per il livello radice.
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_VOLATILE ])
Ad esempio:
UAV(u3)
Tabella descrittore
La DescriptorTable
clausola è un elenco di clausole di tabella delimitate da virgole, nonché un parametro di visibilità facoltativo. Le clausole DescriptorTable includono CBV, SRV, UAV e Sampler. Si noti che i relativi parametri differiscono da quelli delle clausole a livello radice.
DescriptorTable( DTClause1, [ DTClause2, … DTClauseN,
visibility=SHADER_VISIBILITY_ALL ] )
La tabella CBV
descrittore ha la sintassi seguente:
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND // Version 1.1
, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
Ad esempio:
DescriptorTable(CBV(b0),SRV(t3, numDescriptors=unbounded))
Il parametro obbligatorio bReg specifica l'inizio reg dell'intervallo cbuffer. Il parametro numDescriptors specifica il numero di descrittori nell'intervallo cbuffer contiguo; il valore predefinito 1. La voce dichiara un intervallo [Reg, Reg + numDescriptors - 1]
cbuffer, quando numDescriptors è un numero. Se numDescriptors è uguale a "non collegato", l'intervallo è [Reg, UINT_MAX]
, il che significa che l'app deve assicurarsi che non faccia riferimento a un'area non vincolata. Il campo offset rappresenta il parametro OffsetInDescriptorsFromTableStart nelle API C++, ovvero l'offset (in descrittori) dall'inizio della tabella. Se l'offset è impostato su DESCRIPTOR_RANGE_OFFSET_APPEND (impostazione predefinita), significa che l'intervallo è direttamente dopo l'intervallo precedente. Tuttavia, l'immissione di offset specifici consente agli intervalli di sovrapporsi tra loro, consentendo di registrare l'aliasing.
La tabella SRV
descrittore ha la sintassi seguente:
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
Questa operazione è simile alla voce della tabella CBV
descrittore, ad eccezione dell'intervallo specificato per le visualizzazioni delle risorse shader.
La tabella UAV
descrittore ha la sintassi seguente:
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_VOLATILE ])
Questa operazione è simile alla voce della tabella CBV
descrittore, ad eccezione dell'intervallo specificato per le visualizzazioni di accesso non ordinate.
La tabella Sampler
descrittore ha la sintassi seguente:
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=0 ])
Questa operazione è simile alla voce della tabella CBV
descrittore, ad eccezione dell'intervallo specificato per i sampler shader. Si noti che gli esempi non possono essere combinati con altri tipi di descrittori nella stessa tabella descrittore (poiché si trovano in un heap descrittore separato).
Sampler statico
L'esempio statico rappresenta la struttura D3D12_STATIC_SAMPLER_DESC . Il parametro obbligatorio per StaticSampler è un registro scalare, sampler s-register Reg. Altri parametri sono facoltativi con i valori predefiniti illustrati di seguito. La maggior parte dei campi accetta un set di enumerazioni predefinite.
StaticSampler( sReg,
[ filter = FILTER_ANISOTROPIC,
addressU = TEXTURE_ADDRESS_WRAP,
addressV = TEXTURE_ADDRESS_WRAP,
addressW = TEXTURE_ADDRESS_WRAP,
mipLODBias = 0.f,
maxAnisotropy = 16,
comparisonFunc = COMPARISON_LESS_EQUAL,
borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE,
minLOD = 0.f,
maxLOD = 3.402823466e+38f,
space = 0,
visibility = SHADER_VISIBILITY_ALL ])
Ad esempio:
StaticSampler(s4, filter=FILTER_MIN_MAG_MIP_LINEAR)
Le opzioni dei parametri sono molto simili alle chiamate API C++, ad eccezione del borderColor, che è limitato a un'enumerazione in HLSL.
Il campo filtro può essere uno dei D3D12_FILTER.
I campi degli indirizzi possono essere uno dei D3D12_TEXTURE_ADDRESS_MODE.
La funzione di confronto può essere una delle D3D12_COMPARISON_FUNC.
Il campo colore bordo può essere uno dei D3D12_STATIC_BORDER_COLOR.
La visibilità può essere una delle D3D12_SHADER_VISIBILITY.
Compilazione di una firma radice HLSL
Esistono due meccanismi per compilare una firma radice HLSL. Prima di tutto, è possibile collegare una stringa di firma radice a un particolare shader tramite l'attributo RootSignature (nell'esempio seguente, usando il punto di ingresso MyRS1 ):
[RootSignature(MyRS1)]
float4 main(float4 coord : COORD) : SV_Target
{
…
}
Il compilatore creerà e verificherà il BLOB della firma radice per lo shader e lo incorporare insieme al codice di byte shader nel BLOB shader. Il compilatore supporta la sintassi della firma radice per il modello shader 5.0 e versioni successive. Se una firma radice è incorporata in uno shader modello di shader 5.0 e tale shader viene inviato al runtime D3D11, anziché D3D12, la parte della firma radice verrà ignorata automaticamente da D3D11.
L'altro meccanismo consiste nel creare un BLOB di firma radice autonomo, forse per riutilizzarlo con un ampio set di shader, risparmiando spazio. Effect-Compiler Tool (FXC) supporta sia modelli rootsig_1_0che rootsig_1_1 shader. Il nome della stringa di definizione viene specificato tramite l'argomento /E consueto. Ad esempio:
fxc.exe /T rootsig_1_1 MyRS1.hlsl /E MyRS1 /Fo MyRS1.fxo
Si noti che la stringa di firma radice definita può anche essere passata alla riga di comando, ad esempio /D MyRS1="...".
Modifica delle firme radice con il compilatore FXC
Il compilatore FXC crea il codice byte dello shader dai file di origine HLSL. Per questo compilatore sono disponibili molti parametri facoltativi, fare riferimento allo strumento Effect-Compiler.
Per la gestione delle firme radice create da HLSL, la tabella seguente fornisce alcuni esempi dell'uso di FXC.
A linee | Riga di comando | Descrizione |
---|---|---|
1 | fxc /T ps_5_1 shaderWithRootSig.hlsl /Fo rs1.fxo |
Compila uno shader per la destinazione pixel shader 5.1, l'origine dello shader si trova nel file shaderWithRootSig.hlsl, che include una firma radice. Lo shader e la firma radice vengono compilati come BLOB separati nel file binario rs1.fxo. |
2 | fxc /dumpbin rs1.fxo /extractrootsignature /Fo rs1.rs.fxo |
Estrae la firma radice dal file creato dalla riga 1, quindi il file rs1.rs.fxo contiene solo una firma radice. |
3 | fxc /dumpbin rs1.fxo /Qstrip_rootsignature /Fo rs1.stripped.fxo |
Rimuove la firma radice dal file creato dalla riga 1, quindi il file rs1.stripped.fxo contiene uno shader senza firma radice. |
4 | fxc /dumpbin rs1.stripped.fxo /setrootsignature rs1.rs.fxo /Fo rs1.new.fxo |
Combina uno shader e una firma radice che si trovano in file separati in un file binario contenente entrambi i BLOB. In questo esempio rs1.new.fx0 sarebbe identico a rs1.fx0 nella riga 1. |
5 | fxc /T rootsig_1_0 rootSigAndMaybeShaderInHereToo.hlsl /E RS1 /Fo rs2.fxo |
Crea un file binario di firma radice autonomo da un'origine che può contenere più di una sola firma radice. Si noti la destinazione rootsig_1_0 e che RS1 è il nome della stringa di macro della firma radice (#define) nel file HLSL. |
La funzionalità disponibile tramite FXC è disponibile anche a livello di codice usando la funzione D3DCompile . Questa chiamata compila uno shader con una firma radice o una firma radice autonoma (impostando la destinazione rootsig_1_0). D3DGetBlobPart e D3DSetBlobPart possono estrarre e collegare firme radice a un BLOB esistente. D3D_BLOB_ROOT_SIGNATURE viene usato per specificare il tipo di parte del BLOB della firma radice. D3DStripShader rimuove la firma radice (usando il flag D3DCOMPILER_STRIP_ROOT_SIGNATURE) dal BLOB.
Note
Nota
Mentre la compilazione offline degli shader è fortemente consigliata, se gli shader devono essere compilati in fase di esecuzione, fare riferimento alle osservazioni per D3DCompile2.
Nota
Non è necessario modificare gli asset HLSL esistenti per gestire le firme radice da usare con essi.
Argomenti correlati
-
Valore di riferimento dello stencil specificato dello shader
-
Caricamenti della visualizzazione accesso non ordinato tipizzato