Übersicht über Deskriptorheaps

Deskriptorheaps enthalten viele Objekttypen, die nicht Teil eines Pipelinezustandsobjekts (Pipeline State Object, PSO) sind, z. B. Shaderressourcenansichten (SRVs), Unordered Access Views (UAVs), Constant Buffer Views (CBVs) und Samplers.

Zweck von Deskriptorheaps

Der Hauptzweck eines Deskriptorheaps besteht darin, den Großteil der Speicherbelegung zu umfassen, der zum Speichern der Deskriptorspezifikationen von Objekttypen erforderlich ist, auf die Shader für ein möglichst großes Fenster des Renderings verweisen (idealerweise ein ganzer Renderingrahmen oder mehr). Wenn eine Anwendung wechselt, welche Texturen die Pipeline aus der API schnell sieht, muss im Deskriptorheap Speicherplatz vorhanden sein, um Deskriptortabellen für jeden erforderlichen Zustandssatz dynamisch zu definieren. Die Anwendung kann Sich entscheiden, Definitionen wiederzuverwenden, wenn die Ressourcen z. B. erneut in einem anderen Objekt verwendet werden, oder den Heapspeicher einfach sequenziell zuzuweisen, wenn verschiedene Objekttypen gewechselt werden.

Deskriptorheaps ermöglichen es einzelnen Softwarekomponenten auch, deskriptorspeicher getrennt voneinander zu verwalten.

Alle Heaps sind für die CPU sichtbar. Die Anwendung kann auch anfordern, welche CPU-Zugriffseigenschaften ein Deskriptorheap aufweisen soll (falls vorhanden): kombiniertes Schreiben, Zurückschreiben usw. Apps können beliebig viele Deskriptorheaps mit den gewünschten Eigenschaften erstellen. Apps haben immer die Möglichkeit, Deskriptorheaps zu erstellen, die ausschließlich für Stagingzwecke bestimmt sind, deren Größe nicht eingeschränkt ist, und das Kopieren in Deskriptorheaps, die bei Bedarf zum Rendern verwendet werden.

Es gibt einige Einschränkungen hinsichtlich der Möglichkeiten im selben Deskriptorheap. CBV-, UAV- und SRV-Einträge können sich im selben Deskriptorheap befindet. Samplers-Einträge können jedoch keinen Heap mit CBV-, UAV- oder SRV-Einträgen gemeinsam nutzen. In der Regel gibt es zwei Sätze von Deskriptorheaps: einen für die allgemeinen Ressourcen und den zweiten für Sampler.

Die Verwendung von Deskriptorheaps durch Direct3D 12 spiegelt die Leistung der meisten GPU-Hardware wider, d. h., dass Deskriptoren entweder nur in Deskriptorheaps live sind oder dass bei Verwendung dieser Heaps einfach weniger Adressierungsbits benötigt werden. Direct3D 12 erfordert die Verwendung von Deskriptorheaps. Es gibt keine Option zum Speichern von Deskriptoren an einer beliebigen Stelle im Arbeitsspeicher.

Deskriptorheaps können nur sofort von der CPU bearbeitet werden. Es gibt keine Option zum Bearbeiten eines Deskriptorheaps durch die GPU.

Synchronization

Der Inhalt des Deskriptorheaps kann vor, während und nach der Aufzeichnung von Befehlslisten geändert werden, die darauf verweisen. Deskriptoren können jedoch nicht geändert werden, während eine befehlsliste, die zur Ausführung übermittelt wird, auf diesen Speicherort verweisen kann, da dies eine Racebedingung aufrufen könnte.

Bindung

Höchstens ein kombinierter CBV-,SRV-/UAV-Heap und ein Sampler-Heap können jederzeit gebunden werden. Diese Heaps werden sowohl für die Grafik- als auch für die Computepipeline freigegeben (in ihren PSOs beschrieben).

Wechseln von Heaps

