Native und proprietäre Engines

Erste Schritte mit Vulkan unter Android

Vulkan ist die primäre Low-Level-Grafik-API auf Android. Vulkan bietet optimale Leistung für Spiele, die eine eigene Game-Engine und einen eigenen Renderer implementieren.

Damit Sie Vulkan in Ihre Spiele-Engine implementieren können, müssen Sie Folgendes tun:

  • Geeignete Android-Geräte für Vulkan ermitteln
  • Vor- und Nachteile der Unterstützung älterer Android-Geräte
  • Vulkan dem Android-Build-Ziel hinzufügen
  • Shader-Compiler zum Erstellen von SPIR-V für Vulkan auswählen
  • Verfügbare Vulkan API-Version zur Laufzeit ermitteln
  • Informationen zum Optimieren von Vulkan-Renderingvorgängen mit Vulkan-Profilen, Frame-Pacing und Vorrotation
  • Grafiktools für das Debugging und die Leistungsanalyse auswählen

Mindestgerätespezifikationen für Vulkan auswählen

Vulkan ist auf Android-Geräten ab Android 7.0 (API-Level 24) verfügbar. Nicht alle Android-Geräte mit Android 7.0 oder höher unterstützen Vulkan. Sie müssen festlegen, welche Vulkan-fähigen Android-Geräte Ihr Spiel unterstützt.

Empfehlungen

Die folgenden Spezifikationen sind die Mindestanforderungen für die Vulkan-Unterstützung:

  • Auf dem Gerät wird Android 10.0 (API-Level 29) oder höher ausgeführt.
  • Das Gerät unterstützt die Vulkan-API-Version 1.1 oder höher.
  • Das Gerät verfügt über Hardwarefunktionen und ‑merkmale, die mit dem Android-Baseline-Profil von 2022 kompatibel sind.

Unterstützung älterer Geräte

Wenn Ihr Spiel für eine Vielzahl von Geräten mit unterschiedlichen Grafikleistungsstufen entwickelt wurde, müssen Sie möglicherweise Geräte unterstützen, die älter sind als die in Mindestspezifikationen für Geräte für Vulkan auswählen empfohlenen. Bevor Sie Unterstützung für ältere Geräte entwickeln, sollten Sie prüfen, ob Vulkan Vorteile für Ihr Spiel bietet. Bei Spielen mit vielen Draw-Aufrufen, die OpenGL ES verwenden, kann es zu einem erheblichen Treiber-Overhead kommen, da Draw-Aufrufe in OpenGL ES sehr kostspielig sind. Diese Spiele können CPU-gebunden werden, da ein großer Teil der Frame-Time im Grafiktreiber verbracht wird. Durch den Wechsel von OpenGL ES zu Vulkan kann auch die CPU- und Stromnutzung von Spielen erheblich reduziert werden. Das ist besonders dann der Fall, wenn Ihr Spiel komplexe Szenen enthält, in denen Instanziierung nicht effektiv zur Reduzierung von Draw Calls eingesetzt werden kann. Wenn Sie ältere Geräte als Zielgruppe haben, sollten Sie OpenGL ES-Rendering als Fallback einbauen, da einige Geräte in Ihrer Liste der Zielgeräte möglicherweise Vulkan-Implementierungen haben, auf denen Ihr Spiel nicht zuverlässig ausgeführt werden kann.

Möglicherweise möchten Sie ältere Vulkan-fähige Geräte nicht unterstützen, da sie nicht leistungsstark genug sind, Funktionen fehlen oder Stabilitätsprobleme auftreten.

Leistung und Funktionen

Ältere Android-Geräte, die Vulkan unterstützen, haben möglicherweise nicht die Rendering-Leistung oder Hardwareunterstützung für Funktionen, die zum Ausführen Ihres Spiels erforderlich sind. Das ist besonders wahrscheinlich, wenn Ihr Spiel eine hochwertige Grafik hat und Vulkan die einzige API ist, die Sie auf Android verwenden. Viele ältere Geräte sind auf Version 1.0.3 der Vulkan API beschränkt und es fehlen häufig weit verbreitete Vulkan-Erweiterungen, die auf modernerer Hardware verfügbar sind.

Stabilität

Auf älteren Android-Geräten werden möglicherweise veraltete Vulkan-Treiber verwendet. Diese Treiberversionen können Fehler enthalten, die sich auf die Stabilität des Spiels auswirken. Das Umgehen von Treiberfehlern kann viel Test- und Entwicklungszeit in Anspruch nehmen.

Vulkan in Ihr Projekt einbinden

So fügen Sie Ihrem Projekt Vulkan hinzu:

  • Vulkan-API-Header einfügen
  • Shader-Code in SPIR-V kompilieren
  • Vulkan API zur Laufzeit aufrufen

Vulkan-API-Header einfügen

Ihr Spiel muss die Vulkan API-Headerdateien enthalten, damit Code, der Vulkan verwendet, kompiliert werden kann. Eine Kopie der Vulkan-Header finden Sie im Android NDK oder in Vulkan SDK-Releases. Eine bestimmte NDK-Version enthält nur Vulkan-Header, die zum Zeitpunkt der NDK-Veröffentlichung verfügbar waren. Wenn Sie Vulkan-Header aus dem NDK verwenden, müssen Sie NDK-Version 25 oder höher verwenden, die Headerdateien enthält, die Vulkan-Version 1.3 unterstützen. Das Vulkan SDK enthält die aktuelle Version der Header.

Shader-Code in SPIR-V kompilieren

Die Vulkan API erwartet, dass Shader-Programme im binären SPIR-V-Zwischenformat bereitgestellt werden. Diese Konvention unterscheidet sich von OpenGL ES, wo Sie Quellcode, der in der OpenGL Shading Language (GLSL) geschrieben wurde, als Textstrings einreichen konnten. Verwenden Sie einen Shader-Compiler, um Code, der in einer Shader-Sprache wie GLSL oder der High-level Shader Language (HLSL) geschrieben wurde, in SPIR-V-Module für die Verwendung mit Vulkan zu kompilieren.

Mit dem shaderc-Compiler können Shader-Programme, die in GLSL geschrieben wurden, in SPIR-V kompiliert werden. Wenn in Ihrem Spiel HLSL verwendet wird, unterstützt der DirectXShaderCompiler die SPIR-V-Ausgabe. Normalerweise kompilieren Sie Shader-Programme offline im Rahmen des Asset-Build-Prozesses für Ihr Spiel und fügen die SPIR-V-Module als Teil Ihrer Laufzeit-Assets ein.

Vulkan API zur Laufzeit aufrufen

Zum Aufrufen der Vulkan API muss Ihr Spiel Funktionszeiger für Vulkan API-Aufrufe abrufen. Am einfachsten ist es, die libvulkan.so-Shared Library zu verknüpfen, die im Android NDK enthalten ist. Das Verknüpfen mit der Bibliothek hat zwei Nachteile: zusätzlichen Overhead beim Funktionsaufruf und Einschränkungen hinsichtlich der Vulkan API-Funktionszeiger, die automatisch aufgelöst werden.

Wenn Sie eine Vulkan-API-Funktion aufrufen, wird die Steuerung über eine Dispatch-Tabelle weitergeleitet, die von einem Konstrukt namens Vulkan-Loader verwaltet wird. Android verwendet eine eigene Vulkan-Loader-Implementierung und nicht den LunarG-Loader. Dieses Ladesystem ist Teil der Schichtarchitektur der Vulkan API. Wenn Sie zur Build-Zeit eine Verknüpfung zur Systembibliothek herstellen, führt dies zu einer zusätzlichen Dispatch-Ebene für einen bestimmten API-Aufruf. Der Overhead ist zwar gering, kann aber bei Spielen, die viele Vulkan-Aufrufe ausführen, spürbar sein.

Die Systembibliothek löst in der Regel nur Zeiger auf Vulkan-Funktionen auf, die als Teil der Core API gelten. Vulkan hat eine große Anzahl von Erweiterungen, die zusätzliche Vulkan-Funktionen definieren. Viele davon werden nicht automatisch von der Systembibliothek aufgelöst. Sie müssen Zeiger auf diese Vulkan-Funktionen manuell auflösen, bevor Sie sie verwenden können.

Um diese Probleme zu beheben, müssen Sie Zeiger auf alle Vulkan-Funktionen, die Sie zur Laufzeit verwenden möchten, dynamisch auflösen. Eine Möglichkeit, dies zu erreichen, ist die Verwendung einer Open-Source-Meta-Loader-Bibliothek wie volk. Im Beispielspiel AGDKTunnel wird volk für diesen Zweck verwendet. Wenn Sie eine Meta-Loader-Bibliothek verwenden, dürfen Sie in Ihren Build-Skripts nicht gegen die gemeinsam genutzte Bibliothek libvulkan.so verknüpfen.

Verfügbare Vulkan API-Version ermitteln

Android unterstützt die folgenden Vulkan-API-Versionen:

  • 1.0.3
  • 1,1
  • 1.3

Die höchste Vulkan-API-Versionsnummer, die auf einem bestimmten Gerät verfügbar ist, wird durch die Android-Version und die Unterstützung des Vulkan-Treibers bestimmt.

Android-Version

Die Plattformunterstützung für eine Vulkan-API-Version hängt von einer Mindestversion von Android (API-Level) ab:

  • 1.3 – Android 13.0 (API‑Level 33) und höher
  • 1.1 – Android 10.0 (API‑Level 29) und höher
  • 1.0.3 – Android 7.0 (API‑Level 24) und höher

Vulkan-Treiberunterstützung

Die Unterstützung einer Vulkan API-Version durch die Android-Plattform garantiert nicht, dass die API-Version vom Vulkan-Treiber des Geräts unterstützt wird. Ein Gerät mit Android 13 unterstützt möglicherweise nur Version 1.1 der Vulkan API.

Fordern Sie beim Initialisieren von Vulkan keine API-Version an, die höher ist als:

  • Die maximale Vulkan-API-Version für die auf dem Gerät ausgeführte Android-Version
  • Die von vkEnumerateInstanceVersion gemeldete Vulkan-API-Version
  • Die Vulkan-API-Version, die von der apiVersion-Eigenschaft der VkPhysicalDeviceProperties-Struktur gemeldet wird

Hier ist ein Beispiel für die Ermittlung der höchsten unterstützten Vulkan-API-Version:

// Minimum Android API levels for Vulkan 1.3/1.1 version support
static constexpr int kMinimum_vk13_api_level = 33;
static constexpr int kMinimum_vk11_api_level = 29;

uint32_t GetHighestSupportedVulkanVersion(VkPhysicalDevice physical_device) {
  uint32_t instance_api_version = 0;
  vkEnumerateInstanceVersion(&instance_api_version);

  VkPhysicalDeviceProperties device_properties;
  vkGetPhysicalDeviceProperties(physical_device, &device_properties);

  // Instance and device versions don't have to match, use the lowest version
  // number for API support if they don't.
  const uint32_t driver_api_version =
      (instance_api_version < device_properties.apiVersion) ?
      instance_api_version : device_properties.apiVersion;

  const int device_api_level = android_get_device_api_level();
  if (device_api_level >= kMinimum_vk13_api_level &&
      driver_api_version >= VK_API_VERSION_1_3) {
    return VK_API_VERSION_1_3;
  } else if (device_api_level >= kMinimum_vk11_api_level &&
             driver_api_version >= VK_API_VERSION_1_1) {
    return VK_API_VERSION_1_1;
  }
  return VK_API_VERSION_1_0;
}

Vulkan-Profilkompatibilität ermitteln

Vulkan-Profile sind JSON-Dateien, die eine Reihe von erforderlichen Funktionen, Erweiterungen, Möglichkeiten und Mindestparametergrenzwerten definieren, die ein Vulkan-Gerät unterstützen muss, um mit dem Profil kompatibel zu sein. Wenn Sie herausfinden möchten, ob ein Gerät mit einem bestimmten Vulkan-Profil kompatibel ist, z. B. mit dem Android-Baseline-Profil von 2022, können Sie die Open-Source-Vulkan Profiles API-Bibliothek verwenden. Sie können die JSON-Datei des Profils auch selbst parsen und Gerätefunktionen mit den entsprechenden Vulkan-APIs abfragen, um die Profilkompatibilität zu ermitteln.

Vulkan-Profile

Android verwendet Vulkan-Profile, in denen definiert wird, welche Funktionen und Erweiterungen für die einzelnen Geräte mit Android verfügbar sind.

Das Android Baseline Profile (ABP) ist der erste Versuch, ein Vulkan-Profil zu erstellen. ABP2021 und ABP2022 sind rückblickende Profile, die darauf abzielen, mehr als 85% der aktiven Geräte zu diesem Zeitpunkt abzudecken. Es wird keine neuen ABP-Versionen mehr geben.

Vulkan Profiles for Android (VPA) ist das neue zukunftsorientierte Profil, das die Anforderungen von Softwareentwicklern widerspiegeln und konsistente Funktionen bereitstellen soll, sobald Hardwareentwickler sie liefern können. VPA15_minimums ist das erste Profil für Android 15. Jedes Jahr wird ein neues VPA veröffentlicht, um jedes wichtige Android-Release abzudecken.

Frame-Pacing implementieren

Ein korrektes Frame-Pacing ist ein wichtiger Bestandteil eines hochwertigen Spielerlebnisses. Das Android Game Development Kit enthält die Frame Pacing-Bibliothek, mit der Sie in Ihrem Spiel ein optimales Frame Pacing erreichen können. Weitere Implementierungsdetails finden Sie unter Android Frame Pacing in Ihren Vulkan-Renderer einbinden.

Nicht auf implizite Synchronisierung und Frame-Pacing verlassen

vkAcquireNextImageKHR und vkQueuePresentKHR werden zur Verwaltung der Swapchain verwendet. Verlassen Sie sich nicht auf das potenzielle Blockierungsverhalten für die allgemeine Anwendungs- oder GPU-Synchronisierung.

Das genaue Blockierungsverhalten dieser Funktionen kann sich erheblich unterscheiden:

  • Android-Geräte
  • GPU-Treiber
  • Status der Präsentations-Engine (VkPresentModeKHR)

Der einzige Zweck von vkAcquireNextImageKHR besteht darin, ein verfügbares präsentierbares Bild abzurufen. Die Funktion kann blockieren oder nicht. Ebenso stellt vkQueuePresentKHR eine Anfrage zum Anzeigen eines Bildes in die Warteschlange und kann blockieren oder nicht.

Keine der beiden Funktionen bietet zuverlässige Garantien für die Synchronisierung unabhängiger CPU-Aufgaben oder GPU-Vorgänge.

Verwenden Sie für eine robuste Synchronisierung immer explizite Vulkan-Primitive wie Semaphoren für GPU-GPU-Abhängigkeiten (z.B. „Render-to-Present“), Fences für die GPU-CPU-Synchronisierung (z.B. um zu wissen, wann das Rendern auf der CPU abgeschlossen ist) und Pipeline-Barrieren oder Ereignisse für detailliertere GPU-Ausführungs- und Speicherabhängigkeiten. Durch die explizite Synchronisierung wird ein vorhersehbares Verhalten gewährleistet und subtile Fehler werden vermieden, die durch implementierungsspezifische Zeitvariationen entstehen, die im vielfältigen Hardware-Ökosystem von Android inhärent sind.

Vorabrotation implementieren

Android-Geräte können in verschiedenen Ausrichtungen angezeigt werden. Die Ausrichtung des Geräts kann sich von der Ausrichtung der Renderoberfläche unterscheiden. Im Gegensatz zu OpenGL ES unter Android werden Abweichungen zwischen den beiden nicht von Vulkan behandelt. Informationen zur Funktionsweise des Ausrichtungsprozesses und zur optimalen Methode zur Behandlung von Ausrichtungsunterschieden bei der Verwendung von Vulkan finden Sie unter Gerätedrehung mit Vulkan-Vorrotation verarbeiten.

Fehlerbehebung und Profilerstellung für Vulkan-Rendering

Es gibt mehrere Tools, mit denen Sie Rendering- und Leistungsprobleme mit Vulkan-Rendering-Code diagnostizieren können.

Weitere Informationen zu den Debugging- und Profiling-Tools von Vulkan finden Sie im Abschnitt Tools und erweiterte Funktionen.

Vulkan-Validierungsebenen

Vulkan-Validierungsebenen sind Laufzeitbibliotheken, die aktiviert werden können, um Ihre Aufrufe der Vulkan API zu prüfen und Warnungen oder Fehler bei falscher oder nicht optimaler Verwendung auszugeben. Diese Validierungsebenen sind standardmäßig nicht aktiv, da der Validierungsprozess Laufzeit-Overhead verursacht und die Leistung Ihres Spiels beeinträchtigt. Informationen zur Verwendung von Validierungsebenen in Ihrem Spiel finden Sie unter Mit der Validierungsebene debuggen.

Tools für die Frame-Erfassung

Mit Tools zur Frame-Erfassung können Sie die Vulkan API-Aufrufe aufzeichnen und wiedergeben, die während eines Spiele-Frames ausgeführt werden. Mit diesen Tools haben Sie folgende Möglichkeiten:

  • Informationen zu aktiven Grafikressourcen und Visualisierungen ansehen
  • Die Abfolge der API-Aufrufe Ihres Spiels und die API-Parameter ansehen
  • Status der Grafikpipeline zum Zeitpunkt eines Draw-Aufrufs untersuchen
  • Ergebnisse des Renderings bis zu einem bestimmten Draw-Aufruf im Frame visualisieren

Mit dem Open-Source-Tool RenderDoc können Sie Frames aus Spielen erfassen, die unter Android ausgeführt werden. RenderDoc unterstützt die Frame-Erfassung sowohl von Vulkan als auch von OpenGL ES.

Mit dem Android GPU Inspector (AGI) lassen sich auch Vulkan-Frames erfassen.

Tools zur Leistungsanalyse

Verwenden Sie Tools zur Leistungsanalyse, um Rendering-Probleme in Ihrem Spiel zu untersuchen, die zu suboptimalen Framerates führen. Einzelne GPU-Anbieter stellen Tools zur Verfügung, mit denen du dein Spiel profilieren und Leistungsdaten speziell für ihre GPU-Architekturen abrufen kannst. Die Leistungsmerkmale und Engpässe Ihres Spiels können sich beim Rendern auf GPUs verschiedener Anbieter oder sogar auf verschiedenen GPU-Generationen desselben Anbieters erheblich unterscheiden.

Sie können auch den Android GPU Inspector verwenden, um Leistungsdaten zu erfassen und zu analysieren. Im Gegensatz zu den Tools der Anbieter ist Android GPU Inspector mit mehreren GPUs verschiedener Anbieter kompatibel. Android GPU Inspector unterstützt jedoch keine älteren Android-Geräte und ist möglicherweise nicht mit allen neuen Geräten kompatibel.

Vulkan-Tests mit CTS-D verbessern

Hersteller von Android-Geräten verwenden die Compatibility Test Suite (CTS), um sicherzustellen, dass ihre Geräte kompatibel sind. Entwicklerbasierte CTS-Tests (CTS-D) werden von Android-App-Entwicklern eingereicht, um sicherzustellen, dass zukünftige Android-Geräte ihre Anwendungsfälle erfüllen und ihre Anwendungen reibungslos und ohne Fehler ausführen können.

Wenn Sie mit Ihrer Vulkan-Anwendung einen neuen Fehler auslösen, der ein bestimmtes Android-Gerät betrifft, können Sie einen neuen Testvorschlag einreichen, in dem Sie das Problem und die Möglichkeiten zur Überprüfung beschreiben. So wird sichergestellt, dass das Problem in einem zukünftigen Update für das Gerät behoben wird und dass derselbe Fehler nicht auf anderen Geräten auftritt.

Eine detaillierte Anleitung zum Einreichen des Testvorschlags finden Sie hier.