Kombinieren von XAML und DirectX

Entwicklerblog für Windows 8-Apps

Ein Einblick in die Entwicklung von Apps im Metro-Stil – präsentiert vom Windows 8-Entwicklerteam

Kombinieren von XAML und DirectX

  • Comments 0

Schon seit Beginn der Entwicklung von Windows 8 haben wir über Möglichkeiten nachgedacht, die Benutzeroberfläche (z. B. die umfangreichen Steuerelemente und Interaktionsmöglichkeiten durch XAML) und Grafik, (etwa das Hochleistungsrendering auf niedriger Ebene von DirectX) miteinander zu kombinieren.

Ihr Feedback aus den Entwicklungscenter-Foren und anderen Kanälen zur Developer Preview unterstützte uns dabei, den Schwerpunkt auf die zusammengehörigen Szenarien zu legen, die den Entwicklern am wichtigsten waren. Wir fanden verschiedene Gemeinsamkeiten: Viele von Ihnen wollten entweder DirectX-Grafikelemente mit dem, was normalerweise eine XAML-App wäre, kombinieren, oder einfach eine Benutzeroberfläche im Metro-Stil zu einer DirectX-App hinzufügen.

Wir haben gute Nachrichten für Sie! Mit Veröffentlichung der Consumer Preview muss nicht mehr kategorisch zwischen einer XAML-App und einer DirectX-App unterschieden werden. Jetzt können Sie mithilfe eines vertrauten XAML-Modells in derselben App zugleich von den Vorteilen von XAML als funktionsreicher Benutzeroberfläche und von DirectX als Hochleistungsrenderinglösung profitieren.

Mit dieser Kombination können Sie die Vorzüge beider Ansätze nutzen. Dadurch eröffnen sich zahlreiche Möglichkeiten. Einige der von Ihnen genannten Schlüsselszenarien bezogen sich beispielsweise auf:

  • Apps für Bildverarbeitung, Kreativität und Design, in denen Benutzeroberfläche und Grafik verschmelzen
  • Umfassende Karten- und Dokument-Viewer, bei denen sowohl sehr umfangreiche DirectX-Grafiken als auch Benutzeroberflächenelemente verwendet werden
  • Spiele und Simulationen mit Hochleistungs-DirectX-Grafik im Vollbildschirmmodus und einer darüber liegenden minimalen Benutzeroberfläche

In diesen Szenarien können Entwickler durch Kombination von XAML und DirectX produktiver umfangreiche und schnellere Apps entwickeln.

Benutzeroberflächen im Metro-Stil unter Windows 8

Ähnlich wie HTML/JavaScript ist XAML ein Toolkit für die Benutzeroberflächen für sämtliche App-Typen unter Windows 8. Es bietet Konstrukte für Interaktivität, Steuerelemente und Animationen im Metro-Stil und umfangreiche Funktionen wie Unterstützung für Barrierefreiheit, Datenbindung, Medien- und HTML-Hosting. Zudem profitieren Sie von der Entwurfszeitunterstützung in Visual Studio und Expression Blend und können dabei Programmiersprachen Ihrer Wahl verwenden.

Ein Aspekt, mit dem sich das Entwicklerteam ständig befasst und der XAML und HTML/JavaScript gleichermaßen betrifft, ist die Leistung: Für Windows 8 haben wir dafür große Anstrengungen unternommen, sodass Sie nun einfacher als je zuvor schnelle und flüssige Apps im Metro-Stil erstellen können. Speziell im Grafikbereich haben wir die Rendering- und Kompositionsleistung weiter verbessert. Wo immer die Möglichkeit bestand, haben wir GPU-Hardware verwendet und es sogar ermöglicht, verbreitete Typen von Animationen unabhängig aus dem Benutzeroberflächen-Thread auszuführen und so sicherzustellen, dass sie reibungslos ausgeführt werden – ganz gleich, welche weiteren Aufgaben die App in der CPU ausführt. Wir haben sichergestellt, dass die Frameworks der Benutzeroberfläche alle Aufgaben schnell, flüssig und mit verringertem Energiebedarf ausführen. Wenn Sie ein Benutzeroberflächen-Framework verwenden, nutzen Sie im Hintergrund bereits die Leistung von DirectX. In vielen Fällen können Sie damit bereits eine hervorragende Grafikleistung erzielen.

DirectX unter Windows 8

Dennoch gibt es selbstverständlich Gelegenheiten, wo Sie die volle Rendering-Leistung im unmittelbaren Modus und den direkten Zugriff auf Grafikgeräte benötigen, die DirectX bietet. Von Windows 8 an sind DirectX SDK-Komponenten Teil des primären Windows-SDK. Außerdem enthält DirectX nun eine Auswahl neuer Funktionen, wie eine einheitliche 3D-API, verbesserte 2D-Grafik- und Textdarstellung mit Direct2D, eine gut ausgestattete Bildverarbeitungs-Pipeline und verbesserte Druckunterstützung.

Unter Windows 8 wurden alle Komponenten für DirectX optimiert und darauf abgestimmt: die Entwicklerplattformen, das Betriebssystem und das Hardwaredesign. So können Sie mit DirectX unter Windows 8 Höchstleistungs-Rendering ermöglichen. Der größte Nachteil dabei ist, dass das Erstellen und Verwalten von reinen DirectX-Lösungen recht komplex sein kann und Sie sie in C++ implementieren müssen (es sei denn, Sie verwenden einen Drittanbieterwrapper).

Hier kommt die Interoperabilität von DirectX und XAML ins Spiel: Sie können jetzt C#, Visual Basic oder C++ verwenden, um Ihre XAML-Benutzeroberfläche zu konstruieren und C++-DirectX-Komponenten einbinden. Wenn HTML/JavaScript und DirectX für Sie interessant ist: Wie zuvor erwähnt, haben wir viel getan, um die Vorteile von DirectX in die Benutzeroberflächenplattformen zu integrieren. In Bezug auf die Kombination von Benutzeroberfläche und nativer DirectX-Grafik haben wir uns für Windows 8 jedoch auf XAML konzentriert.

Entwurfsziele

Unter Beachtung der eben genannten Fakten entwickelten wir verschiedene Hauptziele, die wir durch Kombination von DirectX und XAML erreichen wollten:

1. Leistung

  • Unterstützung von Eingaben mit geringer Latenz und Interaktivität
  • Ermöglichen von inkrementellem Neuzeichnen sowohl von XAML- als auch von DirectX-Inhalten
  • Minimierung des Nutzungsaufwands von XAML

Wir wollten vor allem vermeiden, eine „XAML-Steuer“ zu erheben: Wenn Ihre App hauptsächlich aus DirectX-Komponenten besteht, sollte die Benutzeroberfläche im Metro-Stil mithilfe von XAML problemlos zu realisieren sein. Wir wissen, dass das nicht für Sie von Bedeutung ist: Wir wollten dazu beitragen, dass Ihre Kunden durch Ihre App in den Genuss ausgezeichneter Leistung und langer Akkulebensdauer kommen.

2. Flexibilität

  • Aktivieren der vollen Funktionalität von sowohl XAML als auch DirectX 11

Im Ergebnis können Sie nun eine XAML-Schnittstelle in Blend und Visual Studio entwerfen und ausarbeiten und sie mit beliebigen DirectX-Inhalten kombinieren. Wir wollten keinesfalls die Leistung von XAML und DirectX einschränken, sondern Ihnen die Möglichkeit eröffnen, sie zu kombinieren.

3. Integration

  • Sicherstellen der reibungslosen Integration von XAML und DirectX

Sie können DirectX-Grafiken und XAML-Benutzeroberflächen unter Verwendung vertrauter XAML-Konzepte in einer einzigen App kombinieren.

