ANGLE converts application shaders into Vulkan VkShaderModules through a series of steps:
ANGLE Internal Translation: The initial calls to glCompileShader
are passed to the ANGLE shader translator. The translator compiles application shaders into SPIR-V, after transforming GLSL to conform to the GL_KHR_vulkan_glsl extension spec with some additional workarounds and emulation. We emulate OpenGL's different depth range, viewport y flipping, default uniforms, and emulate a number of extensions among others. For more info see TranslatorVulkan.cpp. After initial compilation, the SPIR-V blobs are not complete. The translator initially assigns resources and in/out variables arbitrary descriptor set, binding and location indices. The correct values are determined at link time. For the sake of transform feedback, some additional code is generated to be removed or modified during SPIR-V transformation.
The translator outputs some feature code conditional to Vulkan specialization constants, which are resolved at draw-time. For example, for emulating Dithering and Android surface rotation.
Link Time: During a call to glLinkProgram
the Vulkan back-end can know the necessary locations and properties to write to connect the shader stage interfaces. However, some draw-time information is still necessary to finalize the SPIR-V; for example whether “early fragment tests” can be enabled. As an optimization, the SPIR-V is transformed with arbitrary settings and a Vulkan pipeline object is created in an attempt to warm the Vulkan pipeline cache.
Draw-Time SPIR-V Transformation and Pipeline Creation: Once the application records a draw call, a transformation pass is done on the generated SPIR-V to update the arbitrary descriptor set, binding and location indices set in step 1. Additionally, component and various transform feedback decorations are added, inactive varyings are removed, early fragment tests are enabled or disabled, debug info is removed and pre-rotation is applied. At this time, VkShaderModule
s are created (and cached). The appropriate specialization constants are then resolved and the VkPipeline
object is created (see details here). Note that we currently don't use SPIRV-Tools to perform any SPIR-V optimization. This could be something to improve on in the future.
See the below diagram for a high-level view of the shader translation flow: