Cross-compatible Zig (nightly) + GLFW + Vulkan triangle demo, wired up with:
glfw-zigfor windowing and inputvulkan-zigfor Vulkan bindings + codegen- A small but realistic graphics stack: instance, device, swapchain, pipeline, command buffers, resize handling, etc.
- How to use glfw-zig to create a Vulkan-compatible window (no client API).
- How to integrate vulkan-zig:
- Auto-generate
vk.zigfromvk.xmlat build time. - Use the generated loader (
vkb,vki,vkd) in idiomatic Zig.
- Auto-generate
- A clean separation of concerns:
graphics_context.zig– instance, device, queues, surface, allocator.swapchain.zig– swapchain creation, resize-safe recreation, per-frame sync.vertex.zig– vertex format and binding/attribute descriptions.
- SPIR-V shader compilation via
glslc, embedded with@embedFile. - Cross-platform behavior:
- Windows: LunarG Vulkan SDK +
vulkan-1.dll - macOS: MoltenVK (
libvulkan.dylib→libMoltenVK.dylib) - Linux: system Vulkan loader (
libvulkan.so)
- Windows: LunarG Vulkan SDK +
- A recent Zig 0.16.0-dev build (same major/dev line as the one used in
build.zig.zon). - Make sure
zigis on yourPATH.
You need a working Vulkan runtime + loader for your platform.
Windows
- Install the LunarG Vulkan SDK: https://vulkan.lunarg.com/sdk/home
This gives you:vulkan-1.dll(loader)- GPU drivers integration
glslcand tools
macOS
- Install the Vulkan SDK for macOS (which includes MoltenVK), or:
- Install MoltenVK + loader via your package manager (e.g. Homebrew).
- You should end up with:
libvulkan.dylibin a system or SDK locationlibMoltenVK.dylibavailable to the loader
Linux
- Install Vulkan loader + dev packages via your distro:
- e.g.
vulkan-loader,vulkan-tools, appropriate Mesa/NVIDIA/AMD drivers.
- e.g.
The build calls glslc to compile the shaders in shaders/ to SPIR-V.
- If you installed the Vulkan SDK,
glslcis already there. - Just ensure it’s on your
PATH:-
macOS example (
~/.zprofile):export PATH="$PATH:$HOME/VulkanSDK/<VERSION>/macOS/bin"
-
Windows: the SDK installer can add this automatically; otherwise add the
binfolder manually toPATH.
-
vulkan-zig generates vk.zig from the official Vulkan registry XML (vk.xml).
This project uses a “best of both worlds” approach:
- If
registry/vk.xmlexists (you’ve pinned a specific version), it is used. - Otherwise, the first
zig buildwill:- Create
registry/(if needed). - Download the latest
vk.xmlfrom the Khronos GitHub repo intoregistry/vk.xml. - Run the
vulkan-ziggenerator to producevk.zigin the Zig cache.
- Create
registry/vk.xml is git-ignored so your repo stays light, but you still get reproducible builds once it’s been fetched once.
You normally don’t need to do anything manually. Just:
zig buildand let the build script handle it.
If you want to pin a specific registry version (e.g. for long-term reproducibility):
-
Download
vk.xmlfrom the Vulkan-Docs repo. -
Place it at
registry/vk.xml. -
Commit everything except
vk.xmlitself (it remains in.gitignore)
git clone https://github.com/James-Riordan/zig-glfw-vulkan-openxr.git
cd zig-glfw-vulkan-openxrBuild & run in one go:
zig build runOn the first build, you will see steps like:
run exe vulkan-zig-generator (vk.zig)run curl (vk.xml)run glslc (triangle_vert.spv)run glslc (triangle_frag.spv)
After that, incremental builds will be much faster.
You should see a window with a colored triangle rendered via Vulkan. Resizing the window will trigger a safe swapchain recreation (tested on Windows + macOS via MoltenVK)
High-level structure (only the interesting bits):
zig-glfw-vulkan-openxr/
├─ src/
│ ├─ main.zig # Entry point; GLFW loop, wiring everything together
│ └─ graphics/
│ ├─ graphics_context.zig # Vulkan instance, device, queues, surface, allocator
│ ├─ swapchain.zig # Swapchain + per-frame sync + resize-safe recreation
│ └─ vertex.zig # Vertex struct + binding/attribute descriptions
├─ shaders/
│ ├─ triangle.vert # GLSL vertex shader
│ └─ triangle.frag # GLSL fragment shader
├─ registry/
│ └─ vk.xml # (ignored by git) Vulkan registry; auto-fetched if absent
├─ build.zig # Build script: deps, shader compilation, vk.xml handling
├─ build.zig.zon # Zig package dependencies (glfw-zig, vulkan-zig)
└─ README.md # You are herecurl: command not found
- Install
curland ensure it’s on yourPATH. The build uses it once to downloadvk.xmlif it’s missing.
glslc: command not found
-
Install the Vulkan SDK or
glslcvia your package manager. -
Confirm
glslcis visible in your terminal shell (glslc --version).
IncompatibleDriver / Vulkan initialization errors
-
Usually means:
-
No Vulkan-capable GPU/driver.
-
MoltenVK / Vulkan loader not properly installed or discoverable.
-
-
On macOS, double-check your Vulkan SDK / MoltenVK install and that
libvulkan.dylib+libMoltenVK.dylibare in the expected locations.
Weird crashes on window resize
-
This codebase already includes a safe swapchain recreation path (create new swapchain first, then tear down the old one).
-
If you see issues, they’re likely from:
-
A partially broken Vulkan install.
-
Very old drivers / SDK.
-
-
Updating your Vulkan SDK + GPU drivers usually resolves it.
That’s it. This repo is meant to be a clean, minimal reference for:
-
glfw-zigwindowing -
vulkan-zigintegration -
A small but realistic Vulkan render loop in Zig
From here you can start layering in descriptor sets, depth buffers, multiple pipelines, or (eventually) OpenXR on top