© istockphoto.com/pxhidalgo
Teil 1: Eine erste Erkundungstour

Besuch auf dem Vulkan


Anfang nächsten Jahres steht für alle Grafikprogrammierer ein großes Jubiläum an: 25 Jahre OpenGL. Für ein Grafik-API ist das ein ganz schön stolzes Alter. So verwundert es denn auch nicht, dass die Rufe nach einem plattformübergreifenden Nachfolger in den letzten Jahren immer lauter wurden – Rufe nach einem schicken, schlanken API, ohne überflüssigen Ballast, mit dessen Hilfe sich moderne Multi-Core-CPUs und leistungsfähige Grafikkarten bis an ihre Grenzen ausreizen lassen. Mit dem Ziel, die Funktionsweise des neuen Vulkan-API besser nachvollziehen zu können, werden wir uns im ersten Teil dieser Artikelserie zunächst einmal auf eine kleine Erkundungstour begeben.

Mit einer „Hallo-Welt-Anwendung“ fängt normalerweise alles an. Um niemanden zu überfordern, versucht man auf möglichst einfache Weise zu demonstrieren, welche Anweisungen und Bestandteile für ein voll funktionsfähiges Programm erforderlich sind. Auch beim Kennenlernen eines neuen Grafik-API wie OpenGL drehte sich in der Vergangenheit zunächst alles um die Ausgabe einer kurzen Begrüßungsbotschaft, um das grafische Äquivalent der berühmten zwei Wörter „Hello World!“, um die Darstellung einer schlichten ein- oder mehrfarbigen Dreiecksfläche. Verzichtet man beispielsweise auf Animationen und Texturen, so besteht ein mithilfe der GLUT-Library (OpenGL Utility Toolkit) erstelltes OpenGL-Programm in der Tat nur aus wenigen Zeilen Sourcecode.

Nun ja, so einfach wie früher ist die Welt inzwischen nicht mehr. Selbst das denkbar einfachste Programm, das auf die modernen OpenGL-Spezifikationen 3.3 bzw. 4.x setzt oder gar das neue Vulkan- oder Direct3D-12-API verwendet, kann aufgrund seiner Komplexität nicht mehr guten Gewissens als Hallo-Welt-Anwendung bezeichnet werden.

Was die Wahl des zu verwendenden Grafik-API betraf, war die Entscheidung der Spieleentwickler vor dem Einsetzen des Smartphone- und Tabletbooms mehr als nur eindeutig: Keine Frage, man entschied sich für DirectX und schenkte OpenGL keinerlei Beachtung. Erst als es immer wichtiger wurde, Spiele und anderweitige Grafikanwendungen für so viele Endgeräte wie möglich zu entwickeln, rückte OpenGL (ES) immer stärker in den Fokus der Entwickler. Wie aber sieht jetzt die Zukunft aus? Sollte man OpenGL den Rücken kehren, nun, da das neue Vulkan-API endlich verfügbar ist? Wenn man mit der Performance seiner OpenGL-Anwendungen zufrieden ist, gibt es eigentlich keinen Grund dazu. Aber selbst wenn im Rahmen eines laufenden Projekts aktuell noch kein Einsatz von Vulkan erforderlich ist, sollte man bereits jetzt an die Zukunft denken, seinen inneren Schweinehund überwinden (Programmierer gelten ja bekanntlich von Natur aus als faul-schlau) und sich in das neue API einarbeiten – wohl wissend, dass die Entwicklung eines auf Vulkan basierenden Frameworks eine richtig zeitintensive Angelegenheit werden wird.

Die Tatsache, dass man mithilfe von OpenGL beeindruckende dreidimensionale Welten in Echtzeit darstellen kann, ändert nichts daran, dass es sich im Kern um ein völlig veraltetes API handelt. Seinerzeit wurde OpenGL als globaler Zustandsautomat (Global State Machine) entworfen. Anfang der 1990er-Jahre (im Januar 1992 wurde die OpenGL-Spezifikation 1.0 veröffentlicht) ergab dieses Design durchaus Sinn. Um Dinge wie Multi-Threaded-Rendering musste man sich damals keine Gedanken machen, da es weder Mehrkernprozessoren noch leistungsfähige Grafikkarten gab. Da Änderungen in der Grafikpipeline – wie beispielsweise eine Modifikation der Vertexfarbe – einen nicht zu unterschätzenden Rechenaufwand bedeuteten, war es nur folgerichtig, die Werte sämtlicher Parameter so lange beizubehalten, bis seitens des Hauptprogramms eine Änderung erfolgte. Allerdings lässt sich ein globaler Zustandsautomat wie OpenGL nur sehr schlecht in eine auf Multi-Threading ausgelegte Anwendung integrieren; es sei denn, man beschränkt den API-Einsatz auf einen einzigen Renderingthread.

Vulkan – anfängerfreundlich oder nur etwas für Profis?

Für welchen Entwicklertyp ist das neue Vulkan-API nun eigentlich entworfen worden? Soll OpenGL durch Vulkan ersetzt werden oder ist eine langfristige friedliche Koexistenz angedacht? Wäre es sinnvoll, zunächst einmal OpenGL zu erlernen?

