Stammsignatur, Version 1.1

Der Zweck von Version 1.1 der Stammsignatur besteht darin, Anwendungen zu ermöglichen, Treibern mitzuteilen, wann sich Deskriptoren in einem Deskriptorheap nicht ändern oder die Datendeskriptoren, die auf zeigen, nicht geändert werden. Dadurch können Treiber Optimierungen vornehmen, die möglicherweise in dem Wissen möglich sind, dass ein Deskriptor oder der Speicher, auf den er verweist, für einen bestimmten Zeitraum statisch ist.

Übersicht

Root Signature Version 1.0 ermöglicht es, den Inhalt von Deskriptorheaps und den Speicher, auf den sie verweisen, von Anwendungen jederzeit frei zu ändern, wenn Befehlslisten/Bündel, die darauf verweisen, möglicherweise auf der GPU ausgeführt werden. Sehr häufig benötigen Anwendungen jedoch nicht die Flexibilität, Deskriptoren oder Arbeitsspeicher zu ändern, nachdem Befehle aufgezeichnet wurden, die darauf verweisen.

Anwendungen sind oft trivial in der Lage:

  • Richten Sie Deskriptoren (und möglicherweise den Speicher, auf den sie verweisen) vor dem Binden von Deskriptortabellen oder Stammdeskriptoren in einer Befehlsliste oder einem Bündel ein.
  • Stellen Sie sicher, dass sich diese Deskriptoren erst ändern, wenn die Befehlsliste /bundles, die auf sie verweisen, die Ausführung zum letzten Mal abgeschlossen haben.
  • Stellen Sie sicher, dass sich die Daten, auf die die Deskriptoren zeigen, nicht für die gleiche vollständige Dauer ändern.

Alternativ kann eine Anwendung möglicherweise nur erkennen, dass sich Daten für eine kürzere Dauer nicht ändern. Insbesondere können Daten während der Ausführung der Befehlsliste für das Zeitfenster statisch sein, das derzeit von einer Stammparameterbindung (Deskriptortabelle oder Stammdeskriptor) auf die Daten verweist. Anders ausgedrückt: Eine Anwendung möchte möglicherweise die Ausführung auf der GPU-Zeitleiste ausführen, die einige Daten zwischen Zeiträumen aktualisiert, in denen sie über einen Stammparameter festgelegt werden, da sie weiß, dass sie statisch sind, wenn sie festgelegt werden.

Wenn sich Deskriptoren oder die Datendeskriptoren, auf die verweisen, nicht ändern, sind die spezifischen Optimierungen, die Treiber möglicherweise ausführen, hardwareherstellerspezifisch, und vor allem ändern sie das Verhalten nicht, außer möglicherweise die Leistung zu verbessern. Wenn Sie möglichst viel Wissen über anwendungsabsichten beibehalten, werden Anwendungen nicht belastet.

Eine Optimierung besteht darin, dass viele Treiber effizientere Speicherzugriffe durch Shader erzeugen können, wenn sie wissen, welche Versprechen eine Anwendung über die Statik von Deskriptoren und Daten machen kann. Beispielsweise könnten Treiber eine Dereferenzierungsebene für den Zugriff auf einen Deskriptor in einem Heap entfernen, indem sie ihn in einen Stammdeskriptor konvertieren, wenn die jeweilige Hardware nicht auf die Stammargumentgröße reagiert.

Die zusätzliche Aufgabe für Entwickler, die Version 1.1 verwenden, besteht darin, Zusagen über die Volatilität und Statik von Daten zu machen, wo immer möglich, damit Treiber die sinnvollen Optimierungen machen können. Entwickler müssen keine Zusagen zur Statik machen.

Die Stammsignaturversion 1.0 funktioniert weiterhin unverändert, obwohl Anwendungen, die Stammsignaturen neu kompilieren, jetzt standardmäßig Root Signature 1.1 verwenden (mit der Option, Version 1.0 bei Bedarf zu erzwingen).

Statische und flüchtige Flags

Die folgenden Flags sind Teil der Stammsignatur, damit Treiber eine Strategie für die optimale Behandlung einzelner Stammargumente auswählen können, wenn sie festgelegt sind, und auch die gleichen Annahmen in Pipeline State Objects (PSOs) einbetten können, wenn sie ursprünglich kompiliert werden , da die Stammsignatur Teil eines PSO ist.

Die folgenden Flags werden von der App festgelegt und gelten für Deskriptoren oder Daten.

typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS
{
    D3D12_DESCRIPTOR_RANGE_FLAG_NONE    = 0,
    D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE    = 0x1,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE   = 0x2,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE    = 0x4,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8
} D3D12_DESCRIPTOR_RANGE_FLAGS;

typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS
{
    D3D12_ROOT_DESCRIPTOR_FLAG_NONE = 0,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE    = 0x2,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC  = 0x8
} D3D12_ROOT_DESCRIPTOR_FLAGS;

DESCRIPTORS_VOLATILE

Wenn dieses Flag festgelegt ist, können die Deskriptoren in einem Deskriptorheap, auf den eine Stammdeskriptortabelle verweist, von der Anwendung jederzeit geändert werden, es sei denn, die Befehlsliste/Bündel, die die Deskriptortabelle binden, wurden übermittelt und haben die Ausführung noch nicht abgeschlossen. Für instance ist das Aufzeichnen einer Befehlsliste und das anschließende Ändern von Deskriptoren in einem Deskriptorheap, auf den sich diese bezieht, gültig, bevor die Befehlsliste zur Ausführung übermittelt wird. Dies ist das einzige unterstützte Verhalten von Root Signature Version 1.0.

Wenn das DESCRIPTORS_VOLATILE-Flag nicht festgelegt ist, sind Deskriptoren statisch. Für diesen Modus gibt es kein Flag. Statische Deskriptoren bedeuten, dass die Deskriptoren in einem Deskriptorheap, auf den eine Stammdeskriptortabelle verweist, zu dem Zeitpunkt initialisiert wurden, zu dem die Deskriptortabelle für eine Befehlsliste/ein Bündel (während der Aufzeichnung) festgelegt wurde und die Deskriptoren erst geändert werden können, wenn die Befehlsliste/das Paket zum letzten Mal ausgeführt wurde. Für Version 1.1 der Stammsignatur sind statische Deskriptoren die Standardannahme, und die Anwendung muss bei Bedarf das flag DESCRIPTORS_VOLATILE angeben.

Bei Bundles, die Deskriptortabellen mit statischen Deskriptoren verwenden, müssen die Deskriptoren ab dem Zeitpunkt bereit sein, zu dem das Bundle aufgezeichnet wird (im Gegensatz zum Aufruf des Bundles), und sie müssen sich erst ändern, wenn die Ausführung des Bundles zum letzten Mal abgeschlossen ist. Deskriptortabellen, die auf statische Deskriptoren verweisen, müssen während der Bündelaufzeichnung festgelegt und nicht in das Bundle geerbt werden. Es ist gültig, dass eine Befehlsliste eine Deskriptortabelle mit statischen Deskriptoren verwendet, die in einem Bündel festgelegt und zurück zur Befehlsliste zurückgegeben wurde.

Wenn Deskriptoren statisch sind, gibt es eine weitere Verhaltensänderung, bei der das flag DESCRIPTORS_VOLATILE festgelegt werden muss. Nicht beschränkte Zugriffe auf puffernde Ansichten (im Gegensatz zu Texture1D/2D/3D/Cube-Ansichten) sind ungültig und erzeugen nicht definierte Ergebnisse, einschließlich möglicher Gerätezurücksetzung, anstatt Standardwerte für Lese- oder Schreibvorgänge zurückzugeben. Der Zweck zum Entfernen der Fähigkeit für Anwendungen, von der Hardware außerhalb der Grenzen abhängig zu sein, besteht darin, Treibern die Möglichkeit zu geben, statische Deskriptorzugriffe auf Stammdeskriptorzugriffe heraufzustufen, wenn sie dies für effizienter erachen. Stammdeskriptoren unterstützen keine Out-of-Bounds-Überprüfung.

Wenn Anwendungen beim Zugriff auf Deskriptoren auf sicheres Speicherzugriffsverhalten angewiesen sind, müssen sie die Deskriptorbereiche, die auf diese Deskriptoren zugreifen, als DESCRIPTORS_VOLATILE markieren.

DATA_VOLATILE

