page.title=Vulkan Shader Compilers on Android @jd:body
A Vulkan app must manage shaders differently from the way an OpenGL ES app does so: In OpenGL ES, you provide a shader as a set of strings forming the source text of a GLSL shader program. By contrast, the Vulkan API requires you to provide a shader in the form of an entry point in a SPIR-V module.
The NDK includes a runtime library for compiling GLSL into SPIR-V. The runtime library is the same as the one in the Shaderc open source project, and use the same Glslang GLSL reference compiler as a back end. By default, the Shaderc version of the compiler assumes you are compiling for Vulkan. After checking whether your code is valid for Vulkan, the compiler automatically enables the {@code KHR_vulkan_glsl} extension. The Shaderc version of the compiler also generates Vulkan-compliant SPIR-V code.
You can choose to compile SPIR-V modules into your Vulkan app during development, a practice called ahead-of-time, or AOT, compiling. Alternatively, you can have your app compile them from shipped or procedurally generated shader source when needed during runtime. This practice is called runtime compiling.
The rest of this page provides more detail about each practice, and then explains how to integrate shader compilation into your Vulkan app.
For AOT compilation, we recommend the glslc command-line compiler from GLSL to SPIR-V. This compiler is available from the Shaderc project.Many of its command-line options are similar to those of GCC and Clang, allowing you to integrate glslc into build systems easily.
The glslc tool compiles a single-source file to a SPIR-V module with a single shader entry point. By default, the output file has the same name as that of the source file, but with the {@code .spv} extension appended.
You use filename extensions to tell the glslc tool which graphics shader stage to compile, or whether a compute shader is being compiled. For information on how to use these filename extensions, and options you can use with the tool, see Shader stage specification in the glslc manual.
For JIT compilation of shaders during runtime, the NDK provides the libshaderc library, which has both C and C++ APIs.
C++ applications should use the C++ API. We recommend that apps in other languages use the C API, because the C ABI is lower level, and likely to provide better stability.
The following example shows how to use the 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;
}
You can integrate the Vulkan shader compiler into your app using either the project's {@code Android.mk} file or Gradle.
Perform the following steps to use your project's {@code Android.mk} file to integrate the shader compiler.
include $(CLEAR_VARS)
...
LOCAL_STATIC_LIBRARIES := shaderc
...
include $(BUILD_SHARED_LIBRARY)
$(call import-module, third_party/shaderc)
$ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \ APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
This command places two folders in <ndk_root>/sources/third_party/shaderc/. The directory structure is as follows:
include/
shaderc/
shaderc.h
shaderc.hpp
libs/
<stl_version>/
{all of the abis}
libshaderc.a
The STL that you use to build your program must match the {@code stl} specified in {@code stl_version}. Only {@code c++_static}, {@code c++_shared}, {@code gnustl_static}, and {@code gnustl_shared} are supported.