Asynchrone Programmierung (DirectX und C++)Asynchronous programming (DirectX and C++)

In diesem Thema werden verschiedene Aspekte behandelt, die Sie beim Verwenden der asynchronen Programmierung und des Threadings mit DirectX berücksichtigen sollten.This topic covers various points to consider when you are using asynchronous programming and threading with DirectX.

Asynchrone Programmierung und DirectXAsync programming and DirectX

Wenn Sie gerade erste Erfahrungen mit DirectX sammeln oder wenn Sie sogar bereits mit DirectX vertraut sind, sollten Sie Ihre gesamte Grafikverarbeitungspipeline in einen Thread einfügen.If you're just learning about DirectX, or even if you're experienced with it, consider putting all your graphics processing pipeline on one thread. In jeder beliebigen Szene eines Spiels gibt es allgemeine Ressourcen wie Bitmaps, Shader und andere Objekte, die einen exklusiven Zugriff erfordern.In any given scene in a game, there are common resources such as bitmaps, shaders, and other assets that require exclusive access. Genau für diese Ressourcen müssen Sie den Zugriff über parallele Threads hinweg synchronisieren.These same resources require that you synchronize any access to these resources across the parallel threads. Es ist schwierig, das Rendering über mehrere Threads zu parallelisieren.Rendering is a difficult process to parallelize across multiple threads.

Wenn Ihr Spiel ausreichend komplex ist oder Sie die Leistung verbessern möchten, können Sie mithilfe der asynchronen Programmierung einige der Komponenten parallelisieren, die nicht für Ihre Renderingpipeline spezifisch sind.However, if your game is sufficiently complex, or if you are looking to get improved performance, you can use asynchronous programming to parallelize some of the components that are not specific to your rendering pipeline. Moderne Hardware ist mit Hyperthreading-CPUs mit mehreren Kernen ausgestattet, und Ihre App sollte sich diese Leistungsmerkmale zu Nutze machen!Modern hardware features multiple core and hyperthreaded CPUs, and your app should take advantage of this! Sie können dies sicherstellen, indem Sie eine asynchrone Programmierung für einige der Komponenten Ihres Spiels verwenden, die keinen direkten Zugriff auf den Direct3D-Gerätekontext benötigen. Hierzu gehören:You can ensure this by using asynchronous programming for some of the components of your game that don't need direct access to the Direct3D device context, such as:

  • Datei-E/Afile I/O
  • Physische Effektephysics
  • Künstliche Intelligenz (KI)AI
  • Netzwerknetworking
  • Audioaudio
  • Steuerelementecontrols
  • XAML-basierte UI-KomponentenXAML-based UI components

Ihre App kann diese Komponenten in mehreren gleichzeitigen Threads verwalten.Your app can handle these components on multiple concurrent threads. Das asynchrone Laden wirkt sich positiv auf die Datei-E/A aus, insbesondere auf das Laden von Objekten, da Ihr Spiel oder Ihre App sich in einem interaktiven Zustand befinden kann, während mehrere (oder mehrere Hundert) Megabytes von Objekten geladen oder gestreamt werden.File I/O, especially asset loading, benefits greatly from asynchronous loading, because your game or app can be in an interactive state while several (or several hundred) megabytes of assets are being loaded or streamed. Es ist am einfachsten, diese Threads mit der Parallel Patterns Library (PPL) und dem task-Muster zu erstellen und zu verwalten, die in dem in der Datei „PPLTasks.h“ definierten concurrency-Namespace enthalten sind.The easiest way to create and manage these threads is by using the Parallel Patterns Library and the task pattern, as contained in the concurrency namespace defined in PPLTasks.h. Wenn Sie die Parallel Patterns Library verwenden, können Sie direkt von den Hyperthreading-CPUs mit mehreren Kernen profitieren und verschiedene Verbesserungen erzielen, z. B. durch verkürzte Ladezeiten oder weniger Störungen und Verzögerungen bei umfassenden CPU-Berechnungen oder Netzwerkverarbeitung.Using the Parallel Patterns Library takes direct advantage of multiple core and hyperthreaded CPUs, and can improve everything from perceived load times to the hitches and lags that come with intensive CPU calculations or network processing.

Beachten Sie    In einer universellen Windows-Plattform (UWP)-app, die Benutzeroberfläche, die vollständig in einem Singlethread-Apartment (STA) ausgeführt wird.Note   In a Universal Windows Platform (UWP) app, the user interface runs entirely in a single-threaded apartment (STA). Wenn Sie eine UI für Ihr DirectX-Spiel mit XAML-Interoperabilität erstellen, können Sie nur mithilfe von STA auf die Steuerelemente zugreifen.If you are creating a UI for your DirectX game using XAML interop, you can only access the controls by using the STA.

 

Multithreading mit Direct3D-GerätenMultithreading with Direct3D devices