Wenn dieses Flag festgelegt ist, können die Daten, auf die von Deskriptoren verwiesen wird, von der CPU jederzeit geändert werden, es sei denn, die Befehlsliste/Bündel, die die Deskriptortabelle binden, wurden übermittelt und haben die Ausführung noch nicht abgeschlossen. Dies ist das einzige unterstützte Verhalten von Root Signature Version 1.0.

Das Flag ist sowohl in Deskriptorbereichsflags als auch in Stammdeskriptorflags verfügbar.

DATA_STATIC_WHILE_SET_AT_EXECUTE

Wenn dieses Flag festgelegt ist, können die Daten, auf die von Deskriptoren verwiesen wird, nicht geändert werden, wenn der zugrunde liegende Stammdeskriptor oder die zugrunde liegende Deskriptortabelle während der Ausführung auf dem GPU-Zeitleiste in einer Befehlsliste bzw. einem Bundle festgelegt wird und wenn nachfolgende Ziehungen/Verteiler nicht mehr auf die Daten verweisen.

Bevor ein Stammdeskriptor oder eine Deskriptortabelle auf der GPU festgelegt wurde, können diese Daten auch durch die gleiche Befehlsliste bzw. dasselbe Paket geändert werden. Die Daten können auch geändert werden, während eine Stammdeskriptor- oder Deskriptortabelle, die darauf verweist, weiterhin in der Befehlsliste/im Bundle festgelegt ist, solange das Zeichnen/Verteilen, das darauf verweist, abgeschlossen ist. Dies erfordert jedoch, dass die Deskriptortabelle erneut an die Befehlsliste gebunden wird, bevor die Stammdeskriptor- oder Deskriptortabelle das nächste Mal dereferenziert wird. Dadurch kann der Treiber erkennen, dass daten, auf die von einem Stammdeskriptor oder einer Deskriptortabelle verwiesen wird, geändert wurden.

Der wesentliche Unterschied zwischen DATA_STATIC_WHILE_SET_AT_EXECUTE und DATA_VOLATILE besteht darin, DATA_VOLATILE ein Treiber nicht erkennen kann, ob Datenkopien in einer Befehlsliste die Daten geändert haben, auf die ein Deskriptor verweist, ohne zusätzliche Zustandsnachverfolgung durchzuführen. Wenn ein Treiber also für instance beliebige Datenvorrufbefehle in seine Befehlsliste einfügen kann (um beispielsweise den Shaderzugriff auf bekannte Daten effizienter zu gestalten), teilt DATA_STATIC_WHILE_SET_AT_EXECUTE dem Treiber mit, dass er nur daten vorab abrufen muss, wenn er über SetGraphicsRootDescriptorTable, SetComputeRootDescriptorTable festgelegt ist. oder eine der Methoden zum Festlegen der konstanten Pufferansicht, der Shaderressourcenansicht oder der ungeordneten Zugriffsansicht.

Für Bundles gilt die Zusage, dass Daten statisch sind, während sie bei execute festgelegt sind, eindeutig auf jede Ausführung des Bundles.

Das Flag ist sowohl in Deskriptorbereichsflags als auch in Stammdeskriptorflags verfügbar.

DATA_STATIC

Wenn dieses Flag festgelegt ist, wurden die Daten, auf die von Deskriptoren verwiesen wird, zu dem Zeitpunkt initialisiert, zu dem ein Stammdeskriptor oder eine Deskriptortabelle, die auf den Speicher verweist, während der Aufzeichnung für eine Befehlsliste bzw. ein Paket festgelegt wurde, und die Daten können erst geändert werden, wenn die Ausführung der Befehlsliste/des Pakets zum letzten Mal abgeschlossen wurde.

Bei Bundles beginnt die statische Dauer bei der Stammdeskriptor- oder Deskriptortabelleneinstellung während der Aufzeichnung des Bundles, im Gegensatz zur Aufzeichnung einer aufrufenden Befehlsliste. Darüber hinaus muss eine Deskriptortabelle, die auf statische Daten verweist, im Bundle festgelegt und nicht geerbt werden. Es ist gültig, dass eine Befehlsliste eine Deskriptortabelle verwendet, die auf statische Daten verweist, die in einem Bündel festgelegt und an die Befehlsliste zurückgegeben wurden.

Das Flag ist sowohl in Deskriptorbereichsflags als auch in Stammdeskriptorflags verfügbar.

Kombinieren von Flags

Höchstens eines der DATA-Flags kann gleichzeitig angegeben werden, mit Ausnahme von Sampler-Deskriptorbereichen, die DATA-Flags überhaupt nicht unterstützen, da Sampler nicht auf Daten zeigen.

Das Fehlen von DATA-Flags für SRV- und CBV-Deskriptorbereiche bedeutet, dass standardmäßig DATA_STATIC_WHILE_SET_AT_EXECUTE Verhalten angenommen wird. Der Grund, warum diese Standardeinstellung anstelle von DATA_STATIC gewählt wird, ist, dass DATA_STATIC_WHILE_SET_AT_EXECUTE in den meisten Fällen viel wahrscheinlicher ein sicherer Standardwert ist, während immer noch eine Optimierungschance bietet, die besser ist als DATA_VOLATILE.

Das Fehlen von DATA-Flags für UAV-Deskriptorbereiche bedeutet, dass standardmäßig DATA_VOLATILE Verhalten angenommen wird, da in der Regel UAVs geschrieben werden.

DESCRIPTORS_VOLATILE kann nicht mit DATA_STATIC kombiniert, sondern mit den anderen DATA-Flags kombiniert werden. Der Grund, warum DESCRIPTORS_VOLATILE mit DATA_STATIC_WHILE_SET_AT_EXECUTE kombiniert werden kann, ist, dass flüchtige Deskriptoren immer noch während der Ausführung der Befehlsliste/ des Bundles bereit sein müssen und DATA_STATIC_WHILE_SET_AT_EXECUTE nur Zusagen über die Statik innerhalb einer Teilmenge der Befehlslisten-/Bundleausführung macht.

Flagzusammenfassung

In den folgenden Tabellen sind die flag-Kombinationen zusammengefasst, die verwendet werden können.

Gültige D3D12_DESCRIPTOR_RANGE_FLAGS-Einstellungen BESCHREIBUNG
Keine Flags festgelegt Deskriptoren sind statisch (Standard). Standardannahmen für Daten: für SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE und für UAV: DATA_VOLATILE. Diese Standardwerte für SRV/CBV passen sicher zu den Verwendungsmustern für die meisten Stammsignaturen.
DATA_STATIC Sowohl Deskriptoren als auch Daten sind statisch. Dadurch wird das Potenzial für die Treiberoptimierung maximiert.
DATA_VOLATILE Deskriptoren sind statisch, und die Daten sind flüchtig.
DATA_STATIC_WHILE_SET_AT_EXECUTE Deskriptoren sind statisch, und Daten sind statisch, während sie bei der Ausführung festgelegt sind.
DESCRIPTORS_VOLATILE Deskriptoren sind flüchtig, und es werden Standardannahmen für Daten getroffen: für SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE und für UAV: DATA_VOLATILE.
DESCRIPTORS_VOLATILE | DATA_VOLATILE Sowohl Deskriptoren als auch Daten sind volatil, was der Stammsignatur 1.0 entspricht.
DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE Deskriptoren sind flüchtig, aber beachten Sie, dass sie sich während der Ausführung von Befehlslisten nicht ändern können. Daher ist es gültig, die zusätzliche Deklaration zu kombinieren, dass Daten statisch sind, während sie während der Ausführung über die Stammdeskriptortabelle festgelegt werden . Die zugrunde liegenden Deskriptoren sind effektiv länger statisch, als die Daten als statisch zugesagt werden.

 

Gültige D3D12_ROOT_DESCRIPTOR_FLAGS Einstellungen BESCHREIBUNG
Keine Flags festgelegt Standardannahmen für Daten: für SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE und für UAV: DATA_VOLATILE. Diese Standardwerte für SRV/CBV passen sicher zu den Verwendungsmustern für die meisten Stammsignaturen.
DATA_STATIC Daten sind statisch, das beste Potenzial für die Treiberoptimierung.
DATA_STATIC_WHILE_SET_AT_EXECUTE Die Daten sind statisch, während sie bei der Ausführung festgelegt sind.
DATA_VOLATILE Entspricht Stammsignatur 1.0.

 

API-Zusammenfassung der Version 1.1

