Skripts zu Vulkan migrieren

Bei Arbeitslasten, für die GPU-Computing ideal ist, bietet die Migration von RenderScript-Skripts zu Vulkan-Computing Ihrer App mehr direkte Kontrolle über die GPU-Hardware und damit möglicherweise eine zusätzliche Leistung im Vergleich zu anderen APIs.

Es folgt eine allgemeine Übersicht, in der du erfährst, wie du Vulkan-Shader verwenden kannst, um RenderScript-Skripts zu ersetzen.

Vulkan-Initialisierung

Anstatt ein RenderScript-Kontextobjekt in Kotlin oder Java zu erstellen, führen Sie die folgenden Schritte aus, um mithilfe des NDK einen Vulkan-Kontext zu erstellen.

  1. Erstellen Sie eine Vulkan-Instanz.

  2. Wählen Sie ein physisches Vulkan-Gerät aus, das eine Computing-Warteschlange unterstützt.

  3. Erstellen Sie ein logisches Vulkan-Gerät und rufen Sie die Computing-Warteschlange ab.

Optional können Sie die Vulkan-Validierungsebenen unter Android einrichten, um die Entwicklung Ihrer Vulkan-Anwendung zu beschleunigen.

Mit der Beispiel-App wird gezeigt, wie Sie den Vulkan-Kontext in VulkanContext.h initialisieren. Weitere Informationen finden Sie in den Abschnitten Initialisierung und Geräte und Warteschlangen der Vulkan-Spezifikation.

Vulkan-Zuweisungen

Eine RenderScript-Zuweisung kann zu einem Vulkan-Speicherbild oder einem Vulkan-Speicherpuffer migriert werden. Um die Leistung bei schreibgeschützten Bildern zu verbessern, verwenden Sie ein Beispielbild mit Abrufvorgängen, entweder als kombinierten Bildsampler oder mit unterschiedlichen sampler und sampler image.

Die Vulkan-Ressourcen werden in Vulkan zugewiesen. Mit der Erweiterung VK_ANDROID_external_memory_android_hardware_buffer können Sie einen Android-AHardwareBuffer in Vulkan importieren, um unnötigen Aufwand beim Kopieren des Arbeitsspeichers zu vermeiden, wenn Sie mit anderen Android-Komponenten interagieren. Diese Erweiterung ist auf allen Android-Geräten verfügbar, die Vulkan 1.1 unterstützen. Weitere Informationen finden Sie unter FEATURE_VULKAN_HARDWARE_VERSION.

Die Beispiel-App zeigt, wie Vulkan-Ressourcen in VulkanResources.h erstellt werden. Weitere Informationen finden Sie in den Abschnitten Ressourcenerstellung und Ressourcendeskriptoren in der Vulkan-Spezifikation.

Konvertierung in Vulkan-Computing-Shader

Deine RenderScript-Skripts müssen in Vulkan-Computing-Shaders konvertiert werden. Möglicherweise müssen Sie Ihren Code auch anpassen, wenn Sie globale RenderScript-Elemente verwenden.

Vulkan-Computing-Shader schreiben

Ein Vulkan-Computing-Shader wird in der Regel in OpenGL Shading Language (GLSL) geschrieben und dann im SPIR-V-Format (Standard Portable Intermediate Visualization-V) kompiliert.

Ausführliche Informationen und Anleitungen zum Einbinden von Shadern in Ihre App finden Sie unter Vulkan-Shader-Compiler unter Android.

Anpassung von globalen Skripten

Je nach den Eigenschaften der globalen Skripte empfehlen wir die Verwendung von Spezialisierungskonstanten, Push-Konstanten oder einheitlichen Pufferobjekten für globales, die nicht innerhalb des Shaders geändert werden:

  • Spezialisierungskonstanten: Empfohlen für globale Skripte, die bei allen Kernel-Aufrufen weitgehend konsistent sind. Wenn Sie den Wert der Spezialisierungskonstanten ändern, muss die Computing-Pipeline neu erstellt werden.
  • Push-Konstanten: Empfohlen für häufig geänderte globale Skripte, die kleiner als maxPushConstantsSize sind (garantiertes Minimum: 128 Byte).
  • Einheitlicher Zwischenspeicher: Empfohlen für häufig geänderte Skript-globale Größen, die größer als das konstante Push-Limit sind.

Für globales, die innerhalb des Shaders geändert werden, können Sie entweder das Vulkan-Speicher-Image oder den Vulkan-Speicherpuffer verwenden.

Berechnungen

Sie müssen eine Vulkan-Computing-Pipeline erstellen, damit die GPU Ihren Compute-Shader ausführt.

Vulkan-Computing-Pipeline erstellen

In der Datei ComputePipeline.h in der Beispiel-App wird gezeigt, wie die Computing-Pipeline von Vulkan erstellt wird.

Um einen kompilierten SPIR-V-Shader in Vulkan zu verwenden, müssen Sie eine Vulkan-Computing-Pipeline so erstellen:

  1. Erstellen Sie ein Shader-Modul mit dem kompilierten SPIR-V-Shader.
  2. Erstellen Sie ein Layout für den Deskriptorsatz und geben Sie die Ressourcenbindungen an. Weitere Informationen finden Sie unter Zuweisungen.
  3. Erstellen Sie einen Deskriptorsatz aus dem Layout des Deskriptorsatzes.
  4. Erstellen Sie ein Pipelinelayout aus dem Deskriptorsatz-Layout.
  5. Erstellen Sie eine Compute-Pipeline mit dem Shader-Modul und dem Pipelinelayout.

Weitere Informationen finden Sie in der Vulkan-Spezifikation im Abschnitt Compute-Pipelines.

Berechnung starten

So starten Sie die Berechnung mit einer Computing-Pipeline:

  1. Aktualisieren Sie den mit den Vulkan-Ressourcen festgelegten Deskriptor.
  2. Erstellen Sie einen Vulkan-Befehlspuffer und notieren Sie sich die folgenden Befehle:
    1. Binden Sie die Pipeline und den Deskriptorsatz.
    2. Senden Sie Compute-Arbeitsgruppen.
  3. Übergeben Sie den Befehlspuffer an die Compute-Warteschlange.
  4. Warten Sie in der Warteschlange oder geben Sie optional einen Synchronisierungszaun zurück.

Wenn Sie mehrere Kernel miteinander verketten möchten (z. B. um Codes mit ScriptGroup zu migrieren), notieren Sie sie in einem einzigen Befehlspuffer und synchronisieren Sie sie mit Arbeitsspeicherbarrieren.

Die Beispielanwendung zeigt zwei Computing-Aufgaben:

  • HUE-Rotation: Eine einfache Rechenaufgabe mit einem einzelnen Rechen-Shader. Das Codebeispiel finden Sie unter ImageProcessor::rotateHue.
  • Weichzeichnen: Eine komplexere Rechenaufgabe, die zwei Compute-Shader nacheinander ausführt. Das Codebeispiel finden Sie unter ImageProcessor::blur.

Weitere Informationen zu Befehlspuffern oder Speicherbarrieren finden Sie in den Abschnitten zu Befehlspuffern und Speicherbarrieren in der Vulkan-Spezifikation.