Skip to content

The kernel's variants by WESL's conditional translation, and the repository's Rust pinned (1.100.0) - #70

Merged
yujiaxu-ops merged 1 commit into
mainfrom
kernel-wesl
Nov 13, 2026
Merged

yujiaxu-ops merged 1 commit into
mainfrom
kernel-wesl

Conversation

@yujiaxu-ops

@yujiaxu-ops yujiaxu-ops commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Item 6 of the renderer review (6a): the kernel's variants without text patches. One PR, as agreed, together with pinning the toolchain that wesl-rs needs.

The kernel

Before: the kernel was made for a device and a scene by patching its text.

  • The hardware traversal was cut in at markers (kernel_base).
  • A device's switches and a scene's source features were found and replaced at anchors (kernel_switches, kernel_source). Each anchor was a whole line of code, comments included, so editing such a line broke a patch, and only at run time.

Now: the kernel is one WESL module: pathtrace.wgsl, trace_units.wgsl, trace_hw.wgsl, translucent.wgsl.

  • Every variant is in it, under WESL's conditional translation (@if(flag) on a declaration or a statement). WESL is the community's WGSL extension, used by Bevy (bevy_shader 0.20) and Vello.

  • wesl-rs 0.6 makes a kernel's WGSL from the flags, natively and in the browser. The flags are named in the head of pathtrace.wgsl:

    • hwrt;
    • the device switches: strict, cutout_lite, cutout_lite2, last_direct, light_pick;
    • the source features: vcolor, grid, tint, unlit, units, background.
  • gpu.rs: KERNEL_FILES, kernel_template, kernel_flags, kernel_wgsl replace the three patch functions. A flag the source names that is not given is an error.

  • Still done as text, before the variant is made:

    • a scene's functions in their slots;
    • the merged layout;
    • the uniform tables;
    • the loop guard.

    6b, the next PR, removes the last three.

  • The browser module grows: gzip 2.81 → 3.31 MB. This is the agreed long-term trade. Once the variants are few, the browser's can be generated at build time.

The toolchain

  • rust-toolchain.toml pins Rust 1.100.0. wesl-rs 0.6 needs 1.97.1, and until now each machine built with whatever stable it had (1.96 here).
  • Every Rust job in CI now also runs when that file changes.
  • One deprecation fixed: fetch_update → try_update.

Found on the way: WGSL a browser refuses

WESL parses by the specification's grammar, as strictly as Chrome's Tint. The scene library's surface-material hash did not compile through it: a * b ^ c * d is not valid WGSL, because a bitwise operator's operands must be unary expressions. naga accepts it, so this never showed natively. These materials (windows, grime, puddles, wet surfaces), and the particle passes (the same pattern three times), never compiled in a browser.

  • Fixed by adding parentheses in the order naga read the expressions, so the meaning is unchanged.
  • A new unit test holds the shader files outside the kernel to the grammar.

Merge gate

check result
all 2,304 flag combinations, Metal source from the patched kernel vs from the @if kernel identical, allowing for two rewrites: the light pick's blocks take their condition from a local variable (a whole statement is under @if, and those blocks are long), and vertex and instance colours multiply in turn (the same products in the same order)
determinism checks on 1.100 voxel, physics (sequential and on 2 and 4 threads), the renderer's wasm32 graph: recorded hashes
main built with 1.96 vs 1.100 (render-identity, native / merged) 0 changed / 0 changed
main (1.100) vs this branch, render-identity: native / THREERT_MERGED=1 / every switch on / THREERT_UNIFORM_TABLES=1 0 changed in all four
tools/web-hello.ts in Chrome pass (the kernel made by wesl in the page)
cargo test --release 126 passed
npm run typecheck, npm test, tools/npm-pack.ts pass

Docs: RUNTIME "The kernel's source"; ROADMAP § 1a records the step.

🤖 Generated with Claude Code


Note

High Risk
Replaces all kernel variant generation for native and browser builds; incorrect @if flags or WESL output could change rendering or break wasm compilation, though the PR reports parity across 2,304 flag combinations and render-identity checks.

Overview
Kernel compilation no longer splices WGSL with string patches (kernel_base, kernel_switches, kernel_source). The path-tracing stack is one WESL module (pathtrace.wgsl plus trace_units, trace_hw, translucent), and kernel_wgsl drives wesl-rs 0.6 conditional translation from kernel_flags (@if for hwrt, device switches, and scene features). Scene-specific slots (material/volume/geometry functions, merged layout, uniform tables, loop guard) are still applied as text before WESL runs.

Toolchain and CI: adds rust-toolchain.toml at 1.100.0 (wesl-rs needs ≥1.97.1) and extends path filters so Rust jobs run when that file changes. fetch_update is updated to try_update.

Browser WGSL: parentheses fix invalid a * b ^ c * d-style hashes in scene materials and particle shaders so WESL/spec parsing matches Tint; a unit test checks non-kernel shaders the same way.

Docs: ROADMAP and RUNTIME describe WESL-based kernel sourcing and the pinned toolchain.

Reviewed by Cursor Bugbot for commit df45ca5. Bugbot is set up for automated code reviews on this repo. Configure here.

…sitory's Rust pinned (1.100.0)

The kernel was made for a device and a scene by text patches: the hardware traversal cut in at markers
(kernel_base), a device's switches and a scene's source features found and replaced at anchors that were whole lines
of code (kernel_switches, kernel_source), an edit of such a line breaking a patch at run time. Now the kernel is one
WESL module (pathtrace.wgsl, trace_units.wgsl, trace_hw.wgsl, translucent.wgsl) with every variant in it under
@if(flag) on a declaration or a statement, made by wesl-rs 0.6 (natively and in a browser): hwrt; the switches
strict, cutout_lite, cutout_lite2, last_direct, light_pick; the source features vcolor, grid, tint, unlit, units,
background (gpu.rs KERNEL_FILES, kernel_template, kernel_flags, kernel_wgsl). A flag the source names that is not
given is an error. Still text, before the variant: a scene's functions in their slots, the merged layout, the
uniform tables, the loop guard.

rust-toolchain.toml pins 1.100.0 (wesl-rs 0.6 asks for 1.97.1; it was whatever stable a machine had), and every
Rust job of CI runs for it. fetch_update is try_update.

WGSL a browser refuses, found on the way: WESL parses by the specification's grammar, as Chrome's Tint does, and the
scene library's surface-material hash (`a * b ^ c * d`: a bitwise operator's operands must be unary) did not compile
through it; naga had taken it, so those materials and the particle passes (the same, three times) never compiled in a
browser. Parenthesised in the order naga read them. A unit test holds the shader files outside the kernel to the
grammar.

Checks: for all 2,304 combinations of the flags the Metal source naga writes is the patched kernel's (two rewrites
allowed for: the light pick's blocks take their condition from a local, and vertex and instance colours multiply in
turn: the same products in the same order). On 1.100 the voxel and physics determinism checks give their recorded
hashes, and main built with 1.96 and with 1.100 renders the same (render-identity, native and merged). Against main
on 1.100, render-identity native, THREERT_MERGED=1, every switch on, the uniform tables: nothing changed.
tools/web-hello.ts in Chrome: pass. cargo test (126), npm typecheck / test / npm-pack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yujiaxu-ops
yujiaxu-ops merged commit 8964dc4 into main Nov 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant