Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Vulkane
Vulkan for Rust: complete bindings generated from the official vk.xml
specification, plus a safe RAII wrapper that covers compute and graphics
end-to-end — from instance creation through shadow mapping and deferred
shading.
What is Vulkane?
Vulkane generates complete Vulkan API bindings from vk.xml, the
official machine-readable specification maintained by Khronos. Every
type, constant, struct, enum, function pointer, and dispatch table is
derived at build time. Nothing is hardcoded.
To target a different Vulkan version, swap vk.xml and rebuild.
Vulkane exposes Vulkan through two complementary APIs:
-
vulkane::raw— direct FFI bindings, exactly as the spec defines them. Maximum control, zero overhead. -
vulkane::safe— RAII wrappers with automatic cleanup,Result-based error handling, typed flags, and convenience helpers. Covers compute and graphics:- Instance / Device —
Instance,PhysicalDevice,PhysicalDeviceGroup,Device,Queue,DeviceFeaturesbuilder (1.0 / 1.1 / 1.2 / 1.3 features). - Memory —
Buffer,Image,ImageView,Sampler,DeviceMemory, plus a VMA-style sub-allocator (Allocator) with TLSF + linear pools, custom pools, dedicated allocations, persistent mapping, defragmentation, and budget queries. - Convenience helpers —
Buffer::new_bound,Image::new_2d_bound,Queue::upload_buffer<T>,Queue::upload_image_rgba,Queue::one_shot— collapse the 5-step allocate-bind pattern into one call. - Compute —
ComputePipeline,PipelineLayout,DescriptorSet,ShaderModule, specialization constants, pipeline cache, push constants. - Graphics —
RenderPass(withsimple_colorshortcut),Framebuffer,GraphicsPipelineBuilder(depth bias,CompareOp,InputRate, multi-attachment blend, dynamic viewport/scissor),Surface(Win32 / Wayland / Xlib / Xcb / Metal),Swapchain. - Synchronization — typed
PipelineStage/AccessFlags(plus 64-bitPipelineStage2/AccessFlags2for Sync2),Fence,Semaphore(binary + timeline),ImageBarrier::color/::depth,ClearValue,QueryPool. - Derive macros —
#[derive(Vertex)]auto-generates vertex input layouts from#[repr(C)]structs (optionalderivefeature). - Extension ergonomics (0.8+) — curated safe wrappers for
ray tracing (
AccelerationStructure,RayTracingPipeline,cmd_trace_rays), external memory/semaphore interop (DeviceMemory::get_win32_handle/get_fdfor CUDA / HIP / DX12 bridging), timeline semaphores, synchronization 2 (memory_barrier2/image_barrier2/buffer_barrier2), push descriptors, dynamic rendering (begin_rendering), descriptor buffer, subgroup size control, memory priority, and shader integer dot product properties. Every safe create-info builder now exposes apnextextension point so any unwrapped extension struct can be layered on without dropping to raw. - Generated ergonomic traits (0.8+) — alongside the raw
per-command
DeviceExt/InstanceExt/CommandBufferRecordingExttraits, the build emits a second tier —DeviceSafeExt,InstanceSafeExt,PhysicalDeviceSafeExt,QueueSafeExt,CommandBufferRecordingSafeExt— with idiomatic signatures (slices for slice-params,Result<Vec<T>>for(count, data)enumerate pairs, references for input structs, return-by-value for single output params). 545 generated ergonomic methods cover ~70% of the extension surface mechanically. - Raw escape hatch —
Device::dispatch()/Instance::dispatch()expose the full dispatch tables so you can drop to raw Vulkan for anything the safe wrapper doesn't cover yet.
- Instance / Device —
Quick Start
[]
= { = "0.10", = ["fetch-spec"] }
use ;
Bundled Examples
15 examples ship with the crate, from basic compute through advanced
graphics techniques. All are headless (runnable in CI) except
windowed_triangle.
| Example | Technique |
|---|---|
device_info |
Raw API: instance, physical device enumeration, queue families |
fill_buffer |
Safe API: vkCmdFillBuffer round trip |
compute_square |
Compute: SPIR-V, descriptor set, pipeline, dispatch, verify |
compute_image_invert |
Compute: 2D storage image, layout transitions, per-pixel verify |
compile_shader |
Compile GLSL/WGSL → SPIR-V via naga (--features naga) |
headless_triangle |
Graphics: render pass, pipeline, draw, readback |
textured_quad |
Graphics: texture upload, sampler, WGSL fragment shader |
windowed_triangle |
Windowed: winit + surface + swapchain + present loop |
buffer_upload |
Queue::one_shot staging upload pattern |
allocator_compute |
Allocator::create_buffer — 2 lines vs 5 |
raw_interop |
Device::dispatch() + .raw() escape hatch |
depth_prepass |
Depth-only pass + color EQUAL — early-Z prepass |
instanced_mesh |
100 triangles via InputRate::INSTANCE |
shadow_map |
Two-pass shadow mapping: depth bias, comparison sampler, uniform buffers |
deferred_shading |
G-buffer (3 MRT) + fullscreen Phong lighting pass |
derive_vertex |
#[derive(Vertex)] auto-generated vertex layouts (--features derive) |
#[derive(Vertex)]
Enable the derive feature to auto-generate vertex input layouts:
= { = "0.4", = ["fetch-spec", "derive"] }
use Vertex;
// In pipeline setup:
let bindings = ;
let attributes = attributes;
builder.vertex_input
Strides, offsets, and Vulkan format enums are computed at compile time.
Supports f32, [f32; 2..4], u32, [u32; 2..4], i32,
[i32; 2..3], [u8; 4], u16, i16. For per-instance data, use
MyStruct::instance_binding(n) instead of ::binding(n).
Precompiled shader registry
For applications that ship precompiled .spv artifacts (embedded with
include_bytes! or shipped alongside the binary),
[vulkane::safe::ShaderRegistry] gives you a small, shared abstraction
for looking up shaders by name — plus an optional runtime disk
override for shader developers iterating without a full rebuild.
use ;
// Embedded at compile time. `include_bytes!` resolves paths relative
// to the file that invokes it, so the macro call lives in your crate.
const EMBEDDED: & = &;
// Later, when you have a Device:
let module = app_shaders.load_module?;
Lookup order when an override var is configured:
$MY_APP_SHADER_OVERRIDE_DIR/doubler.spvon disk (if the directory and file both exist).- Fall back to the embedded table.
ShaderRegistry::load(name) returns the SPIR-V bytes,
load_words(name) returns a Vec<u32> ready for
[ShaderModule::from_spirv], and load_module(&device, name) wraps
the whole pipeline. Lookup errors flow through
ShaderLoadError
into the unified Error::ShaderLoad variant.
Runtime shader compilation
Vulkane offers two optional, independent back-ends for compiling shader source to SPIR-V at runtime. Enable one, the other, or both — they are completely separate modules.
naga — pure Rust (WGSL + subset of GLSL)
Zero external build dependencies. Best choice when:
- You want a pure-Rust build (no CMake, no C++ toolchain).
- You are targeting modern GLSL or WGSL.
- WGSL's combined image-samplers fit your rendering code.
= { = "0.4", = ["naga"] }
use compile_glsl;
use ShaderStage;
let spirv = compile_glsl?;
// Pass straight into ShaderModule::from_spirv(&device, &spirv).
shaderc — Khronos glslang (full GLSL + HLSL)
Wraps the Khronos reference compiler. Best choice when:
- You need full GLSL support (
#include,GL_*extensions, older core versions, legacy sample shaders). - You are compiling HLSL for a Vulkan target.
- You want optimization passes (
OptimizationLevel::SizeorPerformance) or explicit macro defines / include resolution.
= { = "0.4", = ["shaderc"] }
use ;
let spirv = compile_glsl?;
For fine-grained control — HLSL input, optimization level, macro
defines, include callbacks, target Vulkan version — use
compile_with_options:
use ;
use OptimizationLevel;
let spirv = compile_with_options?;
Build requirements for shaderc
shaderc-rs locates libshaderc in this order:
SHADERC_LIB_DIRenv var — point to a directory containinglibshaderc_combined.VULKAN_SDKenv var — installing the LunarG Vulkan SDK sets this automatically, and ships a prebuiltlibshaderc_combined. This is the easiest path.pkg-config/ system libraries (typical on Linux distros that packageshaderc).- Source build fallback — compiles glslang from C++ source.
Requires CMake ≥ 3.17 (newer CMake may need
CMAKE_POLICY_VERSION_MINIMUM=3.5until shaderc-sys updates its pinned sources), Python 3, and a working C++ toolchain. First build takes 1–3 minutes.
If neither the SDK nor a system package is available and you don't
want to build from source, use the naga feature instead.
When to pick which
| Need | naga |
shaderc |
|---|---|---|
| Pure Rust build (no C++ toolchain) | ✅ | ❌ |
| Modern GLSL (core, no extensions) | ✅ | ✅ |
Full GLSL (#include, GL_* exts) |
❌ | ✅ |
| HLSL input | ❌ | ✅ |
| WGSL input | ✅ | ❌ |
| Optimization passes | ❌ | ✅ |
| Smallest binary / fastest cold build | ✅ | ❌ |
Both features can be enabled simultaneously — pick per shader at the call site.
slang — Khronos Slang (modules, generics, autodiff)
Slang is Khronos's modern shading language. Pick it when you need:
- Modules, generics, and interfaces — real code reuse in shaders.
- Automatic differentiation — tag a function
[Differentiable]and the compiler generates forward (__fwd_diff) and backward (__bwd_diff) variants. A single kernel definition yields both the forward and backward SPIR-V, which is a game-changer for ML compute on Vulkan. - Explicit entry points — one
.slangfile can expose many compute / vertex / fragment entry points; compile each to its own SPIR-V blob from the same parsed module.
= { = "0.4", = ["slang"] }
Slang compilation is stateful — a session holds the SPIR-V target and search paths, modules are loaded by name through those paths, and each entry point is compiled on demand:
use SlangSession;
// Given kernels/autodiff.slang with [Differentiable] functions and
// both `forward` and `backward` compute entry points:
let session = with_search_paths?;
let module = session.load_file?; // parses once
let fwd = module.compile_entry_point?; // Vec<u32> SPIR-V
let bwd = module.compile_entry_point?; // Vec<u32> SPIR-V
Or for a one-off compile:
use compile_slang_file;
let spirv = compile_slang_file?;
Build requirements for slang
shader-slang locates the Slang compiler via:
VULKAN_SDKenv var — the LunarG Vulkan SDK shipsslangcand the Slang runtime library. Easiest path (same asshaderc).SLANG_DIRenv var — a standalone Slang install from shader-slang/slang releases.SLANG_INCLUDE_DIR+SLANG_LIB_DIR— split paths.
At runtime, slang.dll / libslang.so / libslang.dylib must be
discoverable (same directory as the executable, or on the library
search path).
Current limitation
shader-slang 0.1.0 on crates.io only supports loading Slang modules
from disk (via search-path resolution). Inline source strings will be
supported once a newer shader-slang release exposes them; until then,
keep your Slang code in .slang files.
Why Vulkane over ash?
| Aspect | Vulkane | ash |
|---|---|---|
| Source of truth | vk.xml at build time |
Hand-curated bindings |
| New Vulkan version | Swap vk.xml, rebuild | Wait for crate update |
| Safe wrapper | Built-in: compute + graphics + allocator + sync | Raw FFI only |
| Sub-allocator | TLSF + linear pools + defrag built in | BYO (gpu-allocator) |
| Vertex layout | #[derive(Vertex)] |
Manual |
| Pipeline builder | Depth bias, CompareOp, multi-attach, dynamic viewport | N/A (raw structs) |
| Allocation helpers | Buffer::new_bound, Queue::upload_buffer<T> |
N/A |
| GLSL/WGSL→SPIR-V | Optional naga (pure Rust), shaderc (glslang), or slang (Slang + autodiff) feature |
N/A |
| Raw escape hatch | device.dispatch() + .raw() |
N/A (always raw) |
| Maturity | New (0.4) | Battle-tested |
Features
| Feature | Description |
|---|---|
build-support (default) |
XML parsing and code generation during build |
fetch-spec |
Auto-download vk.xml from Khronos GitHub |
naga |
compile_glsl + compile_wgsl → SPIR-V at runtime (pure Rust) |
shaderc |
compile_glsl / compile_with_options → SPIR-V via Khronos glslang (full GLSL + HLSL) |
slang |
SlangSession / compile_slang_file → SPIR-V via Khronos Slang (modules, generics, autodiff) |
derive |
#[derive(Vertex)] proc macro for vertex layouts |
Providing vk.xml
You usually do not have to. A vk.xml ships inside the published crate, so
cargo add vulkane builds with no configuration, no network, and no feature
flags. The rest of this section is for overriding that.
The build resolves a spec in this order and takes the first that exists:
| route | for | |
|---|---|---|
| 1 | VK_XML_PATH — use an absolute path. A relative one is tried as given (against this crate's directory), then against its parent — cargo's registry cache for a dependency, so neither base is one you control |
anyone pinning a different spec revision |
| 2 | Bundled copy at <crate>/vk.xml |
the default for dependents — ships in the crate, which is also why docs.rs and other sandboxed builds work offline |
| 3 | Workspace copy at ../spec/registry/Vulkan-Docs/xml/vk.xml |
this repository only — the path is read from CARGO_MANIFEST_DIR, which for a dependency is inside cargo's registry cache |
| 4 | Auto-download, --features fetch-spec, optionally pinned with VK_VERSION=1.3.250 |
when no copy is present, or to fetch a specific release |
Because route 2 is present in every published version, fetch-spec is a fallback
rather than a requirement. If every route fails the build errors with all of them
named, rather than with a missing-file diagnostic.
Supported Vulkan Versions
1.2.175 through the latest release. The minimum is set by the
VK_MAKE_API_VERSION macros introduced in that version.
Architecture
vk.xml → vulkan_gen (roxmltree parser + codegen) → vulkane crate
├── raw/ (generated FFI bindings)
├── safe/ (RAII wrapper)
└── vulkane_derive (proc macros)
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in vulkane by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.