Nachdem wir die bereits aufgelisteten Szenarien analysierten, konnten wir diese in drei grobe Kategorien aufteilen:

  1. Einbettung kleiner DirectX-Komponenten in eine hauptsächlich mit XAML konstruierte Benutzeroberfläche
  2. Kombination großer skalierbarer DirectX-Oberflächen mit einer XAML-Benutzeroberfläche
  3. Überlagerung einer DirectX-dominierten App mit einer XAML-Benutzeroberfläche im Metro-Stil

Letztlich kamen wir zu dem Ergebnis, dass es keine Universallösung für all diese Kategorien gab. Stattdessen fügten wir drei XAML-Typen hinzu, von denen jeder für eine dieser Hauptkategorien optimiert ist. Unserer Meinung nach bietet Ihnen dieser Ansatz die Flexibilität, die für die Erfordernisse Ihrer App optimalen Optionen auswählen zu können. Diese Optionen schließen sich nicht gegenseitig aus. Sie können für verschiedene Komponenten in derselben App sogar alle drei verwenden.

Szenario 1 – SurfaceImageSource: einzelne DirectX-Komponenten auf einer XAML-Benutzeroberfläche

Als erste Möglichkeit zur Kombination von DirectX und XAML können Sie mithilfe des neuen XAML-Typs SurfaceImageSource Bereiche mit DirectX-Inhalten in eine XAML-App im Metro-Stil einfügen. Eine Instanz dieses Typs stellt Ihnen eine freigegebene DirectX-Oberfläche zur Verfügung, auf der Sie mithilfe der gesamten DirectX-Funktionalität aufbauen können. Dann wird die Oberfläche in die übrige Schnittstelle Ihrer XAML-App eingebettet.

Diese Option ist besonders dann nützlich, wenn Sie DirectX zum Erstellen spezifischer Komponenten verwenden möchten, die Teil einer größeren XAML-Benutzeroberfläche sind. Sie könnten z. B. mithilfe von SurfaceImageSource komplexe Bildeffekte auf ein Foto anwenden oder Hochleistungsvisualisierungen von 3D-Daten produzieren.

Wenn Sie bereits einmal eine XAML-ImageSource verwendet haben, sind Sie mit der Anwendung bereits recht vertraut: Sie können eine SurfaceImageSource als Quelle eines ImageBrush festlegen, um nahezu alle XAML-Elemente zu zeichnen – Pinsel sind wiederverwendbar! Sie können z. B. mithilfe einer SurfaceImageSource ein XAML-Rechteck füllen:

SurfaceImageSource^ surfaceImageSource =  
ref new SurfaceImageSource(rectangle1->Width, rectangle1->Height, true);
ImageBrush^ brush = ref new ImageBrush();
brush->ImageSource = surfaceImageSource;
rectangle1->Fill = brush;

Anschließend können Sie mit DirectX die Inhalte des Rechtecks zeichnen und es ganz nach Bedarf aktualisieren. Das Beste daran ist, dass diese Oberfläche nahtlos in das XAML-Kompositionsmodell integriert ist: Eigenschaften, die auf dieses Rechteck angewendet werden, wirken sich auch auf die Inhalte aus, die Sie mit DirectX zeichnen. Sie können in XAML problemlos Elemente sich überlagern lassen und Rendering-Übergänge, Projektionen, Z-Indizes oder Opazität anwenden, ganz ohne die Airspace-Probleme, die beim Verwenden verschiedener Rendering-Technologien häufig auftreten:

Grafische Darstellung einer XAML-App, die eine DirectX-Oberfläche mit XAML-Inhalten verbindet Die DirectX-Oberfläche wird gedreht und mit anderen XAML-Inhalten zusammengesetzt, die dann über die Oberfläche gelegt werden.

Rechteckige DirectX-Oberfläche zusammengesetzt mit XAML-Inhalten

Dieses Konzept ähnelt dem D3DImage-Typ in WPF. Wir haben uns jedoch mit Ihrem Feedback zu D3DImage auseinandergesetzt und SurfaceImageSource noch leistungsstärker und benutzerfreundlicher gemacht. Was SurfaceImageSourcebesonders auszeichnet: Es unterstützt DirectX, einschließlich Direct2D. Es hebt viele Einschränkungen von D2DImage auf (beispielsweise funktioniert SurfaceImageSource jetzt auch über eine Remotedesktopverbindung). Es verbessert die Leistung und kann Oberflächen für Sie verwalten – Schluss mit dem Sperren und Entsperren oder dem manuellen Erstellen und Verwalten von Puffern! Eine SurfaceImageSource kann sogar Oberflächen unterstützen, die größer als die maximale Texturgröße Ihres Direct3D-Geräts sind.

Das Auffälligste beim Erstellen einer SurfaceImageSource ist möglicherweise, dass auf den ersten Blick gar keine neuen Methoden verfügbar gemacht werden. Tatsächlich wird die Implementierung mittels einer angefügten systemeigenen Schnittstelle verfügbar gemacht. Das ist nötig, um direkt auf DirectX-APIs verweisen zu können, die nur in C++ verfügbar sind. Das bedeutet, dass Sie DirectX-Apis mithilfe von C++ aufrufen müssen, entweder direkt in einer C++-XAML-App oder in einer separaten C++-WinRT-Komponente, die Sie in jede beliebige C#- oder Visual Basic-App einfügen können. Nachdem Sie die notwendige Headerdatei eingefügt haben:

#include "windows.ui.xaml.media.dxinterop.h"

Nun können Sie die ISurfaceImageSourceNative-Schnittstelle abfragen, mit der Sie auf die drei Methoden zugreifen können, mit denen Sie beginnen können:

interface ISurfaceImageSourceNative: IUnknown
{
SetDevice(IDXGIDevice *pDevice);
BeginDraw(
RECT updateRect,
IDXGISurface** pSurface,
POINT* offset
);

EndDraw();
};

BeginDraw() erfordert einen updateRect-Parameter, mit dem Sie den zu aktualisierenden Bereich einschränken können. So können Sie mit kleineren inkrementellen Updates der Oberfläche die Leistung verbessern. Die Methode gibt außerdem eine Oberfläche und einen Punkt zurück, der ein Offset angibt. Hier sollten Sie mit dem Zeichnen beginnen: Selbst wenn Sie die gesamte Oberfläche aktualisieren, sollten Sie dieses Offset berücksichtigen, denn Ihre Oberfläche könnte Teil einer größeren Oberfläche sein, die das Framework intern als Optimierung verwaltet. Von hier können Sie ein DXGI-Gerät erstellen und festlegen, und dann mit DirectX zu zeichnen anfangen! Im Entwicklungscenter finden Sie im Themenfeld zu DirectX- und XAML-Interoperabilität einen guten Überblick über die ausführlichen Details.

Szenario 2 – VirtualSurfaceImageSource: großmaßstäbige DirectX-Inhalte + XAML-Benutzeroberfläche

VirtualSurfaceImageSource erweitert SurfaceImageSource, um die Unterstützung sehr großer Oberflächen besser zu unterstützen. Die Fundamente dazu liegen im Konzept der Virtualisierung, also darin, Bereiche einer Oberfläche immer nur so weit zu zeichnen, wie sie auf dem Bildschirm sichtbar sind.

Dieser Typ wurde entwickelt, um komplexe Inhalte anzuzeigen, die größer als der Bildschirm sind, vor allem, wenn die Anzeige geschwenkt oder gezoomt werden kann. Entsprechende Szenarien sind z. B. Dokument-Viewer und Apps für medizinische Bildgebung – also Apps mit Inhalten, die wesentlich größer sein können als die maximale Auflösung eines durchschnittlichen Bildschirms. Ein weiteres gutes Beispiel wäre ein Kartensteuerelement: Mithilfe einer VirtualSurfaceImageSource können Sie mit DirectX eine große, vektorbasierte Karte implementieren und es dem System überlassen, den jeweils gerade auf dem Bildschirm angezeigten Bereich nachzuverfolgen. Sie können außerdem XAML-Elemente wie zum Beispiel Ortsmarken über die Karte legen und problemlos ihre Position mit den DirectX-Inhalten synchronisieren.

VirtualSurfaceImageSource verwendet Kacheln und ein Rückrufmodell zur Implementierung dieser Virtualisierung. Nachdem Sie Ihre VirtualSurfaceImageSource in voller Größe erzeugt haben, werden die DirectX-Inhalte im Hintergrund in eine Reihe rechteckiger Bereiche aufgeteilt. Das Framework verfolgt die sichtbaren Rechtecke zu jedem beliebigen Zeitpunkt automatisch (möglicherweise auch Rechtecke, die knapp außerhalb des Anzeigebereichs liegen, um ein reibungsloses Schwenken zu gewährleisten). Es aktiviert einen Rückruf, den Ihre App implementiert, um bei Bedarf die Inhalte für neu ins Sichtfeld kommende Bereiche bereitzustellen. Besonders gut funktioniert dies, wenn Sie Ihre VirtualSurfaceImageSource-Inhalte in einem ScrollViewer positionieren, um reibungsloses Schwenken mithilfe von Touchscreens oder Mausgeräten zu ermöglichen.

Eine große DirectX-Oberfläche, gerahmt von einem Bildschirm um den aktuell sichtbaren Bereich. Leere Bereiche außerhalb des Bildschirms stellen Teile der Oberfläche dar, die noch nicht gezeichnet wurden, da sie sich noch nicht im Anzeigebereich befinden.

Große Oberfläche, aufgeteilt in rechteckige Kacheln

Diese Herangehensweise ist nicht nur einfacher zu implementieren, als wenn Sie die Koordinaten selbst nachverfolgen: Sie kann auch die Leistung Ihrer App dramatisch verbessern. Da das System Ihre Inhalte intern zwischenspeichert, wird der Inhalt einer Region nach dem Zeichnen im Speicher beibehalten und von der GPU automatisch wiederverwendet – auch dann, wenn der Inhalt aus dem Anzeigebereich bewegt und wieder zurückbewegt wird. So ist kein Neuzeichnen erforderlich. Wenn ein bereits gezeichneter Bereich aktualisiert werden soll, rufen Sie einfach BeginDraw() auf, genau wie bei einer SurfaceImageSource. Eine weitere Leistungsoptimierung besteht darin, dass das System automatisch Speicherplatz wiederverwendet, der für alte Bereiche, die über einen bestimmten Punkt hinaus außer Sicht sind, verwendet wurde. So wird der Speicherplatzbedarf in Grenzen gehalten und eine hohe Leistung Ihrer App selbst bei sehr großen Oberflächen mit vielen verschiedenen Formularfaktoren und Hardwareprofilen gewährleistet. Dieser Leistungsvorteil zeigt sich besonders deutlich auf mobilen Geräten wie Tablets.

Ähnlich wie mit SurfaceImageSource können Sie die unterstützende systemeigene Schnittstelle abfragen, in diesem Fall IVirtualSurfaceImageSourceNative, um Zugriff auf die benötigten Methoden zu erhalten. Ausführliche Informationen finden Sie im Artikel über DirectX- und XAML-Interoperabilität im Entwicklungscenter, oder im Beispiel für eine Direct2D-Magazin-App.

Szenario 3 – SwapChainBackgroundPanel: DirectX mit einer XAML-Überlagerung

Die dritte und letzte Möglichkeit, XAML- und DirectX-Inhalte zu kombinieren, ist SwapChainBackgroundPanel, ein XAML-Element zur Entwicklung von Vollbild-Apps auf Grundlage von DirectX. Anders als SurfaceImageSource und VirtualSurfaceImageSource ist SwapChainBackgroundPanel eher ein XAML-Element als eine ImageSource. Es baut auf dem XAML-Layoutpanel Grid auf und ermöglicht Apps das Erstellen und vollständige Steuern einer Vollbild-DirectX-Swap-Chain, während alle weiteren XAML-Inhalte darüber gelegt werden:

