system
400.wtf

400.wtf / system / docs · docs/ADR/0008-webgpu-tsl-migration-posture.md

ADR-0008 — WebGPU / TSL migration posture

Status: Proposed (research track; intent already visible in tsconfig.json paths for three/webgpu and three/tsl)

Context

Three.js’s future is WebGPURenderer + TSL (Three Shading Language), which compiles node-based materials to WGSL (WebGPU) and GLSL (WebGL2 fallback). The black hole is raw GLSL (ShaderMaterial + hand-written shaders) on WebGLRenderer. WebGPU browser support in mid-2026 is strong on Chromium/Edge, shipping on Safari 26, still maturing on Android and Firefox — real-visitor coverage for this site is unknown but certainly below “assume it.”

Problem

Decide when and how the project adopts WebGPU/TSL without (a) rewriting a working signature visual for zero visitor-visible gain, or (b) accumulating GLSL so deep that migration later becomes a rewrite.

Decision

Three-stage posture, gated by need:

  1. Now: background stays WebGL/GLSL. No migration. The tsconfig paths stay as harmless enablers.
  2. Learning stage: the next shader-heavy artifact is written with WebGPURenderer + TSL (which transparently falls back to WebGL2). Artifacts are isolated (ADR-0003), so the blast radius of toolchain pain is one folder. This produces real knowledge of TSL ergonomics, bundle cost (WebGPU build of three is heavier), and fallback fidelity — measured on this project, not on blog posts.
  3. Migration stage (conditional): port the background only when a concrete graphics.md feature is blocked or degraded on WebGL (candidates: compute-driven turbulence, 1M+ particles, expensive post) and the learning-stage artifact has proven fallback quality. Port = rewrite bh.vert/frag as TSL nodes; the stateless contract (ADR-0004) makes this a contained, semantics-preserving translation.

Alternatives considered

  • Migrate now: cost (toolchain churn, heavier bundle, fallback QA) with no enabled feature; the current visual is vertex-ALU-bound art, not compute-bound simulation.
  • Never / wait for ubiquity: risks the codebase growing more raw-GLSL surface (lensing, doppler) that all becomes migration debt; the learning-stage artifact caps that risk at near-zero cost.
  • Dual-path background (GLSL + TSL maintained in parallel): double maintenance for a solo project; rejected outright.

Tradeoffs

  • (+) Zero risk to the signature visual; knowledge acquired on disposable surface.
  • (+) Roadmap graphics work stays unblocked (all planned effects are WebGL-feasible).
  • (−) Raw GLSL additions from graphics.md (lensing, seeds, doppler) are future translation work — accepted and bounded (one vertex + one fragment shader).
  • (−) TSL APIs still move between three releases; the learning artifact should pin its three version consciously.

Consequences

  • Dependency policy: track three.js releases (Renovate individual PRs — deployment R5) since both WebGL and WebGPU paths live in one package.
  • performance.md’s cost model gets re-measured if stage 3 ever executes (compute changes everything).

Future evolution

Re-evaluate this ADR when any of: a graphics feature hits a WebGL wall; WebGPU support clears ~90% of realistic visitors; or three.js deprecates WebGLRenderer maintenance. Any stage-3 execution supersedes this ADR with a migration record.