Übersicht über Deskriptorheaps

Deskriptorheaps enthalten viele Objekttypen, die nicht Teil eines Pipelinezustandsobjekts (PSO) sind, z. B. Shader Resource Views (SRVs), Unordered Access Views (UAVs), Constant Buffer Views (CBVs) und Sampler.

Der 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 Renderingfenster verweisen (idealerweise ein ganzer Renderingframe oder mehr). Wenn eine Anwendung wechselt, welche Texturen die Pipeline von der API schnell erkennt, muss im Deskriptorheap Platz vorhanden sein, um Deskriptortabellen für jeden erforderlichen Zustandssatz direkt zu definieren. Die Anwendung kann definitionen wiederverwenden, wenn die Ressourcen z. B. in einem anderen Objekt erneut verwendet werden, oder den Heapbereich einfach sequenziell zuweisen, wenn verschiedene Objekttypen wechselt.

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

Alle Heaps sind für die CPU sichtbar. Die Anwendung kann auch anfordern, welche CPU-Zugriffseigenschaften ein Deskriptorheap aufweisen sollte (falls vorhanden): Kombiniertes Schreiben, Zurückschreiben usw. Apps können beliebig viele Deskriptorheaps mit gewünschten Eigenschaften erstellen. Apps haben immer die Möglichkeit, Deskriptorheaps zu erstellen, die ausschließlich für Stagingzwecke ohne Einschränkungen in der Größe und zum Kopieren in Deskriptorheaps dienen, die bei Bedarf zum Rendern verwendet werden.

Es gibt einige Einschränkungen, was in den selben Deskriptorheap gehen kann. CBV-, UAV- und SRV-Einträge können sich im gleichen Deskriptorheap befinden. Sampler-Einträge können jedoch keinen Heap für CBV-, UAV- oder SRV-Einträge freigeben. 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 wider, was die meisten GPU-Hardware tut, d. h., dass Deskriptoren entweder nur in Deskriptorheaps leben müssen, oder einfach, dass weniger Adressbits erforderlich sind, wenn diese Heaps verwendet werden. Direct3D 12 erfordert die Verwendung von Deskriptorheaps, es gibt keine Option, Deskriptoren an einer beliebigen Stelle im Arbeitsspeicher zu platzieren.

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 zur Ausführung übermittelte Befehlsliste möglicherweise auf diesen Speicherort verweist, da dadurch eine Racebedingung aufgerufen werden kann.

Bindung

Maximal ein kombinierter CBV/SRV/UAV-Heap und ein Sampler-Heap können gleichzeitig gebunden werden. Diese Heaps werden von den Grafik- und Computepipelines gemeinsam genutzt (beschrieben in ihren PSOs).

Wechseln von Heaps

Es ist akzeptabel, dass eine Anwendung heaps innerhalb derselben oder in verschiedenen Befehlen mithilfe der SetDescriptorHeaps - und Reset-APIs wechselt. Bei einigen Hardware kann dies ein teurer Vorgang sein, der eine GPU-Warteschlange erfordert, um alle Arbeit zu leeren, die vom derzeit gebundenen Deskriptorheap abhängt. Wenn Deskriptorheaps geändert werden müssen, sollten Anwendungen daher versuchen, dies zu tun, wenn die GPU-Workload relativ leicht ist, was möglicherweise änderungen auf den Anfang einer Befehlsliste beschränkt.

Bundles

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

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

Verwaltung

Zum Rendern aller Objekte in einer Szene sind viele Deskriptoren erforderlich, und es gibt verschiedene Verwaltungsstrategien, die befolgt werden können.

Die grundlegendste Strategie wäre das Ausfüllen eines neuen Bereichs des Deskriptorheaps mit allen Anforderungen für den nächsten Draw-Aufruf. Kurz vor dem Ausführen des Draw-Aufrufs für die Befehlsliste würde also ein Deskriptortabellenzeiger auf den Anfang der neu aufgefüllten Tabelle festgelegt. Der Vorteil ist, dass es nicht erforderlich ist, aufzuzeichnen, wo sich ein bestimmter Deskriptor im Heap befindet.

Der Nachteil dieser Strategie ist, dass es viele Wiederholungen von Deskriptoren im Deskriptorheap geben könnte, insbesondere wenn eine sehr ähnliche Szene gerendert wird und dieser Deskriptorheapraum schnell verbraucht wird. Separate Deskriptorheaps für diejenigen, die auf der GPU gerendert werden, und für diejenigen, die von der CPU aufgezeichnet werden, wären wahrscheinlich erforderlich, um Konflikte zu vermeiden. Alternativ kann ein Unterzuordnungssystem verwendet werden.

Außerdem könnte das Basissystem durch sorgfältige Verwendung überlappender Deskriptortabellen von einem Zeichnungsaufruf zum nächsten weiter optimiert werden, sodass nur die neuen erforderlichen Deskriptoren hinzugefügt werden.

Eine effizientere als die grundlegende Strategie 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 Zeichnungszeit festzulegen, da der Deskriptorheap im Voraus aufgefüllt wird.

Eine Variante der Vorfüllstrategie besteht darin, den Deskriptorheap als ein riesiges Array zu behandeln, das alle erforderlichen Deskriptoren an festen bekannten Stellen enthält. Dann muss der Draw-Aufruf nur eine Reihe von Konstanten empfangen, die die Indizes in dem Array von sind, in dem 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 Hardware ist dies eine effiziente Möglichkeit, Konstanten zu behandeln.

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

Deskriptorheaps