Wichtige Änderungen von Direct3D 9 zu Direct3D 11
Summary
- Planen Sie Ihre DirectX-Portierung
- Wichtige Änderungen von Direct3D 9 zu Direct3D 11
- Übersicht der Features
In diesem Thema werden die wesentlichen Unterschiede zwischen DirectX 9 und DirectX 11 erläutert.
Direct3D 11 ist im Grunde die gleiche Art von API wie Direct3D 9 - eine virtualisierte Low-Level-Schnittstelle zur Grafikhardware. Sie ermöglicht es Ihnen dennoch, grafische Zeichenoperationen auf einer Vielzahl von Hardware-Implementierungen durchzuführen. Der Aufbau der Grafik-API hat sich seit Direct3D 9 geändert; das Konzept des Gerätekontexts wurde erweitert und eine API speziell für die Grafikinfrastruktur hinzugefügt. Die auf dem Direct3D-Gerät gespeicherten Ressourcen verfügen über einen neuartigen Mechanismus zur Datenpolymorphie, der als Ressourcenansicht bezeichnet wird.
Core-API-Funktionen
In Direct3D 9 musste man eine Schnittstelle zur Direct3D-API erstellen, bevor man sie verwenden konnte. In Ihrem Direct3D 11 Universal Windows Platform (UWP) Spiel rufen Sie eine statische Funktion namens D3D11CreateDevice auf, um das Gerät und den Gerätekontext zu erstellen.
Geräte und Gerätekontext
Ein Direct3D 11-Gerät stellt eine virtualisierte Grafikkarte dar. Es wird verwendet, um Ressourcen im Videospeicher zu erstellen, z. B.: Hochladen von Texturen auf die GPU, Erstellen von Ansichten auf Texturressourcen und Auslagerungsketten und Erstellen von Textursamplern. Eine vollständige Liste, wofür eine Direct3D 11-Geräteschnittstelle verwendet wird, finden Sie unter ID3D11Device und ID3D11Device1.
Ein Direct3D 11- Gerätekontext wird verwendet, um den Pipeline-Status festzulegen und Rendering-Befehle zu erzeugen. Eine Direct3D 11-Rendering-Kette verwendet beispielsweise einen Gerätekontext, um die Rendering-Kette einzurichten und die Szene zu zeichnen (siehe unten). Der Gerätekontext wird verwendet, um auf den von Direct3D-Geräteressourcen verwendeten Videospeicher zuzugreifen (abzubilden); er wird auch verwendet, um Subressourcendaten zu aktualisieren, zum Beispiel konstante Pufferdaten. Eine vollständige Liste, wofür ein Direct3D 11-Gerätekontext verwendet wird, finden Sie unter ID3D11DeviceContext und ID3D11DeviceContext1. Beachten Sie, dass die meisten unserer Beispiele einen unmittelbaren Kontext verwenden, um direkt auf dem Gerät zu rendern, aber Direct3D 11 unterstützt auch verzögerte Gerätekontexte, die hauptsächlich für Multithreading verwendet werden.
In Direct3D 11 werden das Gerätehandle und das Gerätekontexthandle beide durch den Aufruf von D3D11CreateDevice erhalten. Mit dieser Methode können Sie auch einen bestimmten Satz von Hardware-Features anfordern und Informationen über die von der Grafikkarte unterstützten Direct3D-Feature-Level abrufen. Siehe Einführung in ein Gerät in Direct3D 11 für weitere Informationen über Geräte, Gerätekontexte und Threading-Überlegungen.
Geräteinfrastruktur, Framepuffer und Rendering-Zielansichten
In Direct3D 11 werden der Geräteadapter und die Hardwarekonfiguration mit der DirectX Graphics Infrastructure (DXGI) API unter Verwendung der COM-Schnittstellen IDXGIAdapter und IDXGIDevice1 festgelegt. Puffer und andere Fensterressourcen (sichtbar oder außerhalb des Bildschirms) werden durch spezifische DXGI-Schnittstellen erstellt und konfiguriert; die IDXGIFactory2 Factory Pattern-Implementierung erwirbt DXGI-Ressourcen wie den Frame-Puffer. Da DXGI die Swap-Chain besitzt, wird eine DXGI-Schnittstelle verwendet, um Frames auf dem Bildschirm darzustellen - siehe IDXGISwapChain1.
Verwenden Sie IDXGIFactory2, um eine mit Ihrem Spiel kompatible Tauschkette zu erstellen. Sie müssen eine Swap-Kette für ein Kernfenster oder für die Komposition (XAML-Interop) erstellen, anstatt eine Swap-Kette für eine HWND zu erstellen.
Geräteressourcen und Ressourcenansichten
Direct3D 11 unterstützt eine zusätzliche Ebene der Polymorphie von Videospeicherressourcen, die als Ansichten bezeichnet werden. Wo Sie in Direct3D 9 ein einzelnes Objekt für eine Textur hatten, haben Sie jetzt zwei Objekte: die Textur-Ressource, die die Daten enthält, und die Ressourcenansicht, die angibt, wie die Ansicht zum Rendern verwendet wird. Eine auf einer Ressource basierende Ansicht ermöglicht die Verwendung dieser Ressource für einen bestimmten Zweck. Zum Beispiel wird eine 2D-Textur-Ressource als ID3D11Texture2D erstellt, dann wird eine Shader-Ressourcenansicht (ID3D11ShaderResourceView) auf ihr erstellt, damit sie als Textur in einem Shader verwendet werden kann. Eine Rendering-Zielansicht (ID3D11RenderTargetView) kann auch auf derselben 2D-Texturressource erstellt werden, so dass sie als Zeichenfläche verwendet werden kann. In einem anderen Beispiel werden dieselben Pixeldaten in zwei verschiedenen Pixelformaten dargestellt, indem zwei verschiedene Ansichten auf eine einzige Texturressource verwendet werden.
Die zugrunde liegende Ressource muss mit Eigenschaften erstellt werden, die mit der Art der Ansichten, die daraus erstellt werden, kompatibel sind. Wenn zum Beispiel eine ID3D11RenderTargetView auf eine Oberfläche angewendet wird, wird diese Oberfläche mit dem D3D11_BIND_RENDER_TARGET Flag erstellt. Die Oberfläche muss außerdem ein DXGI-Oberflächenformat haben, das mit dem Rendering kompatibel ist (siehe DXGI_FORMAT).
Die meisten Ressourcen, die Sie zum Rendern verwenden, erben von der Schnittstelle ID3D11Resource, die von ID3D11DeviceChild erbt. Vertex-Puffer, Index-Puffer, Konstanten-Puffer und Shader sind alles Direct3D 11-Ressourcen. Eingangslayouts und Sampler-Status erben direkt von ID3D11DeviceChild.
Ressourcenansichten verwenden einen DXGI_FORMAT-Enum-Wert, um das Pixelformat anzugeben. Nicht jedes D3DFMT wird als DXGI_FORMAT unterstützt. So gibt es zum Beispiel kein 24bpp-RGB-Format in DXGI, das D3DFMT_R8G8B8 entspricht. Es gibt auch nicht für jedes RGB-Format BGR-Äquivalente (DXGI_FORMAT_R10G10B10A2_UNORM ist äquivalent zu D3DFMT_A2B10G10R10, aber es gibt keine direkte Entsprechung zu D3DFMT_A2R10G10B10). Sie sollten planen, Inhalte in diesen Legacy-Formaten zum Zeitpunkt der Erstellung in unterstützte Formate zu konvertieren. Eine vollständige Liste der DXGI-Formate ist in der Aufzählung DXGI_FORMAT zu finden.
Direct3D-Geräteressourcen (und Ressourcenansichten) werden erstellt, bevor die Szene gerendert wird. Gerätekontexte werden zum Einrichten der Rendering-Kette verwendet, wie unten erläutert.
Gerätekontext und die Rendering-Kette
In Direct3D 9 und Direct3D 10.x gab es ein einziges Direct3D-Geräteobjekt, das die Erstellung von Ressourcen, den Status und das Zeichnen verwaltete. In Direct3D 11 verwaltet die Direct3D-Geräteschnittstelle immer noch die Ressourcenerstellung, aber alle Status- und Zeichenoperationen werden über einen Direct3D-Gerätekontext abgewickelt. Hier ist ein Beispiel dafür, wie der Gerätekontext (ID3D11DeviceContext1 Interface) verwendet wird, um die Rendering-Kette einzurichten:
- Festlegen und Löschen von Renderzielansichten (und Tiefenschablonenansicht)
- Legen Sie den Scheitelpunktpuffer, den Indexpuffer und das Eingabe-Layout für die Eingabe-Assembler-Stufe (IA-Stufe) fest
- Binden von Vertex- und Pixel-Shadern an die Pipeline
- Binden von konstanten Puffern an Shader
- Binden von Texturansichten und Samplern an den Pixel-Shader
- Zeichnen Sie die Szene
Wenn eine der Methoden ID3D11DeviceContext::Draw aufgerufen wird, wird die Szene auf der Rendering-Zielansicht gezeichnet. Wenn Sie mit dem Zeichnen fertig sind, wird der DXGI-Adapter verwendet, um den fertigen Rahmen zu präsentieren, indem Sie IDXGISwapChain1::Present1 aufrufen.
Zustandsverwaltung
Direct3D 9 verwaltet die Statuseinstellungen mit einer großen Anzahl von individuellen Umschaltern, die mit den Methoden SetRenderState, SetSamplerState und SetTextureStageState gesetzt werden. Da Direct3D 11 die alte Pipeline mit festen Funktionen nicht unterstützt, wird SetTextureStageState durch das Schreiben von Pixel-Shadern (PS) ersetzt. Es gibt keine Entsprechung zu einem Direct3D 9-Statusblock. Direct3D 11 verwaltet stattdessen den Zustand durch die Verwendung von 4 Arten von Zustandsobjekten, die eine schlankere Art und Weise zu gruppieren den Rendering-Status bieten.
Anstatt SetRenderState mit D3DRS_ZENABLE zu verwenden, erstellen Sie beispielsweise ein DepthStencilState-Objekt mit diesen und anderen zugehörigen Statuseinstellungen und verwenden es, um den Status während des Renderns zu ändern.
Bei der Portierung von Direct3D 9-Anwendungen auf Zustandsobjekte ist zu beachten, dass die verschiedenen Zustandskombinationen als unveränderliche Zustandsobjekte dargestellt werden. Sie sollten einmal erstellt werden und so lange verwendet werden, wie sie gültig sind.
Direct3D-Featureebenen
Direct3D verfügt über einen neuen Mechanismus zur Bestimmung der Hardwareunterstützung, die so genannten Feature Levels. Feature-Levels vereinfachen die Aufgabe, herauszufinden, was die Grafikkarte leisten kann, indem sie es Ihnen ermöglichen, einen genau definierten Satz von GPU-Funktionen anzufordern. Beispielsweise implementiert die Funktionsstufe 9_1 die von Direct3D 9-Grafikadaptern bereitgestellten Funktionen, einschließlich Shader Model 2.x. Da es sich bei 9_1 um die niedrigste Funktionsstufe handelt, können Sie davon ausgehen, dass alle Geräte einen Vertex-Shader und einen Pixel-Shader unterstützen, also die gleichen Stufen, die auch vom programmierbaren Shader-Modell von Direct3D 9 unterstützt wurden.
Ihr Spiel wird D3D11CreateDevice verwenden, um das Direct3D-Gerät und den Gerätekontext zu erstellen. Wenn Sie diese Funktion aufrufen, geben Sie eine Liste von Funktionsstufen an, die Ihr Spiel unterstützen kann. Es wird die höchste unterstützte Funktionsebene aus dieser Liste zurückgegeben. Wenn Ihr Spiel beispielsweise BC4/BC5-Texturen verwenden kann (ein Merkmal von DirectX 10-Hardware), würden Sie mindestens 9_1 und 10_0 in die Liste der unterstützten Funktionsstufen aufnehmen. Wenn das Spiel auf DirectX 9-Hardware läuft und BC4/BC5-Texturen nicht verwendet werden können, dann gibt D3D11CreateDevice 9_1 zurück. Dann kann Ihr Spiel auf ein anderes Texturformat (und kleinere Texturen) zurückgreifen.
Wenn Sie sich entscheiden, Ihr Direct3D 9-Spiel zu erweitern, um höhere Direct3D-Feature-Levels zu unterstützen, ist es besser, die Portierung Ihres vorhandenen Direct3D 9-Grafikcodes zuerst zu beenden. Nachdem Sie Ihr Spiel in Direct3D 11 zum Laufen gebracht haben, ist es einfacher, zusätzliche Rendering-Pfade mit verbesserten Grafiken hinzuzufügen.
Eine ausführliche Erläuterung der Feature-Level-Unterstützung finden Sie unter Direct3D feature levels. Unter Direct3D 11 Features und Direct3D 11.1 Features finden Sie eine vollständige Liste der Direct3D 11 Features.
Funktionsstufen und die programmierbare Pipeline
Die Hardware hat sich seit Direct3D 9 weiterentwickelt, und der programmierbaren Grafikpipeline wurden mehrere neue optionale Stufen hinzugefügt. Die Optionen, die Sie für die Grafikpipeline haben, variieren mit dem Direct3D-Feature-Level. Feature-Level 10.0 umfasst die Geometrie-Shader-Stufe mit optionalem Stream-Out für Multipass-Rendering auf der GPU. Feature-Level 11_0 enthält den Hull-Shader und den Domain-Shader für die Verwendung mit Hardware-Tessellation. Die Funktionsstufe 11_0 bietet außerdem volle Unterstützung für DirectCompute-Shader, während die Funktionsstufen 10.x nur eine eingeschränkte Form von DirectCompute unterstützen.
Alle Shader werden in HLSL geschrieben und verwenden ein Shader-Profil, das einem Direct3D-Feature-Level entspricht. Shader-Profile sind aufwärtskompatibel, so dass ein HLSL-Shader, der mit vs_4_0_level_9_1 oder ps_4_0_level_9_1 kompiliert wird, auf allen Geräten funktioniert. Shader-Profile sind nicht abwärtskompatibel, so dass ein mit vs_4_1 kompilierter Shader nur auf Geräten der Funktionsstufen 10_1, 11_0 oder 11_1 funktioniert.
Direct3D 9 verwaltete Konstanten für Shader unter Verwendung eines gemeinsamen Arrays mit SetVertexShaderConstant und SetPixelShaderConstant. Direct3D 11 verwendet konstante Puffer, die Ressourcen wie ein Vertex-Puffer oder Index-Puffer sind. Konstante Puffer sind so konzipiert, dass sie effizient aktualisiert werden können. Anstatt alle Shader-Konstanten in einem einzigen globalen Array zu organisieren, organisieren Sie Ihre Konstanten in logischen Gruppen und verwalten sie über einen oder mehrere Konstantenpuffer. Wenn Sie Ihr Direct3D 9 Spiel auf Direct3D 11 portieren, planen Sie, Ihre konstanten Puffer so zu organisieren, dass Sie sie entsprechend aktualisieren können. Gruppieren Sie zum Beispiel Shader-Konstanten, die nicht bei jedem Frame aktualisiert werden, in einem separaten Konstantenpuffer, damit Sie diese Daten nicht ständig zusammen mit den dynamischeren Shader-Konstanten in den Grafikadapter hochladen müssen.
Hinweis Die meisten Direct3D 9-Anwendungen nutzten Shader in großem Umfang, mischten aber gelegentlich auch das alte Verhalten mit festen Funktionen. Beachten Sie, dass Direct3D 11 nur ein programmierbares Schattierungsmodell verwendet. Die veralteten Funktionen von Direct3D 9 sind veraltet.