TL;DR

Three.js vừa có PR #33418 từ Renaud Rohlinger (@onirenaud, funded by Spawn) nâng cấp toàn diện trải nghiệm debug WebGPU: shader/pipeline fail giờ in ra line, column và source excerpt của WGSL, và renderer có hook onError để app tự xử uncaptured GPU error. Target milestone r185. Bundle phình thêm ~575 B gzip — quá rẻ so với vài giờ debug tiết kiệm được.

Có gì mới

Hai bổ sung chính cho WebGPURenderer:

  • Hook renderer.onError — mirror pattern của onDeviceLost. Wire thẳng vào device.onuncapturederror để surface GPUValidationError, GPUOutOfMemoryError, GPUInternalError ra app code thay vì chỉ nằm lặng trong devtools console.
  • Shader compilation diagnostics — khi pipeline tạo fail, renderer gọi GPUShaderModule.getCompilationInfo() trên các stage liên quan, log từng diagnostic kèm line/column và trích đoạn source có caret chỉ đúng cột lỗi.

Output mẫu từ PR (ai từng debug WGSL sẽ thấy sự khác biệt ngay):

THREE.WebGPURenderer: Render pipeline creation failed
(renderPipeline_MeshBasicNodeMaterial_16):
[Invalid ShaderModule "fragment"] is invalid.

THREE.WebGPURenderer [renderPipeline_.../fragment error] at line 33:4:
identifiers must not start with two or more underscores
  fn main( ) -> OutputStruct {
     ^

Vì sao đáng quan tâm

Trước PR này, shader fail trong WebGPURenderer về cơ bản là hộp đen. Console ném ra đúng một dòng kiểu [Invalid ShaderModule "fragment"] is invalid — không line, không column, không biết material nào, pipeline nào. Muốn đào sâu thì phải tự pushErrorScope / popErrorScope + getCompilationInfo thủ công ở đúng vị trí renderer đang tạo pipeline — mà renderer thì đóng kín.

Giờ thì bạn được nhận thẳng message có line 33, column 4, và dòng source gây lỗi với dấu caret. Đây là DX tiệm cận công cụ native như Dawn/Tint diagnostics hay shader debug của RenderDoc — lần đầu tiên trong three.js.

Chi tiết kỹ thuật

  • Compute pipeline giờ được wrap trong validation error scope (trước đây chỉ render pipeline có).
  • Async rejection: createRenderPipelineAsync rejection không còn bị suppress — reason được log kèm failure.
  • Async render pipeline creation dùng try/finally đảm bảo resolve() luôn được gọi, tránh tình huống hang scene graph khi throw bất thường.
  • Helper _reportShaderDiagnostics được wrap trong top-level try/catch để một custom logger buggy không làm vỡ pipeline của chính nó.
  • Prefix log dọn lại — bỏ THREE. trùng lặp khi namespace đã có sẵn trong tên renderer.
  • Bundle impact: +575 B gzip (WebGPU build), +572 B gzip (WebGPU Nodes build).

So sánh trước & sau

Khía cạnhTrước PR #33418Sau PR #33418
Shader fail message[Invalid ShaderModule "fragment"] is invalidLine, column, source excerpt, caret
Uncaptured GPU errorChỉ thấy trong devtoolsApp bắt qua renderer.onError
Compute pipeline error scopeKhông cóWrap trong validation scope
Async pipeline rejectionBị nuốtLog kèm reason
Identify pipeline/materialKhôngCó (vd renderPipeline_MeshBasicNodeMaterial_16)

Ai hưởng lợi

  • Dev viết custom TSL / raw WGSL node: thấy ngay dòng WGSL nào sai, không còn đoán mò từ message chung chung.
  • CI / visual regression test: hook renderer.onError để fail pipeline test và capture full diagnostic vào log.
  • Production telemetry: forward validation / OOM / internal GPU error sang Sentry, Datadog hoặc logger riêng — trước đây mất hết trừ khi tự gắn uncapturederror listener.
  • Tooling author (editor preview, node-based shader IDE, engine build trên three.js): render inline error squiggle gắn với WGSL source range.
  • App compute-heavy (GPGPU, particle system, post-processing dùng computeAsync): nhận cùng mức bảo vệ validation scope mà render pipeline đã có từ trước.

Limitations & pricing

  • three.js MIT-licensed, miễn phí. PR cũng free khi merge.
  • Diagnostic phụ thuộc GPUShaderModule.getCompilationInfo() — chỉ hoạt động khi browser có WebGPU implementation đàng hoàng (Chrome/Edge ≥ 113, Safari 18+ trên macOS/iOS 18, Firefox Nightly sau flag). WebGL fallback không bị ảnh hưởng.
  • Hook onError chỉ bắt lỗi do WebGPU sinh ra — bug JS ở user code vẫn throw bình thường.
  • PR hiện đang open, chưa merge (tính đến 2026-04-19). Ai muốn dùng ngay phải cherry-pick branch hoặc chờ r185.

What's next

Ba commit đã push: (1) core error reporting + diagnostic infrastructure, (2) diagnostic safety refactor, (3) helper tightening. Đợi maintainer review, merge vào dev, release cùng r185.

Bối cảnh rộng hơn: three.js đang đi theo hướng WebGPU-first — WebGPURenderer dần trở thành default thay cho WebGLRenderer. PR này vá một trong những gap DX khó chịu nhất còn lại so với trải nghiệm debug GLSL/WebGL vốn đã chín mùi. Sau khi merge, có lý do để kỳ vọng ecosystem tooling (inspector, shader IDE) sẽ khai thác tiếp API onError để xây trải nghiệm dev đầy đủ hơn.

Nguồn: github.com/mrdoob/three.js/pull/33418, @onirenaud on X, Toji.dev WebGPU error handling.