Festlegen von Stammsignaturen in HLSL
Das Angeben von Stammsignaturen im HLSL-Shadermodell 5.1 ist eine Alternative zur Angabe in C++-Code.
- Beispiel für eine HLSL-Stammsignatur
- RootFlags
- Stammkonst constants
- Sichtbarkeit
- CBV auf Stammebene
- SRV auf Stammebene
- UAV auf Stammebene
- Deskriptortabelle
- Statischer Sampler
- Kompilieren einer HLSL-Stammsignatur
- Bearbeiten von Stammsignaturen mit dem FXC-Compiler
- Hinweise
- Zugehörige Themen
Beispiel für eine HLSL-Stammsignatur
Eine Stammsignatur kann in HLSL als Zeichenfolge angegeben werden. Die Zeichenfolge enthält eine Auflistung von durch Komma getrennten Klauseln, die die Komponenten der Stammsignatur beschreiben. Die Stammsignatur sollte über Shader hinweg für jedes Pipelinezustandsobjekt (Pipeline State Object, PSO) identisch sein. Beispiel:
Root Signature Version 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 )"
Diese Definition würde die folgende Stammsignatur enthalten, und es wird Folgendes notieren:
- Die Verwendung von Standardparametern.
- b0 und (b0, space=1) stehen nicht in Konflikt
- u0 ist nur für den Geometrie-Shader sichtbar.
- u4 und u5 werden demselben Deskriptor in einem Heap als Alias verwendet.

Stammsignatur, Version 1.1
Version 1.1 der Stammsignatur ermöglicht Treiberoptimierungen für Stammsignaturdeskriptoren und -daten.
#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 )"
Die HLSL-Stammsignatursprache entspricht eng den C++-Stammsignatur-APIs und verfügt über eine gleichwertige Ausdrucksstärke. Die Stammsignatur wird als Sequenz von Klauseln angegeben, die durch Komma getrennt sind. Die Reihenfolge der Klauseln ist wichtig, da die Reihenfolge der Analyse die Slotposition in der Stammsignatur bestimmt. Jede Klausel nimmt einen oder mehrere benannte Parameter an. Die Reihenfolge der Parameter ist jedoch nicht wichtig.
RootFlags
Die optionale RootFlags-Klausel verwendet entweder 0 (standardwert, um keine Flags anzugeben) oder einen oder mehrere vordefinierte Stammflagswerte, die über den OR ''-Operator | verbunden sind. Die zulässigen Stammflagwerte werden durch D3D12 _ ROOT _ SIGNATURE _ FLAGS definiert.
Beispiel:
RootFlags(0) // default value – no flags
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS)
Stammkonst constants
Die RootConstants-Klausel gibt Stammkonstanten in der Stammsignatur an. Zwei erforderliche Parameter sind: num32BitConstants und bReg (das Register, das BaseShaderRegister in C++-APIs entspricht) von cbuffer. Die Parameter space (RegisterSpace in C++-APIs) und visibility (ShaderVisibility in C++) sind optional, und die Standardwerte lauten:
RootConstants(num32BitConstants=N, bReg [, space=0,
visibility=SHADER_VISIBILITY_ALL ])
Beispiel:
RootConstants(num32BitConstants=3, b3)
Sichtbarkeit
Sichtbarkeit ist ein optionaler Parameter, der einen der Werte aus D3D12 _ SHADER _ VISIBILITY haben kann.
SHADER _ VISIBILITY _ ALL überträgt die Stammargumente an alle Shader. Auf einigen Hardware ist dies ohne Kosten, aber auf anderer Hardware gibt es Kosten, um die Daten in alle Shaderstufen zu forken. Durch festlegen einer der Optionen, z. B. SHADER VISIBILITY VERTEX, wird das Stammargument auf _ _ eine einzelne Shaderstufe beschränkt.
Das Festlegen von Stammargumenten auf einzelne Shaderstufen ermöglicht die Verwendung desselben Bindungsnamens in verschiedenen Phasen. Beispielsweise wäre eine SRV-Bindung von t0,SHADER_VISIBILITY_VERTEX und eine SRV-Bindung t0,SHADER_VISIBILITY_PIXEL von gültig. Wenn die Sichtbarkeitseinstellung jedoch t0,SHADER_VISIBILITY_ALL für eine der Bindungen verwendet wird, wäre die Stammsignatur ungültig.
CBV auf Stammebene
Die CBV -Klausel (konstante Pufferansicht) gibt einen konstanten Puffer auf Stammebene an, der den Reg-Eintrag b-register enthält. Beachten Sie, dass dies ein skalarer Eintrag ist. Es ist nicht möglich, einen Bereich für die Stammebene anzugeben.
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 auf Stammebene
Die SRV -Klausel (Shaderressourcenansicht) gibt einen SRV t-register Reg-Eintrag auf Stammebene an. Beachten Sie, dass dies ein skalarer Eintrag ist. Es ist nicht möglich, einen Bereich für die Stammebene anzugeben.
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 auf Stammebene
Die UAV -Klausel (ungeordnete Zugriffsansicht) gibt einen UAV-u-register Reg-Eintrag auf Stammebene an. Beachten Sie, dass dies ein skalarer Eintrag ist. Es ist nicht möglich, einen Bereich für die Stammebene anzugeben.
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 ])
Beispiel:
UAV(u3)
Deskriptortabelle
Die -Klausel selbst ist eine Liste von durch Komma getrennten Deskriptortabellenklauseln sowie ein DescriptorTable optionaler Sichtbarkeitsparameter. Die DescriptorTable-Klauseln umfassen CBV, SRV, UAV und Sampler. Beachten Sie, dass sich ihre Parameter von denen der Klauseln auf Stammebene unterscheiden.
DescriptorTable( DTClause1, [ DTClause2, … DTClauseN,
visibility=SHADER_VISIBILITY_ALL ] )
Die Deskriptortabelle CBV hat die folgende Syntax:
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 ])
Beispiel:
DescriptorTable(CBV(b0),SRV(t3, numDescriptors=unbounded))
Der obligatorische Parameter bReg gibt den Start-Reg des cbuffer-Bereichs an. Der numDescriptors-Parameter gibt die Anzahl der Deskriptoren im zusammenhängenden Cbufferbereich an. Der Standardwert ist 1. Der Eintrag deklariert einen cbuffer-Bereich, [Reg, Reg + numDescriptors - 1] wenn numDescriptors eine Zahl ist. Wenn numDescriptors gleich "unbounded" ist, ist der Bereich . Dies bedeutet, dass die App sicherstellen muss, dass sie nicht auf einen bereichslosen [Reg, UINT_MAX] Bereich verweisen muss. Das Offsetfeld stellt den OffsetInDescriptorsFromTableStart-Parameter in den C++-APIs dar, d. h. den Offset (in Deskriptoren) vom Tabellenanfang. Wenn der Offset auf DESCRIPTOR _ RANGE OFFSET APPEND (Standardeinstellung) festgelegt ist, bedeutet dies, dass der Bereich _ _ direkt nach dem vorherigen Bereich liegt. Durch die Eingabe bestimmter Offsets können sich Bereiche jedoch überlappen, sodass Registeraliasing möglich ist.
Die Deskriptortabelle SRV hat die folgende Syntax:
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 ])
Dies ähnelt dem Deskriptortabelleneintrag, mit der Ausnahme, dass der CBV angegebene Bereich für Shaderressourcenansichten gilt.
Die Deskriptortabelle UAV hat die folgende Syntax:
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 ])
Dies ähnelt dem Deskriptortabelleneintrag, mit der Ausnahme, dass der CBV angegebene Bereich für unsortierte Zugriffsansichten gilt.
Die Deskriptortabelle Sampler hat die folgende Syntax:
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 ])
Dies ähnelt dem Deskriptortabelleneintrag, mit der Ausnahme, dass der CBV angegebene Bereich für Shader-Sampler gilt. Beachten Sie, dass Sampler nicht mit anderen Typen von Deskriptoren in derselben Deskriptortabelle gemischt werden können (da sie sich in einem separaten Deskriptor-Heap befinden).
Statischer Sampler
Der statische Sampler stellt die D3D12 _ STATIC _ SAMPLER _ DESC-Struktur dar. Der obligatorische Parameter für StaticSampler ist ein s-register Reg-Sampler mit Skalar. Andere Parameter sind optional, mit den unten gezeigten Standardwerten. Die meisten Felder akzeptieren einen Satz vordefinierter Enumeren.
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 ])
Beispiel:
StaticSampler(s4, filter=FILTER_MIN_MAG_MIP_LINEAR)
Die Parameteroptionen sind den C++-API-Aufrufen sehr ähnlich, mit Ausnahme von borderColor, das auf eine Enum in HLSL beschränkt ist.
Das Filterfeld kann D3D12 _ FILTER sein.
Die Adressfelder können jeweils eines von D3D12 _ TEXTURE ADDRESS MODE _ _ sein.
Die Vergleichsfunktion kann eine von D3D12 _ COMPARISON _ FUNC sein.
Das Rahmenfarbfeld kann D3D12 _ STATIC BORDER COLOR _ _ sein.
Sichtbarkeit kann D3D12 _ SHADER _ VISIBILITY sein.
Kompilieren einer HLSL-Stammsignatur
Es gibt zwei Mechanismen zum Kompilieren einer HLSL-Stammsignatur. Erstens ist es möglich, eine Stammsignaturzeichenfolge über das RootSignature-Attribut an einen bestimmten Shader anfügen (im folgenden Beispiel mithilfe des MyRS1-Einstiegspunkts):
[RootSignature(MyRS1)]
float4 main(float4 coord : COORD) : SV_Target
{
…
}
Der Compiler erstellt und überprüft das Stammsignaturblob für den Shader und bettet es zusammen mit dem Shader-Bytecode in das Shaderblob ein. Der Compiler unterstützt die Stammsignatursyntax für Shadermodell 5.0 und höher. Wenn eine Stammsignatur in einen Shadermodell-5.0-Shader eingebettet ist und dieser Shader an die D3D11-Runtime gesendet wird( im Gegensatz zu D3D12), wird der Stammsignaturteil von D3D11 automatisch ignoriert.
Der andere Mechanismus besteht darin, ein eigenständiges Stammsignaturblob zu erstellen, z. B. um es mit einem großen Satz von Shadern wiederzuverwenden, wodurch Speicherplatz gespart wird. Das Effect-Compiler Tool (FXC) unterstützt sowohl rootsig _ 1 _ 0- als auch rootsig _ 1 1-Shadermodelle. _ Der Name der Define-Zeichenfolge wird über das übliche /E-Argument angegeben. Beispiel:
fxc.exe /T rootsig_1_1 MyRS1.hlsl /E MyRS1 /Fo MyRS1.fxo
Beachten Sie, dass die Definition der Stammsignaturzeichenfolge auch über die Befehlszeile übergeben werden kann, z.B. /D MyRS1="...".
Bearbeiten von Stammsignaturen mit dem FXC-Compiler
Der FXC-Compiler erstellt Shader-Bytecode aus HLSL-Quelldateien. Es gibt viele optionale Parameter für diesen Compiler. Weitere Informationen finden Sie unter Effect-Compiler Tool.
Die folgende Tabelle enthält einige Beispiele für die Verwendung von FXC für die Verwaltung von HLSL-Stammsignaturen.
| Linie | Befehlszeile | BESCHREIBUNG |
|---|---|---|
| 1 | fxc /T ps_5_1 shaderWithRootSig.hlsl /Fo rs1.fxo |
Kompiliert einen Shader für das Pixel-Shader 5.1-Ziel. Die Shaderquelle befindet sich in der Datei shaderWithRootSig.hlsl, die eine Stammsignatur enthält. Der Shader und die Stammsignatur werden als separate Blobs in der binären Datei rs1.fxo kompiliert. |
| 2 | fxc /dumpbin rs1.fxo /extractrootsignature /Fo rs1.rs.fxo |
Extrahiert die Stammsignatur aus der durch Zeile 1 erstellten Datei, sodass die Datei rs1.rs.fxo nur eine Stammsignatur enthält. |
| 3 | fxc /dumpbin rs1.fxo /Qstrip_rootsignature /Fo rs1.stripped.fxo |
Entfernt die Stammsignatur aus der durch Zeile 1 erstellten Datei, sodass die Datei rs1.stripped.fxo einen Shader ohne Stammsignatur enthält. |
| 4 | fxc /dumpbin rs1.stripped.fxo /setrootsignature rs1.rs.fxo /Fo rs1.new.fxo |
Kombiniert einen Shader und eine Stammsignatur, die sich in separaten Dateien befinden, in einer Binärdatei, die beide Blobs enthält. In diesem Beispiel wäre rs1.new.fx0 mit rs1.fx0 in Zeile 1 identisch. |
| 5 | fxc /T rootsig_1_0 rootSigAndMaybeShaderInHereToo.hlsl /E RS1 /Fo rs2.fxo |
Erstellt eine eigenständige Stammsignaturbinärdatei aus einer Quelle, die mehr als nur eine Stammsignatur enthalten kann. Beachten Sie das _ Rootig 1 _ 0-Ziel, und dass RS1 der Name der Stammsignatur # (definieren) Makrozeichenfolge in der HLSL-Datei ist. |
Die über FXC verfügbare Funktionalität ist auch programmgesteuert mithilfe der D3DCompile-Funktion verfügbar. Mit diesem Aufruf wird ein Shader mit einer Stammsignatur oder einer eigenständigen Stammsignatur kompiliert (wobei das _ Rootig-Ziel auf 1 0 festgelegt _ wird). D3DGetBlobPart und D3DSetBlobPart können Stammsignaturen extrahieren und an ein vorhandenes Blob anfügen. D3D _ BLOB ROOT SIGNATURE wird _ _ verwendet, um den Stammsignatur-Blobteiltyp anzugeben. D3DStripShader entfernt die Stammsignatur (mithilfe des D3DCOMPILER _ STRIP _ ROOT _ SIGNATURE-Flags) aus dem Blob.
Notizen
Hinweis
Während die Offlinekompilierung von Shadern dringend empfohlen wird, wenn Shader zur Laufzeit kompiliert werden müssen, lesen Sie die Hinweise für D3DCompile2.
Hinweis
Vorhandene HLSL-Ressourcen müssen nicht geändert werden, um Stammsignaturen zu verarbeiten, die mit ihnen verwendet werden sollen.