Aplikasi Vulkan harus mengelola shader dengan cara yang berbeda dari aplikasi OpenGL ES: Di OpenGL ES, Anda menyediakan shader sebagai sekumpulan string yang membentuk teks sumber program shader GLSL. Sebaliknya, Vulkan API mengharuskan Anda menyediakan shader dalam bentuk titik entri dalam modul SPIR-V.
NDK Rilis 12 dan yang lebih baru menyertakan library runtime untuk mengompilasi GLSL ke dalam
SPIR-V. Library runtime ini sama seperti yang ada di
project open source Shaderc dan menggunakan compiler
referensi Glslang GLSL yang sama seperti
backend-nya. Secara default, versi Shaderc compiler menganggap Anda mengompilasi untuk Vulkan. Setelah memastikan validitas kode Anda untuk Vulkan, compiler otomatis mengaktifkan ekstensi KHR_vulkan_glsl
. Versi Shaderc compiler juga menghasilkan kode SPIR-V yang sesuai dengan Vulkan.
Anda dapat memilih untuk mengompilasi modul SPIR-V ke dalam aplikasi Vulkan selama tahap pengembangan, melalui praktik yang disebut kompilasi ahead-of-time, atau AOT. Atau, Anda dapat meminta aplikasi agar mengompilasi modul dari sumber shader yang dikirim atau dihasilkan sesuai prosedur saat diperlukan selama runtime. Praktik ini disebut kompilasi runtime. Android Studio memiliki dukungan terintegrasi untuk membangun shader Vulkan.
Bagian selanjutnya di halaman ini memberikan detail selengkapnya tentang setiap praktik di atas, lalu menjelaskan cara mengintegrasikan kompilasi shader ke dalam aplikasi Vulkan.
Kompilasi AOT
Ada dua cara untuk melakukan kompilasi AOT shader, yang dijelaskan di bagian berikut.
Menggunakan Android Studio
Dengan menempatkan shader ke dalam app/src/main/shaders/
, Android Studio akan mengenali shader berdasarkan
ekstensi filenya dan akan menyelesaikan tindakan berikut:
- Mengompilasi semua file shader secara rekursif pada direktori itu.
- Menambahkan akhiran .spv ke file shader SPIR-V yang telah dikompilasi.
- Memaketkan shader SPIRV ke dalam direktori
assets/shaders/
APK.
Aplikasi akan memuat shader yang dikompilasi dari lokasi assets/shaders/
yang sesuai pada runtime; struktur file shader spv yang dikompilasi sama dengan struktur file shader GLSL aplikasi di 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);
Flag kompilasi Shaderc dapat dikonfigurasi dalam blok shaders
DSL gradle, sebagaimana ditunjukkan dalam contoh berikut:
Groovy
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
berlaku untuk semua kompilasi shader; scopedArgs
hanya berlaku saat mengompilasi
untuk cakupan tersebut. Contoh di atas membuat argumen cakupan lights
, yang hanya akan berlaku untuk shader GLSL dalam direktori app/src/main/shaders/lights/
. Lihat glslc untuk daftar lengkap flag kompilasi yang tersedia. Perlu diketahui bahwa Shaderc di dalam NDK adalah snapshot dari repositori github pada saat
NDK dirilis; Anda dapat memperoleh flag yang didukung secara persis untuk versi tersebut dengan perintah
glslc --help
, sebagaimana dijelaskan di bagian selanjutnya.
Kompilasi command line offline
Shader GLSL dapat dikompilasi ke SPIR-V tanpa bergantung pada aplikasi utama menggunakan compiler command line glslc. NDK rilis 12 dan yang lebih baru memaketkan versi glslc bawaan dan alat terkait
dalam direktori <android-ndk-dir>/shader-tools/
untuk mendukung model penggunaan ini.
Compiler ini juga tersedia dari project Shaderc; ikuti petunjuk di sana untuk mem-build versi biner.
glslc menyediakan kumpulan lengkap opsi command line untuk kompilasi shader guna memenuhi berbagai persyaratan aplikasi.
Alat glslc mengompilasi file sumber tunggal ke modul SPIR-V dengan titik entri shader tunggal. Secara default, file output memiliki nama yang sama seperti file sumber,
tetapi dengan tambahan ekstensi .spv
.
Ekstensi nama file digunakan untuk memberi tahu alat glslc tahap shader grafis yang akan dikompilasi, atau apakah shader komputasi sedang dikompilasi. Untuk informasi tentang cara menggunakan ekstensi nama file ini dan opsi yang dapat digunakan dengan alat tersebut, lihat Spesifikasi tahap Shader dalam panduan glslc.
Kompilasi runtime
Untuk kompilasi JIT shader selama runtime, NDK menyediakan library libshaderc, yang memiliki C API dan C++ API.
Aplikasi C++ harus menggunakan C++ API. Kami merekomendasikan agar aplikasi dalam bahasa lain menggunakan C API, karena C ABI adalah level yang lebih rendah dan cenderung memberikan stabilitas yang lebih baik.
Contoh berikut menunjukkan cara menggunakan C++ API:
#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; }
Mengintegrasikan ke dalam project
Compiler shader Vulkan dapat diintegrasikan ke dalam aplikasi menggunakan file Android.mk
project atau Gradle.
Android.mk
Lakukan langkah-langkah berikut ini untuk menggunakan file Android.mk
project Anda guna mengintegrasikan compiler shader.
-
Sertakan baris berikut ke file Android.mk Anda:
include $(CLEAR_VARS) ... LOCAL_STATIC_LIBRARIES := shaderc ... include $(BUILD_SHARED_LIBRARY) $(call import-module, third_party/shaderc)
-
Tetapkan APP_STL ke salah satu dari
c++_static
,c++_shared
,gnustl_static
, ataugnustl_shared
dalam Application.mk aplikasi
Integrasi CMake Gradle
-
Di jendela terminal, buka
ndk_root/sources/third_party/shaderc/
. -
Jalankan perintah berikut untuk membuat Shaderc NDK. Perintah ini hanya perlu dijalankan sekali pada setiap versi NDK yang Anda gunakan:
$ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \ APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
Perintah ini menempatkan dua folder di <ndk_root>/sources/third_party/shaderc/. Struktur direktorinya adalah sebagai berikut:
include/ shaderc/ shaderc.h shaderc.hpp libs/ <stl_version>/ {all of the abis} libshaderc.a
-
Tambahkan include dan lib yang dihasilkan menggunakan
target_include_directories
dantarget_link_libraries
, seperti yang biasa dilakukan untuk library eksternal serupa. Jenis STL aplikasi Anda harus cocok dengan salah satu dari jenisstl
yang ditentukan dalamstl_version
. NDK merekomendasikan penggunaanc++_shared
atauc++_static
, meskipungnustl_static
dangnustl_shared
juga didukung.
Mendapatkan Shaderc terbaru
Shaderc di NDK berasal dari pohon Sumber Android, yang merupakan snapshot repositori Shaderc upstream. Jika memerlukan Shaderc terbaru, baca petunjuk proses build untuk detailnya. Langkah-langkah tingkat tingginya adalah sebagai berikut:
- Download Shaderc terbaru:
git clone https://github.com/google/shaderc.git
- Dependensi update:
./utils/git-sync-deps
- Shaderc build:
<ndk_dir>/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \ APP_STL:=c++_static APP_ABI=all libshaderc_combined -j16
- Konfigurasikan project agar menggunakan build Shaderc milik Anda sendiri dalam file skrip build Anda.