Die folgenden API-Aufrufe aktivieren Version 1.1.

Enumerationen

Diese Enumerationen enthalten die Schlüsselflags zum Angeben der Deskriptor- und Datenvolatilität.

Strukturen

Aktualisierte Strukturen (ab Version 1.0) enthalten Verweise auf die Volatilität/statische Flags.

Functions

Die hier aufgeführten Methoden ersetzen die ursprünglichen Funktionen D3D12SerializeRootSignature und D3D12CreateRootSignatureDeserializer , da sie für jede Version der Stammsignatur konzipiert sind. Das serialisierte Formular wird an die CreateRootSignature-API übergeben. Wenn ein Shader mit einer Stammsignatur erstellt wurde, enthält der kompilierte Shader bereits eine serialisierte Stammsignatur.

Methoden

Die ID3D12VersionedRootSignatureDeserializer-Schnittstelle wird erstellt, um die Stammsignaturdatenstruktur deserialisieren.

Hilfsstrukturen

Hilfsstrukturen wurden hinzugefügt, um die Initialisierung einiger Strukturen der Version 1.1 zu unterstützen.

  • CD3DX12_DESCRIPTOR_RANGE1
  • CD3DX12_ROOT_PARAMETER1
  • CD3DX12_STATIC_SAMPLER1
  • CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC

Weitere Informationen finden Sie unter Hilfsstrukturen und -funktionen für D3D12.

Folgen einer Verletzung von Statischen Flags

Die oben beschriebenen Deskriptor- und Datenflags (sowie die durch das Fehlen bestimmter Flags implizierten Standardwerte) definieren eine Zusage der Anwendung an den Treiber, wie sie sich verhalten soll. Wenn eine Anwendung gegen das Versprechen verstößt, ist dies ein ungültiges Verhalten: Die Ergebnisse sind nicht definiert und können sich zwischen verschiedenen Treibern und Hardware unterscheiden.

Die Debugebene verfügt über Optionen zum Überprüfen, dass Anwendungen ihre Zusagen einhalten, einschließlich der Standardversprechen, die mit der Stammsignaturversion 1.1 ohne Festlegen von Flags kommen.

Versionsverwaltung

Beim Kompilieren von Stammsignaturen, die an Shader angefügt sind, werden neuere HLSL-Compiler standardmäßig die Stammsignatur in Version 1.1 kompilieren, während alte HLSL-Compiler nur 1.0 unterstützen. Beachten Sie, dass 1.1-Stammsignaturen nicht auf Betriebssystemen funktionieren, die die Stammsignatur 1.1 nicht unterstützen.

Die mit einem Shader kompilierte Stammsignaturversion kann mithilfe /force_rootsig_ver <version>von zu einer bestimmten Version erzwungen werden. Das Erzwingen der Version ist erfolgreich, wenn der Compiler das Verhalten der in der erzwungenen Version kompilierten Stammsignatur beibehalten kann, z. B. durch Löschen nicht unterstützter Flags in der Stammsignatur, die nur zu Optimierungszwecken dienen, sich aber nicht auf das Verhalten auswirken.

Auf diese Weise kann eine Anwendung für instance eine 1.1-Stammsignatur in 1.0 und 1.1 kompilieren, wenn sie die Anwendung erstellt und je nach Betriebssystemunterstützung die entsprechende Version zur Laufzeit auswählen. Es wäre jedoch am effizientesten, wenn eine Anwendung Stammsignaturen einzeln kompilieren würde (insbesondere, wenn mehrere Versionen erforderlich sind), getrennt von Shadern. Auch wenn Shader zunächst nicht mit einer angefügten Stammsignatur kompiliert werden, kann der Vorteil der Compilerüberprüfung der Kompatibilität von Stammsignaturen mit einem Shader beibehalten werden, indem die /verifyrootsignature Compileroption verwendet wird. Später zur Laufzeit können PsOs mithilfe von Shadern erstellt werden, die keine Stammsignaturen enthalten, während die gewünschte Stammsignatur (möglicherweise die entsprechende Version, die vom Betriebssystem unterstützt wird) als separaten Parameter übergeben werden.

Erstellen einer Stammsignatur

Stammsignaturen

Festlegen von Stammsignaturen in HLSL