Expand description
Build-script support for Henad model crates.
stamp_commit records the commit a crate was built from, a dirty flag and a hash of its sources, for
henad::build_info! to read. ShaderBuild generates the Rust bindings of a crate’s WGSL shaders, from its build
script. Each shader is composed with the shared modules it reaches through #import henad::<module>, whose text
comes from henad-core’s SHARED_WGSL_MODULES. henad::include_shaders! then brings the two generated files
into the crate, as the modules shader_bindings and binding_decls.
// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
henad_build::stamp_commit();
henad_build::ShaderBuild::discover("src")?.generate()?;
Ok(())
}A crate without shaders keeps the build script for its stamp, and drops the ShaderBuild line.
§Names
A shader’s path below the shader root becomes three Rust names. gpu_vote/step.wgsl gives the module
shader_bindings::gpu_vote::step, the ShaderEntry variant GpuVoteStep and the binding constant
binding_decls::bindings::GPU_VOTE_STEP. The constant is the path’s components upper-cased and joined by _, with
the final .wgsl removed, so my_wgsl/step.wgsl gives MY_WGSL_STEP. Every component of a .wgsl file’s path is
therefore a Rust identifier and not a keyword.
A file with a #define_import_path line is a module other shaders import, and never an entry point. An import
resolves by file path alone. A module’s import path mirrors its path below the shader root, or below the directory
of the file that imports it, as #define_import_path gpu_vote::state in gpu_vote/state.wgsl. The bindings refer
to an imported module by the import path it resolved through, and to a quoted import by the stem of its file name,
as #import "std.inc" gives the module std.
The root henad is reserved for the shared modules, regardless of case. A file named henad.wgsl or a directory
named henad holding a .wgsl file would shadow them, and both are rejected. So is a .wgsl path whose first
component is a name the generated bindings use at their root: wgpu, bytemuck, std, core, alloc, _root,
ShaderEntry, layout_asserts or bytemuck_impls. An import is rejected too when its module path in the bindings
starts with henad or one of those names.
Note that each struct’s layout assertion is named after the struct’s module path and name in upper snake case.
gpu_vote::step::TallyParams and gpu_vote::step_tally::Params both give
GPU_VOTE_STEP_TALLY_PARAMS_ASSERTS, and rustc reports the two inside the generated file. Rename one of the
structs.
§Bindings
binding_decls::bindings holds each entry point’s @group(0) declarations, in @binding order, read from lines
of one form: @group(0) @binding(N) var<...> name: Type;. A line holding @binding or @group in any other form
fails the build. A compile-time assertion checks each list against the length of the layout wgsl_bindgen
derives. A module declares no bindings, and a line holding @binding in a module fails the build too.
§Versions
henad-build pins wgsl_bindgen to 0.23.3 and fixes the code it generates. Cargo keeps one release per
semver-compatible range in a lockfile. A build script that runs wgsl_bindgen itself therefore uses 0.23.3 as
well. Use the same 0.x of henad and henad-build. include_shaders! fails the build when the shaders were composed
against different shared WGSL than the linked henad provides.
Structs§
- Shader
Build - One crate’s shader-binding generation, run from its build script.
Enums§
- Shader
Build Error - Reason a shader build fails.
Functions§
- stamp_
commit - Stamps the crate whose build script calls it with its commit, a dirty flag and a hash of its sources.