Das sind nur einige der Fragen, mit denen sich insbesondere Neulinge auf dem Gebiet der Grafikprogrammierung in diesen Tagen herumschlagen dürften. Eines ist sicher: Vulkan ist in erster Linie für Entwickler gedacht, die ein Maximum an Leistung aus ihren Grafikanwendungen herauskitzeln möchten. Aber diese Tatsache bedeutet natürlich nicht zwangsläufig, dass man sich als Neuling besser erst einmal mit OpenGL beschäftigen sollte. Genau genommen spielt das tatsächlich verwendete API – wenn überhaupt – nur eine untergeordnete Rolle, da die Entwicklung einer Grafikanwendung im Prinzip immer nach demselben Schema erfolgt: Man erstellt eine mehr oder weniger große Anzahl von Shader-Programmen für die Animation, Beleuchtung und Darstellung der virtuellen (Spiele-)Welt und speichert alle hierfür erforderlichen Daten in diversen Texture-, Texture-Array- sowie Buffer-Objekten ab.

Bereits mit OpenGL vertraute Programmierer sind beim Erlernen des neuen Vulkan-API natürlich klar im Vorteil, da sich bei der Shader-Programmierung nach wie vor die OpenGL Shading Language (GLSL) einsetzen lässt. Und wer bereits unter OpenGL mit Vertex-, Index-, Uniform-, Texel- (bzw. Texture-) oder Shader-Storage-Buffern gearbeitet hat, der wird erleichtert sein, dass sich im Rahmen einer Vulkan-Anwendung genau die gleichen Buffertypen verwenden lassen. Zugegeben, es dauert einige Zeit, bis man sich in ein Low-Level-API wie Vulkan eingearbeitet hat. Eine bessere Kontrolle über das Ressourcen- und Speichermanagement oder die Implementierung mehrerer Renderingthreads erfordert nun einmal einiges an Mehraufwand. Aber bekanntlich hat ja jede Medaille immer zwei Seiten: Man muss zwar ein wenig mehr Zeit investieren, im Gegenzug entwickelt man jedoch ein besseres Verständnis von den einzelnen Programmabläufen und der Funktionsweise eines Grafik-API.

Ziehen wir ein erstes Zwischenfazit. Wer bereits mit den modernen OpenGL-Spezifikationen 3.3 oder 4.x vertraut ist, der sollte beim Umstieg auf Vulkan eigentlich keine größeren Probleme haben. Ob man sich nun als blutiger Anfänger in die moderne (!) OpenGL- oder lieber gleich in die Vulkan-Programmierung einarbeitet, sollte meiner Meinung nach keinen großen Unterschied machen, auch wenn Letzteres ein wenig mehr Zeit erfordert.

Erste Schritte bei der Initialisierung einer Vulkan-Anwendung

Ähnlich wie bei OpenGL handelt es sich bei Vulkan auch um ein in C implementiertes API. Anders als bei seinem Vorgänger fühlt man sich jedoch insbesondere in der Eingewöhnungsphase geradezu erschlagen von der großen Anzahl an unterschiedlichen Datentypen (Strukturen sowie Enums), die es bei praktisch allen Funktionsaufrufen zu berücksichtigen gilt. Während in einer OpenGL-Anwendung der Zugriff auf die jeweils verwendeten Objekte – hierzu zählen unter anderem Texturen, Buffer oder Shader – mithilfe von vorzeichenlosen 32-Bit-Ganzzahlen vom Typ GLuint (gleichbedeutend mit unsigned int) erfolgt, kommen in einer Vulkan-Anwendung zwei unterschiedliche Typen von Handles zum Einsatz:

  • Dispatchable Handles sind Zeigervariablen auf bestimmte Objekttypen (z. B. *VkInstance oder *VkDevice)

  • Bei Non-Dispatchable Handles handelt es sich hingegen lediglich um 64-Bit-Integervariablen vom Typ uint64_t (z. B. typedef uint64_t VkRenderPass)

Menschen machen Fehler – Programmierer leider auch! Allerdings sollte bei einer inkorrekten API-Benutzung nicht immer gleich der komplette Rechner abstürzen. Das Problem besteht jedoch darin, dass Vulkan in erster Linie auf Geschwindigkeit ausgelegt ist und der Grafikkartentreiber, anders als noch bei OpenGL, nun nicht mehr für die Überwachung der korrekten API-Benutzung verantwortlich ist. Diesbezügliche Fehler (so genannte „Validity Errors“) werden nicht mehr automatisch abgefangen; der Treiber macht nur noch, was ihm gesagt wird – auch wenn das in letzter Konsequenz zu einem Systemabsturz führt. Aber nur keine Sorge, in der Praxis lassen sich besagte Validity Errors sogar deutlich einfacher identifizieren und beheben, als dies im Rahmen der OpenGL-Programmentwicklung möglich ist. Mithilfe so genannter Validation und Debug Layer, die Bestandteil des LunarG Vulkan SDKs [3] sind, können wir die korrekte API-Benutzung im Verlauf der Projektentwicklung bei jedem Programmdurchlauf aufs Neue überprüfen und somit mögliche Fehler frühzeitig korrigieren.

Der erste Schritt bei der Vulkan-Programmentwicklung besteht nun in der Initialisierung eines VkInstance-Objekts mithilfe der Funktion vkCreateInstance(). Werden mehrere dieser Objekte initialisiert, so findet keinerlei Datenaustausch zwischen...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang