Compilatori di Shadr Vulkan su Android

Un'app Vulkan deve gestire gli mesh in modo diverso rispetto a un'app OpenGL ES: in OpenGL ES, fornisci uno Shader come un insieme di stringhe che formano il testo di origine di un programma mesh GLSL. Al contrario, l'API Vulkan richiede di fornire uno meshr sotto forma di punto di ingresso in un modulo SPIR-V.

NDK Release 12 e successive include una libreria di runtime per la compilazione di GLSL in SPIR-V. La libreria di runtime è la stessa del progetto open source Shaderc e utilizza lo stesso compilatore di riferimenti Glslang GLSL come backend. Per impostazione predefinita, la versione Shaderc del compilatore presuppone che tu stia eseguendo la compilazione per Vulkan. Dopo aver verificato se il tuo codice è valido per Vulkan, il compilatore attiva automaticamente l'estensione KHR_vulkan_glsl. La versione Shaderc del compilatore genera anche codice SPIR-V conforme a Vulkan.

Puoi scegliere di compilare i moduli SPIR-V nella tua app Vulkan durante lo sviluppo, una pratica chiamata prima del tempo, o AOT, compilazione. In alternativa, puoi fare in modo che la tua app le compili dall'origine Shader spedita o generata proceduralmente quando necessario durante il runtime. Questa pratica è chiamata compilazione runtime. Android Studio ha il supporto integrato per la creazione di mesh Vulkan.

Il resto di questa pagina fornisce ulteriori dettagli su ogni esercitazione e spiega come integrare la compilation Shader nell'app Vulkan.

Compilation di AOT

Esistono due modi per ottenere la compilazione AOT dello Shader, descritti nelle sezioni seguenti.

Utilizzare Android Studio

Quando li inserisce in app/src/main/shaders/, Android Studio riconosce gli mesh in base alle loro estensioni file e completa le seguenti azioni:

  • Compila tutti i file dello mesh in modo ricorsivo sotto quella directory.
  • Aggiungi il suffisso .spv ai file puller SPIR-V compilati.
  • Crea gli shard SPIRV nella directory assets/shaders/ dell'APK.

In fase di esecuzione, l'applicazione caricherebbe gli mesh compilati dalla posizione assets/shaders/ corrispondente. La struttura del file dello Shader GLSL compilato è la stessa in app/src/main/shaders/:

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);

I flag di compilazione Shaderc possono essere configurati all'interno del blocco shaders gradle DSL, come mostrato nell'esempio seguente:

Trendy

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 si applica a tutte le compilazioni dello mesh; scopedArgs si applica solo in fase di compilazione per quell'ambito. L'esempio sopra crea un argomento di ambito lights, che verrà applicato solo agli mesh GLSL nella directory app/src/main/shaders/lights/. Consulta glslc per l'elenco completo dei flag di compilazione disponibili. Tieni presente che Shaderc in NDK è uno snapshot di quel repository Github al momento del rilascio NDK; puoi ottenere gli esatti flag supportati per quella versione con il comando glslc --help, come descritto nella sezione successiva.

Compilazione a riga di comando offline

Gli Shader GLSL possono essere compilati in SPIR-V indipendentemente dall'applicazione principale utilizzando il compilatore a riga di comando glslc. NDK 12 e versioni successive pacchettizza una versione del codice glslc predefinito e degli strumenti correlati nella directory <android-ndk-dir>/shader-tools/ per supportare questo modello di utilizzo.

Il compilatore è disponibile anche nel progetto Shaderc; segui le istruzioni fornite per creare una versione binaria.

glslc offre un ricco set di opzioni della riga di comando per la compilazione dello shabbyr, in modo da soddisfare i vari requisiti di un'applicazione.

Lo strumento glslc compila un singolo file di origine in un modulo SPIR-V con un singolo punto di ingresso dello shardr. Per impostazione predefinita, il nome del file di output ha lo stesso nome del file di origine, ma viene aggiunta l'estensione .spv.

Puoi usare le estensioni dei nomi file per indicare allo strumento glslc quale fase di mesh di grafica compilare o se è in corso la compilazione di uno mesh di computing. Per informazioni su come utilizzare queste estensioni per i nomi file e sulle opzioni che puoi utilizzare con lo strumento, consulta la specifica della fase Shader nel manuale glslc.

Compilazione runtime

Per la compilazione JIT degli Shader durante il runtime, l'NDK fornisce la libreria libshaderc, che include le API C e C++.

Le applicazioni C++ devono utilizzare l'API C++. Consigliamo alle app in altri linguaggi di usare l'API C, perché l'ABI C è di livello inferiore ed è probabile che offra una maggiore stabilità.

L'esempio seguente mostra come utilizzare l'API C++:

#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;
}

Integrazione nei tuoi progetti

Puoi integrare il compilatore Shader Vulkan nella tua app utilizzando il file Android.mk del progetto o Gradle.

Android.mk

Esegui i passaggi seguenti per utilizzare il file Android.mk del progetto per integrare il compilatore Shader.

  1. Includi le seguenti righe nel file Android.mk:
    include $(CLEAR_VARS)
         ...
    LOCAL_STATIC_LIBRARIES := shaderc
         ...
    include $(BUILD_SHARED_LIBRARY)
    
    $(call import-module, third_party/shaderc)
    
  2. Imposta APP_STL su c++_static, c++_shared, gnustl_static o gnustl_shared in Application.mk

Integrazione di CMake di Gradle

  1. In una finestra del terminale, vai a ndk_root/sources/third_party/shaderc/.
  2. Esegui questo comando per creare Shaderc di NDK. Devi eseguire questo comando una sola volta su ogni versione NDK che utilizzi:
    $ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
    APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
    

    Questo comando inserisce due cartelle in <ndk_root>/sources/third_party/shaderc/. La struttura delle directory è la seguente:

    include/
      shaderc/
        shaderc.h
        shaderc.hpp
    libs/
      <stl_version>/
        {all of the abis}
           libshaderc.a
    
  3. Aggiungi le inclusioni e le librerie generate utilizzando target_include_directories e target_link_libraries, come fai normalmente per librerie esterne simili. Il tipo STL dell'app deve corrispondere a uno dei tipi di stl specificati in stl_version. L'NDK consiglia di utilizzare c++_shared o c++_static, nonostante siano supportati anche gnustl_static e gnustl_shared.

Scarica l'ultima versione di Shaderc

Shaderc in NDK proviene dalla struttura ad albero di origine Android, che è un'istantanea del repository Shaderc a monte. Se ti serve l'ultima versione di Shaderc, consulta l'articolo sulle istruzioni di creazione dei dettagli. I passaggi generali sono i seguenti:

  1. Scarica l'ultima versione di Shaderc:
    git clone https://github.com/google/shaderc.git
  2. Aggiorna dipendenze:
    ./utils/git-sync-deps
  3. Shaderc di build:
    <ndk_dir>/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
        APP_STL:=c++_static APP_ABI=all libshaderc_combined -j16
    
  4. Configura il tuo progetto per utilizzare la tua build Shaderc nel file di script di build.