Extract Push Constants from SPIR-V Binaries
When configuring graphics pipelines in modern APIs like Vulkan, applications must match pipeline layout definitions precisely to the push constant ranges and shader stage flags declared in shader code. This article explains the primary tools used to inspect compiled GLSL SPIR-V binaries to extract push constant offsets, byte sizes, and execution stage flags, focusing on the industry standard, SPIRV-Reflect, alongside alternatives like SPIRV-Cross.
The Primary Tool: SPIRV-Reflect
The most direct and lightweight tool for extracting push constant data and stage flags from SPIR-V bytecode is SPIRV-Reflect, an open-source C/C++ library maintained by Khronos Group. Designed specifically for runtime reflection, it parses SPIR-V modules without requiring a full compiler infrastructure.
When inspecting a compiled SPIR-V binary, SPIRV-Reflect populates internal structures representing shader resources. For push constants, it identifies:
- Byte Offsets and Sizes: Extracted via
SpvReflectBlockVariable, detailing the relative byte offset and total size of each push constant member or block. - Stage Flags: Extracted via the module's execution
model, which directly translates to Vulkan
VkShaderStageFlagBits(such as vertex, fragment, or compute).
Using its C API, developers can call
spvReflectEnumeratePushConstantBlocks() on an initialized
SpvReflectShaderModule to retrieve an array of push
constant blocks. Each block reports its offset,
size, padded_size, and the associated shader
stage, allowing automated generation of VkPushConstantRange
structs at runtime.
Alternative Option: SPIRV-Cross
While primarily an intermediate language transpiler, SPIRV-Cross is another widely used tool capable of static shader reflection.
Through its Compiler API, calling
get_shader_resources().push_constant_buffers returns all
push constant declarations in the module. Developers can inspect
individual struct members using get_active_buffer_ranges()
to resolve explicit byte ranges, offsets, and member types, while
checking the active spv::ExecutionModel to determine the
target stage flag.
Command-Line Inspection: spirv-dis
For manual debugging without programmatic integration, the
spirv-dis disassembler from the official
SPIRV-Tools suite can be used. Running
spirv-dis converts the binary into human-readable SPIR-V
assembly text:
- Push constants appear under the
OpTypePointer PushConstantdeclaration. - Byte layouts appear as
OpMemberDecorateinstructions specifying theOffsetdecoration for each struct field. - Pipeline stages are specified at the top of the file via
OpEntryPointdirectives.