Direct3D 11 on 12

D3D11On12 ist ein Mechanismus, mit dem Entwickler D3D11-Schnittstellen und -Objekte verwenden können, um die D3D12-API zu steuern. D3D11on12 ermöglicht es Komponenten, die mit D3D11 geschrieben wurden (z. B. D2D-Text und Benutzeroberfläche), mit Komponenten zusammenzuarbeiten, die für die D3D12-API geschrieben wurden. D3D11on12 ermöglicht auch die inkrementelle Portierung einer Anwendung von D3D11 auf D3D12, indem Teile der App aus Gründen der Einfachheit weiterhin D3D11 als Ziel verwenden, während andere D3D12 für die Leistung verwenden und dabei immer ein vollständiges und korrektes Rendering haben. D3D11On12 macht es einfacher als die Verwendung von Interop-Techniken, um Ressourcen gemeinsam zu nutzen und die Arbeit zwischen den beiden APIs zu synchronisieren.

Initialisieren von D3D11On12

Um mit der Verwendung von D3D11On12 zu beginnen, besteht der erste Schritt darin, eine D3D12-Geräte- und Befehlswarteschlange zu erstellen. Diese Objekte werden als Eingabe für die Initialisierungsmethode D3D11On12CreateDevice bereitgestellt. Sie können sich diese Methode wie das Erstellen eines D3D11-Geräts mit dem imaginären Treibertyp D3D_DRIVER_TYPE_11ON12 vorstellen, wobei der D3D11-Treiber für das Erstellen von Objekten und das Übermitteln von Befehlslisten an die D3D12-API verantwortlich ist.

Nachdem Sie über ein D3D11-Gerät und einen unmittelbaren Kontext verfügen, können QueryInterface Sie das Gerät für die ID3D11On12Device-Schnittstelle deaktivieren. Dies ist die primäre Schnittstelle, die für die Interop zwischen D3D11 und D3D12 verwendet wird. Damit sowohl der D3D11-Gerätekontext als auch die D3D12-Befehlslisten auf denselben Ressourcen ausgeführt werden, müssen "umschlossene Ressourcen" mithilfe der CreateWrappedResource-API erstellt werden. Diese Methode "fördert" eine D3D12-Ressource, um in D3D11 verständlich zu sein. Eine umschlossene Ressource beginnt im Zustand "erworben", eine Eigenschaft, die von den Methoden AcquireWrappedResources und ReleaseWrappedResources bearbeitet wird.

Beispielverwendung

Die typische Verwendung von D3D11On12 besteht in der Verwendung von D2D, um Text oder Bilder auf einem D3D12-Backpuffer zu rendern. Beispielcode finden Sie im D3D11On12-Beispiel. Im Folgenden finden Sie eine grobe Übersicht über die hierfür zu ergreifenden Schritte:

  • Erstellen Sie ein D3D12-Gerät (D3D12CreateDevice) und eine D3D12-Swapchain (CreateSwapChain mit einer ID3D12CommandQueue als Eingabe).
  • Erstellen Sie ein D3D11On12-Gerät mit dem D3D12-Gerät und derselben Befehlswarteschlange wie die Eingabe.
  • Rufen Sie die Swap chain back-Puffer ab, und erstellen Sie D3D11-umschlossene Ressourcen für jeden von ihnen. Der verwendete Eingabezustand sollte die letzte Art und Weise sein, in der D3D12 ihn verwendet hat (z. B. RENDER_TARGET), und der Ausgabezustand sollte die Art und Weise sein, in der D3D12 ihn nach Abschluss von D3D11 verwendet (z. B. PRESENT).
  • Initialisieren Sie D2D, und stellen Sie die umschlossenen D3D11-Ressourcen für D2D bereit, um das Rendering vorzubereiten.

Gehen Sie dann für jeden Frame wie folgt vor:

  • Rendern Sie mithilfe einer D3D12-Befehlsliste in den aktuellen Swap chain Back-Puffer, und führen Sie ihn aus.
  • Rufen Sie die umschlossene Ressource des aktuellen Backpuffers ab (AcquireWrappedResources).
  • Geben Sie D2D-Renderingbefehle aus.
  • Geben Sie die umschlossene Ressource (ReleaseWrappedResources) frei.
  • Leeren Sie den D3D11-unmittelbaren Kontext.
  • Vorhanden (IDXGISwapChain1::P resent1).

Hintergrund

D3D11On12 funktioniert systematisch. Jeder D3D11-API-Aufruf durchläuft die typische Laufzeitüberprüfung und gelangt zum Treiber. Auf der Treiberebene zeichnet der spezielle 11on12-Treiber den Zustand auf und stellt Rendervorgänge in D3D12-Befehlslisten aus. Diese Befehlslisten werden bei Bedarf übermittelt (z. B. kann es sein, dass Befehle für eine Abfrage GetData oder Ressource Map geleert werden müssen) oder wie von Flush angefordert. Beim Erstellen eines D3D11-Objekts wird in der Regel das entsprechende D3D12-Objekt erstellt. Einige feste Funktionsrenderungsvorgänge in D3D11, z GenerateMips . B. oder DrawAuto werden in D3D12 nicht unterstützt. D3D11On12 emuliert sie daher mithilfe von Shadern und zusätzlichen Ressourcen.

