www.rolandk.de
- Aktuelle Themen zu .Net -
Achtung: Hier handelt es sich um meine alte Seite.
Die aktuelle ist unter folgendem Link erreichbar: www.rolandk.de/wp/
Home Artikel Grafikprogrammierung SlimDX Devices verwalten




















































SlimDX Devices verwalten
Dienstag, den 20. September 2011 um 19:41 Uhr

 

Allgemeines

Wer schon mit DirectX oder SlimDX gearbeitet hat, kennt das Problem. Über die verschiedenen Device-Klassen wird eine Verbindung zur Grafikhardware hergestellt, doch wo im Programmcode ist eigentlich der richtige Platz, diese Objekte zu verwalten? Zusätzlich kommt bei SlimDX erschwerend hinzu, dass man auch zwischen verschiedenen Versionen, also DirectX 11, 10.1, 10, 9, usw. unterscheiden kann. In diesem Artikel möchte ich eine einfache und elegante Variante vorstellen, wie dieses Problem relativ einfach und übersichtlich gelöst werden kann.

 

Der naheliegendste Ansatz

Das einfachste für den Anfang ist wohl, für die 3D-Ansicht ein UserControl zu schreiben, welches direkt als Member ein Device Objekt hält - von der jeweils präferierten DirectX Version. Beim Öffnen des UserControls (z. B. Load-Ereignis) wird das Device initialisiert und im Paint-Ereignis wird gerendert. Für den Fall, dass die Initialisierung fehlgeschlagen ist, kann ein Standard-Hintergrund über die Framework-Methoden gezeichnet werden. Nachfolgend ein Codeausschnitt, der dieser Vorgehen verdeutlichen soll.

  1. public class MyRenderPanel : UserControl
  2. {
  3. private D3D11.Device m_device;
  4. ...
  5. public override void OnLoad(EventArgs e)
  6. {
  7. //Initialize 3d view
  8. }
  9. ...
  10. public override void OnPaint(PaintEventArgs e)
  11. {
  12. //Rendering logic
  13. }
  14. ...
  15. }

Klingt einfach und das ist es im Prinzip auch. Probleme tauchen meist erst später auf, und zwar etwa bei folgenden Anforderungen:

  • Mehrere Ansichten auf eine 3D-Szene öffnen
  • DirectX-Ausgabe für WinForms- und für WPF-Steuerelemente verwenden
  • Direkte Interaktion mit Direct2D / DirectWrite in 3D-Ansicht
  • Device für andere Berechnungen ohne Grafikausgabe verwenden
  • ...

Was bleibt dabei am Ende übrig? Mehrere Device-Objekte (für jedes nötige Steuerelement eines)? Nicht gerade von Vorteil, da Ressourcen mehrfach erzeugt werden müssen, obwohl das gar nicht nötig ist.

 

Devices über gemeinsame Klasse verwalten

Wie weiter oben beschrieben, wäre eine andere Lösung eventuell sinnvoller. Die Grundidee ist folgende: Warum das Device oder die Devices nicht nur einmal erstellen, und überall im Programm nur dieses verwenden? Mit aktuellen DirectX Versionen spricht da überhaupt nichts dagegen - ganz im Gegenteil. Es empfiehlt sich sogar. Nebenbei sei erwähnt, dass es auch Sinn macht, in einer Anwendungen Devices von unterschiedlichen Direct3D Versionen parallel zu halten. Warum? Das Thema ist zwar etwas komplexer, aber man kann ein Device über einen Umweg auch in eine andere Direct3D-Version "casten" und damit deren jeweiligen Vorteile ausnutzen. Zusätzlich ist es unter bestimmten Voraussetzung möglich, über ein Direct3D 10.1 Device per Direct2D direkt auf eine Textur bzw. in die 3D-Ansicht zu zeichnen. Mehr will ich dazu an der Stelle nicht schreiben, wäre eigentlich ein Thema für einen anderen Artikel. Um wieder zurück zum Thema zu kommen, nachfolgend ein Beispiel, man sich so etwas vorstellen kann.

 

 

Die statische Klasse GraphicsCore ist für die Verwaltung aller Device-Objekte zuständig. Das Initialize wird dabei nur einmal etwa bei Programmstart aufgerufen - wird eine Exception geschmissen, so weiß man, dass 3D-Grafik nicht verwendet werden kann. Ist die Initialize Methode erfolgreich, so steht ab diesem Zeitpunkt von jeder Position im Programm aus jedes Device-Objekt zur freien Verfügung. Das einzige, worauf man aufpassen sollte, ist Threading. Dieses hier beschriebene Vorgehen ist eher dann sinnvoll, wenn man nur im Gui-Thread rendert und die Initialize-Methode auch im Gui-Thread aufruft. Grund: Objekte in DirectX sollten auch nur in dem Thread verwendet werden, der sie erzeugt hat. Klar, Ausnahmen gibt es da auch genug (vor allem in DirectX 11), aber im Allgemeinen sollte es so sein.

 

Zusammenfassung

Dieser Artikel gab einen Einblick darin, wie man Device-Objekte sinnvoll verwalten kann. Angehängt ist noch ein Beispielprogramm, welches das beschriebene Vorgehen weiter veranschaulicht. Selbstverständlich handelt es sich dabei - wie oft bei DirectX Themen - nicht um eine Ideallösung, sondern mehr um einen Vorschlag oder besser gesagt, einen Denkanstoß.

 

Siehe auch...

 

Kommentar hinzufügen

Ihr Name:
Kommentar: