Vulkan-Shader-Compiler unter Android

Eine Vulkan-App muss Shader anders verwalten als eine OpenGL ES-App: In OpenGL ES stellen Sie einen Shader als eine Reihe von Zeichenfolgen bereit, die den Quelltext eines GLSL-Shader-Programm. Im Gegensatz dazu müssen Sie für die Vulkan API einen Shader in hat die Form eines Einstiegspunkts in einem SPIR-V-Modul.

NDK Release 12 und höher enthält eine Laufzeitbibliothek zum Kompilieren von GLSL in SPIR-V. Die Laufzeitbibliothek ist mit der im das Open-Source-Projekt Shaderc, Der Referenz-Compiler Glslang GLSL ist als Back-End. Standardmäßig ist die Shaderc-Version des Compiler geht davon aus, dass Sie für Vulkan kompilieren. Nachdem Sie überprüft haben, ob Ihr Code für Vulkan aktiviert der Compiler automatisch die Erweiterung KHR_vulkan_glsl. Shaderc Version des Compilers generiert außerdem Vulkan-konformen SPIR-V-Code.

Du kannst während der Entwicklung SPIR-V-Module in deine Vulkan-App kompilieren. eine sogenannte Vorab-Kompilierung oder AOT-Kompilierung. Alternativ können Sie Du kannst sie in deiner App aus versendeten oder verfahrenstechnisch generierten Shader kompilieren lassen Quelle, wenn dies während der Laufzeit erforderlich ist. Diese Vorgehensweise wird als Laufzeitkompilierung bezeichnet. Android Studio bietet integrierte Unterstützung für die Erstellung von Vulkan-Shadern.

Im Folgenden werden die einzelnen Vorgehensweisen näher erläutert. wie du die Shader-Kompilierung in deine Vulkan-App einbindest.

AOT-Kompilierung

Es gibt zwei Möglichkeiten, eine Shader-AOT-Kompilierung zu erreichen, die in den folgenden Abschnitten beschrieben werden.

Android Studio verwenden

Android Studio fügt Shader in app/src/main/shaders/ ein und erkennt Shader folgendermaßen: deren Dateiendung und führt die folgenden Aktionen aus:

  • Kompilieren Sie alle Shader-Dateien rekursiv unter diesem Verzeichnis.
  • Hängen Sie das Suffix „.spv“ an die kompilierten SPIR-V-Shaderdateien an.
  • Packen Sie SPIRV-Shaders in das Verzeichnis assets/shaders/ des APK.

Die Anwendung lädt die kompilierten Shader zur Laufzeit aus dem entsprechenden assets/shaders/-Speicherort. Die Struktur der kompilierten spv-Shader-Datei ist mit der Struktur der GLSL-Shader-Datei der Anwendung unter app/src/main/shaders/ identisch:

AAsset* file = AAssetManager_open(assetManager,
                     "shaders/tri.vert.spv", AASSET_MODE_BUFFER);
size_t fileLength = AAsset_getLength(file);
char* fileContent = new char[fileLength];
AAsset_read(file, fileContent, fileLength);

Kompilierungs-Flags von Shaderc können im Gradle-DSL-Block shaders konfiguriert werden, wie im folgenden Beispiel gezeigt:

Cool

android {
  defaultConfig {
    shaders {
      glslcArgs.addAll(['-c', '-g'])
      scopedArgs.create('lights') {
        glslcArgs.addAll(['-DLIGHT1=1', '-DLIGHT2=0'])
      }
    }
  }
}

Kotlin

android {
  defaultConfig {
    shaders {
        glslcArgs += listOf("-c", "-g")
        glslcScopedArgs("lights", "-DLIGHT1=1", "-DLIGHT2=0")
    }
  }
}

glslcArgs gelten für alle Shader-Kompilierungen. scopedArgs gilt nur beim Kompilieren für diesen Bereich. Im obigen Beispiel wird das Bereichsargument lights erstellt, das nur auf GLSL-Shader im Verzeichnis app/src/main/shaders/lights/ Weitere Informationen finden Sie unter glslc für die vollständige Liste der verfügbaren Kompilierungs-Flags. Shaderc innerhalb des NDK ist ein Snapshot aus diesem GitHub-Repository im NDK-Veröffentlichungszeit; erhalten Sie die genauen unterstützten Flags für diese Version mit dem Befehl glslc --help, wie im nächsten Abschnitt beschrieben.

Offline-Kompilierung über die Befehlszeile

GLSL-Shader können unabhängig von der Hauptanwendung mit dem Befehlszeilen-Compiler glslc zu SPIR-V kompiliert werden. NDK Release 12 und höher enthält eine Version der vordefinierten Version von glslc und zugehörige Tools im Verzeichnis <android-ndk-dir>/shader-tools/, um dieses Nutzungsmodell zu unterstützen.

Der Compiler ist auch auf dem Shaderc verfügbar. Projekt respektieren; folgen Sie der Anleitung, um eine Binärversion zu erstellen.

glslc bietet zahlreiche Befehlszeilenoptionen für die Shader-Kompilierung, um verschiedene Anforderungen für eine Anwendung zu erfüllen.

Das glslc-Tool kompiliert eine einzelne Quelldatei in ein SPIR-V-Modul mit einem einzelnen Shader Einstiegspunkts hinzufügen. Standardmäßig hat die Ausgabedatei denselben Namen wie die Quelldatei. aber mit angehängter Erweiterung .spv.

Sie teilen dem glslc-Tool mithilfe von Dateinamenerweiterungen mit, welche Grafik-Shader-Phase kompiliert werden soll. oder ob ein Compute-Shader kompiliert wird. Informationen zur Verwendung dieser Dateinamen Erweiterungen und Optionen, die Sie mit dem Tool verwenden können, finden Sie unter <ph type="x-smartling-placeholder"></ph> Spezifikation der Shader-Phase in der <ph type="x-smartling-placeholder"></ph> glslc-Anleitung.

Laufzeitkompilierung

Für die JIT-Kompilierung von Shadern während der Laufzeit stellt das NDK die libshaderc-Bibliothek bereit. die sowohl C als auch C++ APIs bietet.

C++-Anwendungen sollten die C++ API verwenden. Wir empfehlen, Apps in anderen Sprachen die C API verwenden, da das C ABI niedriger ist und wahrscheinlich eine bessere Stabilität bietet.

Das folgende Beispiel zeigt, wie die C++ API verwendet wird:

#include <iostream>
#include <string>
#include <vector>
#include <shaderc/shaderc.hpp>

std::vector<uint32_t> compile_file(const std::string& name,
                                   shaderc_shader_kind kind,
                                   const std::string& data) {
  shaderc::Compiler compiler;
  shaderc::CompileOptions options;

  // Like -DMY_DEFINE=1
  options.AddMacroDefinition("MY_DEFINE", "1");

  shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(
      data.c_str(), data.size(), kind, name.c_str(), options);

  if (module.GetCompilationStatus() !=
      shaderc_compilation_status_success) {
    std::cerr << module.GetErrorMessage();
  }

  std::vector<uint32_t> result(module.cbegin(), module.cend());
  return result;
}

In Ihre Projekte einbinden

Sie können den Vulkan-Shader-Compiler entweder mit dem Android.mk-Datei oder Gradle-Plug-in verwenden.

Android.Mk

Führen Sie die folgenden Schritte aus, um den Android.mk Ihres Projekts zu verwenden -Datei zum Integrieren des Shader-Compilers.

  1. Fügen Sie die folgenden Zeilen in die Datei „Android.mk“ ein:
    include $(CLEAR_VARS)
         ...
    LOCAL_STATIC_LIBRARIES := shaderc
         ...
    include $(BUILD_SHARED_LIBRARY)
    
    $(call import-module, third_party/shaderc)
    
  2. Legen Sie für APP_STL einen der folgenden Werte fest: c++_static, c++_shared, gnustl_static, oder gnustl_shared in Application.mk der App

CMake-Integration von Gradle

  1. Wechseln Sie in einem Terminalfenster zu ndk_root/sources/third_party/shaderc/
  2. Führen Sie den folgenden Befehl aus, um den Shaderc von NDK zu erstellen. Sie müssen diesen Befehl für jede verwendete NDK-Version nur einmal ausführen:
    $ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
    APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
    

    Mit diesem Befehl werden zwei Ordner in <ndk_root>/sources/third_party/shaderc/ abgelegt. Das Verzeichnis sieht wie folgt aus:

    include/
      shaderc/
        shaderc.h
        shaderc.hpp
    libs/
      <stl_version>/
        {all of the abis}
           libshaderc.a
    
  3. Fügen Sie die generierten Bundles und Bibliotheken mithilfe von hinzu. target_include_directories und <ph type="x-smartling-placeholder"></ph> target_link_libraries, wie Sie es normalerweise bei ähnlichen extern Bibliotheken. Der STL-Typ deiner App muss einem der stl-Typen entsprechen, die in stl_version. Das NDK empfiehlt die Verwendung von c++_shared oder c++_static, obwohl gnustl_static und gnustl_shared werden ebenfalls unterstützt.

Das neueste Shaderc

Shaderc im NDK stammt aus dem Android Source Tree, einer Snapshot des vorgelagerten Shaderc-Repositorys. Wenn Sie das neueste Shaderc benötigen, finden Sie weitere Informationen in der Build-Anleitung. Die übergeordneten Schritte sind folgende:

  1. Laden Sie die neueste Shaderc-Version herunter:
    git clone https://github.com/google/shaderc.git
  2. Aktualisieren Sie die Abhängigkeiten:
    ./utils/git-sync-deps
  3. Build Shaderc:
    <ndk_dir>/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
        APP_STL:=c++_static APP_ABI=all libshaderc_combined -j16
    
  4. Konfigurieren Sie Ihr Projekt so, dass es Ihren eigenen Shaderc-Build in Ihrer Build-Skriptdatei verwendet.