Indirektes Zeichnen
Indirektes Zeichnen ermöglicht es, einige Szenendurchläufe und Cullings von der CPU auf die GPU zu verschieben, was die Leistung verbessern kann. Der Befehlspuffer kann von der CPU oder GPU generiert werden.
- Befehlssignaturen
- Indirekte Argumentpufferstrukturen
- Erstellen von Befehlssignaturen
- Zugehörige Themen
Befehlssignaturen
Mit dem Befehlssignaturobjekt (ID3D12CommandSignature) können Apps indirekte Zeichnung angeben, insbesondere Folgendes festlegen:
- Das indirekte Argumentpufferformat.
- Der verwendete Befehlstyp (aus den ID3D12GraphicsCommandList-MethodenDrawInstanced, DrawIndexedInstanced oder Dispatch).
- Der Satz von Ressourcenbindungen, der sich pro Befehlsaufruf im Vergleich zu der Gruppe ändert, die geerbt wird.
Beim Start erstellt eine App einen kleinen Satz von Befehlssignaturen. Zur Laufzeit füllt die Anwendung einen Puffer mit Befehlen (über die vom App-Entwickler gewählten Mittel). Die Befehle enthalten optional den Zustand, der für Vertexpuffersichten, Indexpuffersichten, Stammkonstanten und Stammdeskriptoren (rohe oder strukturierte SRV/UAV/CBVs) festgelegt werden soll. Diese Argumentlayouts sind nicht hardwarespezifisch, sodass Apps die Puffer direkt generieren können. Die Befehlssignatur erbt den verbleibenden Zustand aus der Befehlsliste. Anschließend ruft die App ExecuteIndirect auf, um die GPU anzuweisen, den Inhalt des indirekten Argumentpuffers entsprechend dem format zu interpretieren, das durch eine bestimmte Befehlssignatur definiert wird.
Wenn die Befehlssignatur Stammargumente ändert, wird dies in der Befehlssignatur als Teilmenge einer Stammsignatur gespeichert.
Beachten Sie, dass kein Befehlssignaturstatus in die Befehlsliste zurückfällt, wenn die Ausführung abgeschlossen ist.
Angenommen, ein App-Entwickler möchte eine eindeutige Stammkonstante pro Zeichnungsaufruf im indirekten Argumentpuffer angeben. Die App erstellt eine Befehlssignatur, die es dem indirekten Argumentpuffer ermöglicht, die folgenden Parameter pro Draw-Aufruf anzugeben:
- Der Wert einer Stammkonstante.
- Die Zeichenargumente (Vertexanzahl, instance Anzahl usw.).
Der von der Anwendung generierte indirekte Argumentpuffer würde ein Array von Datensätzen mit fester Größe enthalten. Jede Struktur entspricht einem Zeichnungsaufruf. Jede Struktur enthält die Zeichenargumente und den Wert der Stammkonstante. Die Anzahl der Zeichnungsaufrufe wird in einem separaten GPU-sichtbaren Puffer angegeben.
Es folgt ein Beispielbefehlspuffer, der von der App generiert wurde:
Indirekte Argumentpufferstrukturen
Die folgenden Strukturen definieren, wie bestimmte Argumente in einem indirekten Argumentpuffer angezeigt werden. Diese Strukturen werden in keiner D3D12-API angezeigt. Anwendungen verwenden diese Definitionen beim Schreiben in einen indirekten Argumentpuffer (mit der CPU oder GPU):
- D3D12_DRAW_ARGUMENTS
- D3D12_DRAW_INDEXED_ARGUMENTS
- D3D12_DISPATCH_ARGUMENTS
- D3D12_VERTEX_BUFFER_VIEW
- D3D12_INDEX_BUFFER_VIEW
- D3D12_GPU_VIRTUAL_ADDRESS (typdef'd Synonym für UINT64).
- D3D12_CONSTANT_BUFFER_VIEW
Erstellen von Befehlssignaturen
Verwenden Sie zum Erstellen einer Befehlssignatur die folgenden API-Elemente:
- ID3D12Device::CreateCommandSignature (gibt einen ID3D12CommandSignature aus)
- D3D12_INDIRECT_ARGUMENT_TYPE
- D3D12_INDIRECT_ARGUMENT_DESC
- D3D12_COMMAND_SIGNATURE_DESC
Die Reihenfolge von Argumenten innerhalb eines indirekten Argumentpuffers wird so definiert, dass sie genau der Reihenfolge der Argumente entspricht, die im pArguments-Parameter von D3D12_COMMAND_SIGNATURE_DESC angegeben sind. Alle Argumente für einen Draw(Grafik)/Dispatch-Aufruf (Compute) in einem indirekten Argumentpuffer sind eng gepackt. Anwendungen können jedoch einen beliebigen Byteschritt zwischen Draw-/Dispatch-Befehlen in einem indirekten Argumentpuffer angeben.
Die Stammsignatur muss nur angegeben werden, wenn die Befehlssignatur eines der Stammargumente ändert.
Für den SRV/UAV/CBV-Stamm ist die angegebene Anwendungsgröße in Bytes. Die Debugebene überprüft die folgenden Einschränkungen für die Adresse:
- CBV: Die Adresse muss ein Vielfaches von 256 Bytes sein.
- Unformatierte SRV/UAV: Die Adresse muss ein Vielfaches von 4 Bytes sein.
- Strukturierte SRV/UAV: Adresse muss ein Vielfaches des Strukturbytes stride sein (im Shader deklariert).
Eine bestimmte Befehlssignatur ist entweder eine Zeichen- oder eine Computebefehlssignatur. Wenn eine Befehlssignatur einen Zeichnungsvorgang enthält, handelt es sich um eine Grafikbefehlssignatur. Andernfalls muss die Befehlssignatur einen Verteilungsvorgang enthalten, und es handelt sich um eine Computebefehlssignatur.
Die folgenden Abschnitte zeigen einige Beispielbefehlssignaturen.
Keine Argumentänderungen
In diesem Beispiel enthält der von der Anwendung generierte indirekte Argumentpuffer ein Array von 36-Byte-Strukturen. Jede Struktur enthält nur die fünf Parameter, die an DrawIndexedInstanced (plus Padding) übergeben werden.
Der Code zum Erstellen der Befehlssignaturbeschreibung folgt:
D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;
Das Layout einer einzelnen Struktur in einem indirekten Argumentpuffer lautet:
Byte | BESCHREIBUNG |
---|---|
0:3 | IndexCountPerInstance |
4:7 | InstanceCount |
8:11 | StartIndexLocation |
12:15 | BaseVertexLocation |
16:19 | StartInstanceLocation |
20:35 | Auffüllen |
Stammkonstanten und Vertexpuffer
In diesem Beispiel ändert jede Struktur in einem indirekten Argumentpuffer zwei Stammkonstanten, ändert eine Vertexpufferbindung und führt einen nicht indizierten Zeichnungsvorgang aus. Zwischen Strukturen gibt es keine Auffüllung.
Der Code zum Erstellen der Befehlssignaturbeschreibung lautet:
D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;
Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;
Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;
Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;
Das Layout einer einzelnen Struktur innerhalb des indirekten Argumentpuffers ist wie folgt:
Byte | BESCHREIBUNG |
---|---|
0:3 | Daten für den Stammparameterindex 2 |
4:7 | Daten für den Stammparameterindex 6 |
8:15 | Virtuelle Adresse von VB am Slot 3 (64-Bit) |
16:19 | VB-Größe |
20:23 | VB-Schritt |
24:27 | VertexCountPerInstance |
28:31 | InstanceCount |
32:35 | StartVertexLocation |
36:39 | StartInstanceLocation |
Zugehörige Themen
-
DirectX-Videotutorials für erweitertes Lernen: Ausführen indirekter und asynchroner GPU-Culling
-
Indirektes Zeichnen und GPU-Culling: Exemplarische Codeanleitung
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für