Aplikacja Vulkan musi zarządzać cieniami inaczej niż aplikacja OpenGL ES: w przypadku OpenGL ES udostępniasz program do cieniowania jako zestaw ciągów tekstowych tworzących tekst źródłowy programu do cieniowania OpenGL. Z kolei interfejs Vulkan API wymaga udostępnienia programu do cieniowania w postaci punktu wejścia w module SPIR-V.
NDK w wersji 12 i nowszych zawiera bibliotekę środowiska wykonawczego, które umożliwia kompilowanie GLSL do SPIR-V.
Biblioteka środowiska wykonawczego jest taka sama jak w projekcie open source Shaderc, a jako backend korzysta ten sam kompilator odwołań Glslang GLSL. Domyślnie wersja Shaderc kompilatora zakłada, że kompilujesz dla języka Vulkan. Po sprawdzeniu, czy Twój kod jest zgodny z platformą Vulkan, kompilator automatycznie włącza rozszerzenie KHR_vulkan_glsl
. Wersja kompilatora Shaderc generuje też kod SPIR-V zgodny z Vulkanem.
W trakcie programowania możesz kompilować moduły SPIR-V w aplikację Vulkan (metodę nazywaną wcześniej) lub kompilację AOT. Możesz też w razie potrzeby skompilować je w czasie działania z przesłanego lub wygenerowanego proceduralnie źródła programu do cieniowania. Jest to tzw. kompilowanie w czasie działania. Android Studio ma zintegrowaną obsługę cieniowania Vulkan.
Na tej stronie znajdziesz więcej informacji o każdej z nich, a potem dowiesz się, jak zintegrować kompilację programów do cieniowania z aplikacją Vulkan.
Kompilacja AOT
Istnieją 2 sposoby na uzyskanie kompilacji AOT dla cieniowania opisane w kolejnych sekcjach.
Użyj Android Studio
Po wprowadzeniu cieniowania w app/src/main/shaders/
Android Studio rozpoznaje je na podstawie ich rozszerzeń plików i wykona te działania:
- Skompiluj rekurencyjnie wszystkie pliki cieniowania w tym katalogu.
- Dołącz sufiks .spv do skompilowanych plików cieniowania SPIR-V.
- Zapakuj shader SPIRV do katalogu
assets/shaders/
pakietu APK.
Aplikacja wczytuje skompilowane programy do cieniowania z odpowiedniej lokalizacji w języku assets/shaders/
w czasie działania. Skompilowana struktura pliku cieniowania spv jest taka sama jak struktura pliku cieniowania GLSL aplikacji w 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);
Flagi kompilacji Shaderc można skonfigurować wewnątrz bloku DSL shaders
Gradle, jak pokazano w tym przykładzie:
Odlotowy
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") } } }
Wartości glslcArgs
mają zastosowanie do wszystkich kompilacji cieniowania, a scopedArgs
tylko podczas kompilacji dla tego zakresu. Powyższy przykład tworzy argument zakresu lights
, który będzie stosowany tylko do cieniowania GSL w katalogu app/src/main/shaders/lights/
. Pełną listę dostępnych flag kompilacji znajdziesz w dokumentacji glslc. Zwróć uwagę, że Shaderc w NDK to zrzut z repozytorium github w momencie wydania NDK. Dokładne obsługiwane flagi dla danej wersji możesz uzyskać, używając polecenia glslc --help
, jak opisano w następnej sekcji.
Kompilacja wiersza poleceń offline
Programy Shadery GLSL można kompilować do interfejsu SPIR-V niezależnie od głównej aplikacji za pomocą kompilatora wiersza poleceń glslc. NDK w wersji 12 i nowszych zawiera wersję gotowego pliku glslc i powiązanych narzędzi w katalogu <android-ndk-dir>/shader-tools/
na potrzeby obsługi tego modelu użycia.
Kompilator jest również dostępny w projekcie Shaderc. Aby utworzyć wersję binarną, postępuj zgodnie z podanymi tam instrukcjami.
glslc udostępnia bogaty zestaw opcji wiersza poleceń na potrzeby kompilacji programu do cieniowania, które pozwalają spełnić różne wymagania aplikacji.
Narzędzie glslc skompiluje plik z jednym kodem źródłowym i utworzy moduł SPIR-V z pojedynczym punktem wejścia do cieniowania. Domyślnie plik wyjściowy ma taką samą nazwę jak plik źródłowy, ale z dołączonym rozszerzeniem .spv
.
Rozszerzenia plików informują narzędzie glslc o tym, który program do cieniowania grafiki ma skompilować oraz o tym, czy ten program jest kompilowany. Informacje o tym, jak korzystać z tych rozszerzeń nazw plików, a także o opcjach, których możesz używać z narzędziem, znajdziesz w specyfikacji etapu Shader w instrukcji glslc.
Kompilacja środowiska wykonawczego
Do kompilacji programów do cieniowania przy użyciu metody JIT w czasie działania NDK dostarcza bibliotekę libshaderc, która zawiera interfejsy API zarówno w języku C, jak i C++.
Aplikacje w C++ powinny używać interfejsu API C++. Zalecamy, aby aplikacje w innych językach korzystały z interfejsu C API, ponieważ interfejs C ABI jest niższy i prawdopodobnie zapewni większą stabilność.
Z przykładu poniżej dowiesz się, jak korzystać z interfejsu 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; }
Integracja ze swoimi projektami
Możesz zintegrować kompilator do cieniowania Vulkan ze swoją aplikacją za pomocą pliku Android.mk
projektu lub Gradle.
Android.mk
Wykonaj poniższe czynności, aby użyć pliku Android.mk
swojego projektu do integracji kompilatora do cieniowania.
-
W pliku Android.mk umieść te wiersze:
include $(CLEAR_VARS) ... LOCAL_STATIC_LIBRARIES := shaderc ... include $(BUILD_SHARED_LIBRARY) $(call import-module, third_party/shaderc)
-
Ustaw APP_STL na jedną z wartości
c++_static
,c++_shared
,gnustl_static
lubgnustl_shared
w pliku Application.mk aplikacji
Integracja CMake dla Gradle
-
W oknie terminala przejdź do
ndk_root/sources/third_party/shaderc/
. -
Uruchom to polecenie, by utworzyć Shaderc dla NDK. To polecenie musisz uruchomić tylko raz w każdej wersji NDK:
$ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \ APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
To polecenie umieszcza 2 foldery w katalogu <ndk_root>/sources/third_party/shaderc/. Struktura katalogów jest taka:
include/ shaderc/ shaderc.h shaderc.hpp libs/ <stl_version>/ {all of the abis} libshaderc.a
-
Dodaj wygenerowane rozszerzenia i biblioteki za pomocą
target_include_directories
itarget_link_libraries
, tak jak w przypadku podobnych bibliotek zewnętrznych. Typ STL aplikacji musi pasować do jednego z typówstl
określonych w polustl_version
. NDK zaleca użyciec++_shared
lubc++_static
, ale obsługiwane są teżgnustl_static
ignustl_shared
.
Pobierz najnowszą wersję Shaderca
Shaderc w NDK pochodzi z drzewa źródłowego Androida, które jest zrzutem przedstawnego repozytorium Shaderc. Jeśli potrzebujesz najnowszej wersji Shaderc, zapoznaj się ze szczegółami kompilacji. Ogólnie rzecz biorąc:
- Pobierz najnowszą wersję Shaderca:
git clone https://github.com/google/shaderc.git
- Zaktualizuj zależności:
./utils/git-sync-deps
- Kompilacja Shaderc:
<ndk_dir>/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \ APP_STL:=c++_static APP_ABI=all libshaderc_combined -j16
- Skonfiguruj projekt tak, aby w pliku skryptu kompilacji korzystał z własnej kompilacji Shaderc.