| src | feat: initial SPIR-V tooling bindings | |
| tests/fixtures | feat: initial SPIR-V tooling bindings | |
| .gitignore | feat: initial SPIR-V tooling bindings | |
| build.zig | feat: initial SPIR-V tooling bindings | |
| build.zig.zon | feat: initial SPIR-V tooling bindings | |
| flake.lock | feat: initial SPIR-V tooling bindings | |
| flake.nix | feat: initial SPIR-V tooling bindings | |
| LICENSE | feat: initial SPIR-V tooling bindings | |
| README.md | feat: initial SPIR-V tooling bindings | |
spirv-zig
Zig bindings around SPIR-V tooling: validation, disassembly, and reflection. Wraps SPIRV-Tools (for tools.validate and tools.disassemble) and SPIRV-Reflect (for reflect.ShaderModule). Both upstream libraries are built statically from source as part of zig build.
Requirements
- Zig 0.17.0-dev or newer (tracks Zig master).
python3onPATHat build time. SPIRV-Tools' source includes tables generated from grammar JSONs by python scripts;build.zigruns those scripts as part of the build graph rather than vendoring the outputs.
Platform Support
At the time of writing this has only been developed and tested on macOS aarch64. Linux and Windows have not been exercised (yet).
Usage
Add the dependency by running zig fetch --save 'https://codeberg.org/quint/spirv-zig/archive/<tag-or-sha>.tar.gz'.
// build.zig.zon.dependencies=.{.spirv=.{.url="https://codeberg.org/quint/spirv-zig/archive/<tag-or-sha>.tar.gz",.hash="...",},},// build.zigconstspirv=b.dependency("spirv",.{.target=target,.optimize=optimize,});my_mod.addImport("spirv",spirv.module("spirv"));Validate a SPIR-V module
constspirv=@import("spirv");consttools=spirv.tools;varctx=trytools.Context.create(.vulkan_1_4);deferctx.destroy();switch(trytools.validate(allocator,&ctx,words)){.ok=>{},.err=>|d|{deferd.deinit(allocator);std.debug.print("at word {d}: {s}\n",.{d.position.index,d.message});returnerror.InvalidShader;},}The validator runs the same checks as the spirv-val CLI. Diagnostics carry the raw SPIRV-Tools error message and the offending word offset.
Disassemble to text
switch(trytools.disassemble(allocator,&ctx,words,.{.friendly_names=true,.indent=true})){.ok=>|text|{deferallocator.free(text);std.debug.print("{s}\n",.{text});},.err=>|d|{deferd.deinit(allocator);returnerror.DisassembleFailed;},}Reflect descriptor bindings
constreflect=spirv.reflect;constmodule=tryreflect.ShaderModule.create(allocator,words);defermodule.destroy(allocator);constbindings=trymodule.descriptorBindings(allocator);deferallocator.free(bindings);for(bindings)|b|{std.debug.print("set={d} binding={d} type={d}\n",.{b.set,b.binding,b.descriptor_type});}Other enumerators on ShaderModule: descriptorSets, inputVariables, outputVariables, interfaceVariables, pushConstantBlocks, specializationConstants. Each returns a []*<element> owned by the caller and freed via allocator.free. The records the pointers refer to are owned by the module and invalidated by destroy.
Scope
This repository started life as a tool for improving the SPIR-V backend in Zig. The API is small and pragmatic:
- Tracks Zig master, not stable releases.
- Wraps the parts of SPIRV-Tools / SPIRV-Reflect that I needed.
- Missing pieces are exposed through
tools.c/reflect.cfor callers who want to drop down to the raw C API. Anything used throughcis on its own for source/binary stability.
The typed wrappers (tools.Context, tools.Diagnostic, reflect.ShaderModule, the *Options and enum types) are the surface this library aims to keep working.