Slang shader compilation (SPIR-V + WGSL)#
Two behaviourally identical drivers compile a Slang shader tree:
Lane |
File |
|---|---|
Linux / POSIX |
|
Windows |
|
They must be kept in step. Both are project-agnostic — nothing about a
specific project is hard-coded. A thin wrapper sets the path variables, sources
the library, and calls slang_compile_main. Everything else is data, read from
a manifest JSON the wrapper points at.
The shell library deliberately does not set -e/-u/-o pipefail, so sourcing
it cannot change the caller’s shell options; wrappers run under
set -euo pipefail themselves.
Caller variables#
Required:
Variable |
Meaning |
|---|---|
|
the manifest JSON (schema below) |
|
root of the |
Optional (default in the right column):
Variable |
Meaning |
Default |
|---|---|---|
|
where |
|
|
where |
|
|
staging dir for the combined WGSL emit, before validation and copy |
|
|
root the manifest’s |
|
Manifest schema#
Keys starting with _ are documentation and ignored.
Key |
Shape |
Meaning |
|---|---|---|
|
|
one row per (entry point, target). |
|
|
the combined (whole-module) WGSL emit |
|
|
post-emit regex patches applied to that combined emit |
|
|
toolchain floor for the combined emit |
Return codes from slang_compile_main#
Code |
Meaning |
|---|---|
0 |
success — also when the source root is absent and there is nothing to do |
1 |
a |
2 |
a prerequisite is missing ( |
Code 2 is deliberately not a silent skip: a missing slangc once let CI pass
green with no compiled shaders at all.
The combined-emit outcomes#
_slang_emit_one_wgsl handles one wgslMap row and reports which of four
things happened; slang_compile_combined_wgsl owns the counters and turns them
into the summary line and the exit code.
Return |
Meaning |
What the caller does |
|---|---|---|
0 |
emitted, patched, validated, copied to |
counts it into |
1 |
|
records the source in the emit-failed WARN block; the run still exits 0 |
2 |
the emit has a varying struct member with neither |
records it in |
3 |
the row names a source file that is not in the tree |
nothing — a row can point at a shader another repo owns |
The asymmetry between 1 and 2 is deliberate. A failed slangc is a build
problem the log already shows; an emit that succeeded and is structurally
wrong is the regression this guard exists for, because the only thing standing
between it and a committed, naga-rejected shader is that exit code. In both
cases the destination file is left exactly as it was: nothing is copied until
the validator has passed.
The guard exists because slangc 2026.1 (the Vulkan SDK build in the Linux image)
drops @location(N) from varying struct members in the combined emit while
emitting it per entry point, so a regeneration yields WGSL naga rejects. Two
defences are both needed: below minSlangcVersionForWgsl nothing is emitted, so
the checked-in WGSL is never overwritten, and at or above it every emit is
validated. The manifest is read with python3, not jq, because the image has no jq.
A depthTexturePatches pattern that matches nothing is a WARNING, not a
refusal — it means slangc’s output moved under the pattern, which is worth
seeing but is not itself proof the emit is wrong.
Staleness#
An output is reused only when it is newer than its source and every .slang
file under the source tree and the manifest file itself. That is
conservative on purpose — an import or a manifest edit rebuilds every dependent.