Skip to content

fix(web): report real GPU backend; unblock the WebGL2 path#87

Merged
proggeramlug merged 1 commit into
mainfrom
fix/web-webgpu-adapter-and-gl-prereqs
Jul 11, 2026
Merged

fix(web): report real GPU backend; unblock the WebGL2 path#87
proggeramlug merged 1 commit into
mainfrom
fix/web-webgpu-adapter-and-gl-prereqs

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What

The web build asks wgpu for BROWSER_WEBGPU | GL and compiles wgpu's webgl feature — but the GL path could never run. Three separate bugs on it, each fatal on its own:

  1. No display handle on the instance. wgpu-core passes raw_display_handle: None for a canvas surface target and then errors MissingDisplayHandle unless the instance carries one (wgpu-core 29 instance.rs:254). Surface creation died immediately. The WebGPU backend never reads it.
  2. Limits::default() is unsatisfiable on GL. WebGL2 has no compute, so max_compute_workgroups_per_dimension is 0 against a default request of 65535request_device fails outright.
  3. Unconditional COPY_SRC on the swapchain. A WebGL2 surface doesn't advertise it, so Surface::configure rejects the config.

Also: log the backend and adapter wgpu actually selected, instead of hardcoding "(WebGPU)".

Why it matters even though WebGL2 still can't render

A user reported the web build dying with No WebGPU/WebGL adapter found on macOS Sequoia. The root cause is that having navigator.gpu is not the same as having an adapter — Chrome ships the API on by default but hands back no adapter when graphics acceleration is off, the GPU is blocklisted, or it's a VM/remote session. wgpu picks its backend once, in Instance::new, purely on whether navigator.gpu is defined (wgpu-29 api/instance.rs:74), so it commits to WebGPU and never looks at the GL backend we compiled in.

These three fixes are the prerequisites for the GL path ever working. They are not sufficient: Renderer::new_impl eagerly creates 14 compute pipelines plus storage buffers and a 64KB joint uniform, and WebGL2 (GLES 3.0) has no compute shaders or storage buffers at all — wgpu only reports COMPUTE_SHADERS at GLES 3.1+. A real fallback needs a downlevel / 2D-only renderer init path (fits the existing setDirect2DMode idea). Filing this separately.

Risk

Inert on WebGPU. The limits change is explicitly scoped to Backend::Gl, so the WebGPU path requests exactly the limits it always has; the COPY_SRC mask is a no-op wherever the surface advertises the usage (i.e. everywhere WebGPU runs today).

Verification

Built for wasm32-unknown-unknown against current main. Drove the resulting build in a real headless Chrome:

  • WebGPU path: boots, Bloom engine initialized (BrowserWebGpu on …), game renders and plays into level 1.
  • GL path (forced by hiding navigator.gpu): now gets past instance/surface/device/swapchain creation and reaches renderer init, where it hits the compute-pipeline wall described above — i.e. exactly as far as these fixes are meant to take it.

Summary by CodeRabbit

  • Bug Fixes
    • Improved WebGL2 compatibility during graphics initialization.
    • Prevented startup failures caused by unsupported device limits or texture operations.
    • Added more accurate initialization diagnostics, including the active graphics backend and adapter.

The web build asks wgpu for BROWSER_WEBGPU | GL and compiles wgpu's `webgl`
feature, but the GL path could never actually run. Three bugs, each fatal on
its own, all on that path:

- The instance carried no display handle. wgpu-core passes
  `raw_display_handle: None` for a canvas surface target and then fails with
  MissingDisplayHandle unless the *instance* supplies one, so surface creation
  died immediately. The WebGPU backend never reads it.
- Device creation requested `Limits::default()`, which is unsatisfiable on GL:
  WebGL2 has no compute, so max_compute_workgroups_per_dimension is 0 against a
  default request of 65535.
- The swapchain was configured with COPY_SRC unconditionally; a WebGL2 surface
  doesn't advertise it and Surface::configure rejects it.

Also log the backend and adapter wgpu actually chose, instead of hardcoding
"(WebGPU)".

This does not make WebGL2 usable yet — Renderer::new_impl eagerly builds 14
compute pipelines and storage buffers, which WebGL2 (GLES 3.0) cannot provide
at all; that needs a downlevel/2D-only init path. These are the prerequisites,
and they are inert on WebGPU: the WebGPU path keeps the limits it always
requested and was verified end-to-end (game boots and renders).
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bbb47cc3-50dd-444c-b2af-cbea9e774c8c

📥 Commits

Reviewing files that changed from the base of the PR and between 1d75f0c and 42cfe93.

📒 Files selected for processing (1)
  • native/web/src/lib.rs

📝 Walkthrough

Walkthrough

Changes

Web initialization compatibility

Layer / File(s) Summary
Display handle and instance setup
native/web/src/lib.rs
Adds WebDisplay with HasDisplayHandle and uses it when constructing the wgpu instance.
Backend-adaptive device and surface configuration
native/web/src/lib.rs
Uses adapter limits for the GL backend, masks surface usage by advertised capabilities, and logs the selected backend and adapter name.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: fixing backend reporting and unblocking the WebGL2 path.
Description check ✅ Passed The description covers summary, motivation, risks, and verification, though its headings differ from the template.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/web-webgpu-adapter-and-gl-prereqs

Comment @coderabbitai help to get the list of available commands.

@proggeramlug proggeramlug merged commit ae7ee3e into main Jul 11, 2026
8 of 10 checks passed
proggeramlug pushed a commit that referenced this pull request Jul 11, 2026
PR #87/#88's web work pushed native/web/src/lib.rs to 2034 lines
(limit 2000). Pure code motion, same pattern as input_ffi.rs: the
Phase-1c material-system FFI section (compile/params/draw submission,
instance buffers, texture arrays, reflection probes) moves to
material_ffi.rs. lib.rs 2034 -> 1546; cargo check for
wasm32-unknown-unknown green; validate-ffi passes.
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