Abbildung eines Kompositionsmodells von SwapChainBackgroundPanel, bei dem sich DirectX-Inhalte im Hintergrund eines XAML-Overlays befinden

Ein SwapChainBackgroundPanel befindet sich im Hintergrund von überlagerten XAML-Inhalten

Wir sind überzeugt, dass dies die beste Möglichkeit für Spiele und andere Apps ist, bei denen der Hauptteil der Grafik auf DirectX basiert. Sie können hervorragende Leistung erzielen und auf ein Update-Modell zurückgreifen, das beinahe einer reinen DirectX-App entspricht. Sie können gleichzeitig mithilfe von XAML eine „Heads-Up-Display“-Schnittstelle erstellen und sie per Datenbindung mit Ihrem Spielemodell verknüpfen, interaktive Steuerelemente hinzufügen und Elemente im Metro-Stil hinzufügen, z. B. AppBars.

Um dies zu erreichen, haben wir einige Beschränkungen für das SwapChainBackgroundPanel eingerichtet: Es muss das XAML-Stammelement Ihrer App sein. Einige geerbte XAML-Eigenschaften wie Opazität und RenderTransform haben darauf keinerlei Auswirkung mehr. (Selbstverständlich können Sie diese Effekte weiterhin erzielen, indem Sie die entsprechenden DirectX-Operationen auf den Swap-Chain-Inhalt anwenden.) Dies ermöglicht einen Kompromiss zwischen der nahtlosen Integration in das Kompositionsmodell des XAML-Frameworks, das mithilfe von SurfaceImageSource bereitgestellt wird, und der Interaktion mit der geringsten Latenz und zusätzlicher Kontrolle über die zeitliche Steuerung der Darstellung, die möglich sind, wenn Sie die Swap-Chain direkt verwalten.

Die unterstützende systemeigene Schnittstelle verfügt in diesem Fall nur über eine einzige Methode:

interface ISwapChainBackgroundPanelNative: IUnknown
{
SetSwapChain(IDXGISwapChain *pSwapChain);
};

Sie können mit der Darstellung Ihrer Inhalte beginnen, sobald Sie SetSwapChain() aufrufen, um Ihre Swap-Chain dem Panel zuzuordnen. SwapChainBackgroundPanel steht dann auch für Treffertests zur Verfügung. Eingaben werden mithilfe gewöhnlicher XAML-Eingabeereignisse behandelt. Alle untergeordneten XAML-Elemente, die Sie dem Panel hinzufügen, werden an der Spitze Ihrer Swap-Chain angezeigt.

Im Themenbereich Interoperabilität im Entwicklungscenter finden Sie weitere Informationen über die Verwendung des SwapChainBackgroundPanels, und es wird ein Quellbeispiel für einen DirectX-Shooter, der mithilfe von SwapChainBackgroundPanel entwickelt wurde und die durchgehende Implementierung eines Direct3D-Spiels mit einer XAML-Schnittstelle zeigt, bereitgestellt:

Screenshot eines DirectX- und XAML-Ego-Shooter-Spiels. Die DirectX-Oberfläche enthält Wände und Ziele, die von einer XAML-Benutzeroberfläche mit einem Menü und einer AppBar-Steuerung überlagert sind.

Ein mit DirectX und XAML entwickeltes Spiel

Zusammenfassung

Wir freuen uns über die neuen Möglichkeiten, die sich durch die Kombination der umfassenden Unterstützung von Benutzeroberflächen und der Entwurfszeitproduktivität von XAML mit den Vorteilen von DirectX-Hochleistungsgrafiken eröffnen. Wir hoffen, dass diese drei neuen Möglichkeiten, Apps im Metro-Stil zu erstellen, Sie bei der Entwicklung von begeisternden Apps für Ihre Kunden unterstützen.

– Jesse Bishop
    Programmanager, Windows

  • Loading...
Leave a Comment
  • Please add 8 and 2 and type the answer here:
  • Post