Multithreading für Gerätekontexte ist nur verfügbar für Grafikgeräte, die eine Direct3D-Funktionsebene von 11 unterstützen_0 oder höher.Multithreading for device contexts is only available on graphics devices that support a Direct3D feature level of 11_0 or higher. Sie können jedoch die Nutzung des leistungsfähigen Grafikprozessors (GPU) auf vielen Plattformen maximieren, z. B. auf speziellen Gaming-Plattformen.However, you might want to maximize the use of the powerful GPU in many platforms, such as dedicated gaming platforms. Im einfachsten Fall möchten Sie vielleicht das Rendering einer HUD-Überlagerung (Heads-up-Display) vom Rendern der 3D-Szene trennen, sodass beide Komponenten separate parallele Pipelines verwenden.In the simplest case, you might want to separate the rendering of a heads-up display (HUD) overlay from the 3D scene rendering and projection and have both components use separate parallel pipelines. Beide Threads müssen jedoch dasselbe Singlethread-ID3D11DeviceContext-Element verwenden, um Ressourcenobjekte (Texturen, Gitter, Shader und andere Objekte) zu erstellen und zu verwalten. Dies erfordert, dass Sie für einen sicheren Zugriff eine Art von Synchronisierungsmechanismus implementieren (z. B. wichtige Abschnitte).Both threads must use the same ID3D11DeviceContext to create and manage the resource objects (the textures, meshes, shaders, and other assets), though, which is single-threaded, and which requires that you implement some sort of synchronization mechanism (such as critical sections) to access it safely. Sie können zwar separate Befehlslisten für den Gerätekontext in verschiedenen Threads (für verzögertes Rendering) erstellen, diese Befehlslisten aber nicht gleichzeitig in derselben ID3D11DeviceContext-Instanz wiedergeben.And, while you can create separate command lists for the device context on different threads (for deferred rendering), you cannot play those command lists back simultaneously on the same ID3D11DeviceContext instance.

Jetzt kann Ihre App zum Erstellen von Ressourcenobjekten auch das ID3D11Device-Element verwenden, das problemlos für Multithreading eingesetzt werden kann.Now, your app can also use ID3D11Device, which is safe for multithreading, to create resource objects. Warum also nicht immer ID3D11Device anstatt ID3D11DeviceContext verwenden?So, why not always use ID3D11Device instead of ID3D11DeviceContext? Nun, derzeit steht nicht für alle Grafikoberflächen eine Treiberunterstützung für Multithreading zur Verfügung.Well, currently, driver support for multithreading might not be available for some graphics interfaces. Sie können das Gerät abfragen und herausfinden, ob es Multithreading unterstützt. Wenn Sie aber die größtmögliche Zielgruppe erreichen möchten, sollten Sie das Singlethread-ID3D11DeviceContext-Element zur Verwaltung von Ressourcenobjekten verwenden.You can query the device and find out if it does support multithreading, but if you are looking to reach the broadest audience, you might stick with single-threaded ID3D11DeviceContext for resource object management. Wenn allerdings der Grafikgerätetreiber Multithreading oder Befehlslisten nicht unterstützt, versucht Direct3D 11, den synchronisierten Zugriff auf den Gerätekontext intern zu behandeln. Und wenn keine Befehlslisten unterstützt werden, wird eine Softwareimplementierung bereitgestellt.That said, when the graphics device driver doesn't support multithreading or command lists, Direct3D 11 attempts to handle synchronized access to the device context internally; and if command lists are not supported, it provides a software implementation. So können Sie Multithreadcode schreiben, der auf Plattformen mit Grafikoberflächen ausgeführt wird, die keine Treiberunterstützung für den Zugriff auf Multithread-Gerätekontexte bieten.As a result, you can write multithreaded code that will run on platforms with graphics interfaces that lack driver support for multithreaded device context access.

Wenn Ihre App separate Threads für die Verarbeitung von Befehlslisten und zum Anzeigen von Frames unterstützt, möchten Sie wahrscheinlich, dass der Grafikprozessor (GPU) aktiv bleibt. Er soll die Befehlslisten verarbeiten und gleichzeitig Frames zeitnah ohne Störungen oder Verzögerungen anzeigen.If your app supports separate threads for processing command lists and for displaying frames, you probably want to keep the GPU active, processing the command lists while displaying frames in a timely fashion without perceptible stutter or lag. In diesem Fall können Sie eine Separate ID3D11DeviceContext für jeden Thread, und klicken Sie zum Freigeben von Ressourcen (z. B. Texturen), indem sie mit der D3D11 erstellen_Ressource_Verschiedenes _SHARED-Flag.In this case, you could use a separate ID3D11DeviceContext for each thread, and to share resources (like textures) by creating them with the D3D11_RESOURCE_MISC_SHARED flag. In diesem Szenario muss ID3D11DeviceContext::Flush für den Verarbeitungsthread aufgerufen werden, um die Ausführung der Befehlsliste abzuschließen, bevor die Ergebnisse der Ressourcenobjektverarbeitung im Anzeigethread angezeigt werden.In this scenario, ID3D11DeviceContext::Flush must be called on the processing thread to complete the execution of the command list prior to displaying the results of processing the resource object in the display thread.

Verzögertes RenderingDeferred rendering

Beim verzögerten Rendering werden Grafikbefehle in einer Befehlsliste aufgezeichnet, damit sie zu einem anderen Zeitpunkt ausgeführt werden können. Hierbei wird das Rendering in einem Thread ausgeführt, während die Aufzeichnung der Befehle zum Rendern in zusätzlichen Threads erfolgt.Deferred rendering records graphics commands in a command list so that they can be played back at some other time, and is designed to support rendering on one thread while recording commands for rendering on additional threads. Nachdem diese Befehle abgeschlossen wurden, können sie in dem Thread ausgeführt werden, der das endgültige Anzeigeobjekt (Framepuffer, Textur oder andere Grafikausgabe) generiert.After these commands are completed, they can be executed on the thread that generates the final display object (frame buffer, texture, or other graphics output).

Erstellen Sie mit ID3D11Device::CreateDeferredContext einen Kontext für verzögertes Rendering (anstatt mit D3D11CreateDevice oder D3D11CreateDeviceAndSwapChain, die einen Kontext für das sofortige Rendering erstellen).Create a deferred context using ID3D11Device::CreateDeferredContext (instead of D3D11CreateDevice or D3D11CreateDeviceAndSwapChain, which create an immediate context). Weitere Informationen finden Sie im Thema zum Sofortigen und verzögerten Rendering.For more info, see Immediate and Deferred Rendering.