1
0
Fork
You've already forked spirv-zig
0
Idiomatic Zig wrappers around the Khronos SPIR-V toolchain.
  • Zig 95.8%
  • Nix 4.2%
2026年05月21日 19:42:33 +02:00
src feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
tests/fixtures feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
.gitignore feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
build.zig feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
build.zig.zon feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
flake.lock feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
flake.nix feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
LICENSE feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00
README.md feat: initial SPIR-V tooling bindings 2026年05月21日 19:42:33 +02:00

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).
  • python3 on PATH at build time. SPIRV-Tools' source includes tables generated from grammar JSONs by python scripts; build.zig runs 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.c for callers who want to drop down to the raw C API. Anything used through c is 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.