Es ist akzeptabel, dass eine Anwendung Heaps mithilfe der APIs SetDescriptorHeaps und Reset innerhalb derselben Befehlsliste oder in anderen umschaltet. Auf einigen Hardwarekomponenten kann dies ein kostspieliger Vorgang sein, bei dem ein GPU-Angehaltener erforderlich ist, um alle Arbeit zu leeren, die vom derzeit gebundenen Deskriptorheap abhängt. Wenn daher Deskriptorheaps geändert werden müssen, sollten Anwendungen versuchen, dies zu tun, wenn die GPU-Workload relativ gering ist, was möglicherweise änderungen am Anfang einer Befehlsliste einschränkt.

Bundles

Bei Bundles kann es nur einen Aufruf der SetDescriptorHeaps-Methode geben, und die festgelegten Deskriptorheaps müssen genau denen der Befehlsliste entsprechen, die das Paket aufruft. Wenn das Paket keine Deskriptortabellen ändert, müssen die Deskriptorheaps nicht festgelegt werden.

Eine Liste der API-Aufrufe, die nicht mit Paketen verwendet werden können, finden Sie unter Erstellen und Aufzeichnen von Befehlslisten und Paketen.

Verwaltung

Um alle Objekte in einer Szene zu rendern, sind viele Deskriptoren erforderlich, und es gibt einige verschiedene Verwaltungsstrategien, die befolgt werden können.

Die grundlegendste Strategie besteht darin, einen neuen Bereich des Deskriptorheaps mit allen Anforderungen für den nächsten Draw-Aufruf auszufüllen. Kurz vor dem Ausgeben des Draw-Aufrufs in der Befehlsliste würde also ein Deskriptortabellenzeiger auf den Anfang der neu aufgefüllten Tabelle festgelegt werden. Der Nachteil ist, dass keine Aufzeichnung erforderlich ist, wenn sich ein bestimmter Deskriptor im Heap befindet.

Der Nachteil dieser Strategie besteht darin, dass es viele Wiederholungen von Deskriptoren im Deskriptorheap geben kann, insbesondere wenn eine sehr ähnliche Szene gerendert wird und dieser Deskriptorheapbereich schnell aufgebraucht ist. Separate Deskriptorheaps für diejenigen, die auf der GPU gerendert werden, und für die, die von der CPU aufgezeichnet werden, sind wahrscheinlich erforderlich, um Konflikte zu vermeiden. Alternativ kann ein Untergeordnetes Zuordnungssystem verwendet werden.

Darüber hinaus kann das grundlegende System durch die sorgfältige Verwendung überlappender Deskriptortabellen von einem Draw-Aufruf zum nächsten weiter optimiert werden, sodass nur die neuen erforderlichen Deskriptoren hinzugefügt werden.

Eine effizientere Strategie als die grundlegende wäre das Vorabfüllen von Deskriptorheaps mit Deskriptoren, die für die Objekte (oder Materialien) erforderlich sind, die bekanntermaßen Teil der Szene sind. Die Idee hier ist, dass es nur erforderlich ist, die Deskriptortabelle zur Zeichnenzeit festzulegen, da der Deskriptorheap im Voraus aufgefüllt wird.

Eine Variante der Präfüllstrategie besteht darin, den Deskriptorheap als ein großes Array zu behandeln, das alle erforderlichen Deskriptoren an festen bekannten Speicherorten enthält. Anschließend muss der Draw-Aufruf nur einen Satz von Konstanten empfangen, bei denen es sich um die Indizes im Array von handelt, in denen die Deskriptoren verwendet werden müssen.

Eine weitere Optimierung besteht darin, sicherzustellen, dass Stammkonstanten und Stammdeskriptoren diejenigen enthalten, die sich am häufigsten ändern, anstatt Konstanten im Deskriptorheap zu platzieren. Für die meisten Hardwarekomponenten ist dies eine effiziente Methode zum Verarbeiten von Konstanten.

In der Praxis kann eine Grafik-Engine in unterschiedlichen Situationen eine andere Strategie verwenden und Elemente jeder Strategie kombinieren, um die jeweiligen Zeichnungsanforderungen zu erfüllen.

Deskriptorheaps