Für die Interop ist es wichtig, zu verstehen, wie D3D11On12 mit den D3D12-Objekten interagiert, die die App erstellt und bereitgestellt hat. Um sicherzustellen, dass die Arbeit in der richtigen Reihenfolge erfolgt, muss der D3D11-unmittelbaren Kontext geleert werden, bevor zusätzliche D3D12-Arbeiten an diese Warteschlange übermittelt werden können. Es ist auch wichtig, sicherzustellen, dass die D3D11On12 zugewiesene Warteschlange jederzeit entleerbar sein muss. Das bedeutet, dass alle Wartezeiten in der Warteschlange letztendlich erfüllt werden müssen, auch wenn der D3D11-Thread unbegrenzt rendert. Achten Sie darauf, keine Abhängigkeit davon zu nehmen, wann D3D11On12 Leerungen einfügt oder wartet, da sich dies mit zukünftigen Releases ändern kann. Darüber hinaus verfolgt und bearbeitet D3D11On12 die Ressourcenzustände selbst. Die einzige Möglichkeit, die Kohärenz von Zustandsübergängen sicherzustellen, besteht darin, die Acquire-/Release-APIs zu verwenden, um die Zustandsnachverfolgung so zu bearbeiten, dass sie den Anforderungen der App entspricht.

Bereinigen

Um eine umschlossene D3D11On12-Ressource freizugeben, müssen zwei Dinge in dieser Reihenfolge geschehen:

  • Alle Verweise auf die Ressource, einschließlich aller Ansichten der Ressource, müssen freigegeben werden.
  • Die Verarbeitung der verzögerten Zerstörung muss erfolgen. Die einfachste Möglichkeit, dies sicherzustellen, ist das Aufrufen der unmittelbaren Kontext-API Flush .

Nachdem beide Schritte abgeschlossen sind, sollten alle Verweise, die von der umschlossenen Ressource vorgenommen werden, freigegeben werden, und die D3D12-Ressource wird ausschließlich im Besitz der D3D12-Komponente. Beachten Sie, dass D3D12 immer noch auf die GPU-Vervollständigung warten muss, bevor sie eine Ressource vollständig freigeben. Achten Sie daher darauf, einen Verweis auf die Ressource zu speichern, bevor Sie die beiden oben genannten Schritte ausführen, es sei denn, Sie haben bereits bestätigt, dass die GPU die Ressource nicht mehr verwendet.

Alle anderen Ressourcen oder Objekte, die von D3D11On12 erstellt wurden, werden zum geeigneten Zeitpunkt bereinigt, wenn die GPU sie mithilfe des Mechanismus für verzögerte Zerstörung von D3D11 verwendet hat. Wenn Sie jedoch versuchen, das D3D11On12-Gerät selbst freizugeben, während die GPU noch ausgeführt wird, kann die Zerstörung blockiert werden, bis die GPU abgeschlossen ist.

Einschränkungen

Die D3D11On12-Ebene implementiert eine sehr große Teilmenge der D3D11-API, es gibt jedoch einige bekannte Lücken (zusätzlich zu Fehlern in der Implementierung, die zu einem falschen Rendering führen können).

Stand Windows 10, Version 1809 (10,0; Build 17763), solange D3D11On12 auf einem Treiber ausgeführt wird, der Shadermodell 6.0 oder höher unterstützt, können Shader ausgeführt werden, die Schnittstellen verwenden. In früheren Versionen von Windows ist das Feature shaderschnittstellen in D3D11On12 nicht implementiert, und der Versuch, das Feature zu verwenden, verursacht Fehler und Debugmeldungen.

Ab Windows 10 Version 1803 (10.0; Build 17134), swap chains werden auf D3D11On12-Geräten unterstützt. In früheren Versionen von Windows sind sie dies nicht.

D3D11On12 wurde nicht für die Leistung optimiert. Es wird wahrscheinlich einen moderaten CPU-Overhead im Vergleich zu einem Standard-D3D11-Treiber, minimalen GPU-Overhead, und es ist bekannt, dass es einen erheblichen Arbeitsspeicheraufwand gibt. Daher wird die Verwendung von D3D11On12 für komplizierte 3D-Szenen nicht empfohlen, sondern stattdessen für einfache Szenen oder 2D-Rendering empfohlen.

APIs

APIs, aus denen die 11on12-Ebene besteht, werden in 11on12-Referenz beschrieben.

D2D mit D3D11on12 exemplarische Vorgehensweise

Grundlegendes zu Direct3D 12

Arbeiten mit Direct3D 11, Direct3D 10 und Direct2D