fix(web): cap /play canvas at the real 2048 wgpu limit, not gl.MAX_TEXTURE_SIZE

Correction to the previous canvas clamp (#97), which would NOT have fixed the
crash. It capped the wrapper to the device's gl.MAX_TEXTURE_SIZE, but that's
the hardware limit — on a 4K/integrated GPU it reports 8192+, so the wrapper
was never actually capped and the 2560-wide surface still exceeded the limit.

The real ceiling is wgpu's, not the hardware's: on wasm Bevy creates the device
with Limits::downlevel_webgl2_defaults() (forced by WgpuSettingsPriority::WebGL2
in solitaire_web/src/lib.rs; see bevy_render-0.18.1 settings.rs), whose
max_texture_dimension_2d is a fixed 2048 regardless of GPU. So the cap must be
the constant 2048.

(For the record: the reporter's display is 3840x2160 at 150% scale → a 2560x1440
logical viewport, which is the 2560 in the panic — nothing hardcodes 1440p.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-23 18:14:20 -07:00
parent b3b282ec2d
commit 8a2a22ff1b
+17 -19
View File
@@ -23,26 +23,24 @@
<body>
<div id="bevy-wrap"><canvas id="bevy-canvas"></canvas></div>
<script>
// Clamp the Bevy canvas's backing buffer to the device's real WebGL2
// MAX_TEXTURE_SIZE *before* the wasm initialises. `fit_canvas_to_parent`
// sizes the wgpu surface to #bevy-wrap; a surface larger than the GPU
// limit (only 2048 on many laptop/integrated GPUs — e.g. a 2560-wide
// 1440p display) makes Surface::configure panic and kills the WASM
// thread. Querying the real maximum means only devices at the 2048 floor
// letterbox; everyone else still fills the viewport. Runs synchronously
// before the deferred module script below.
(function clampCanvasToGpuLimit() {
var max = 2048; // WebGL2 spec floor — the safe fallback
try {
var probe = document.createElement("canvas").getContext("webgl2");
if (probe) {
var m = probe.getParameter(probe.MAX_TEXTURE_SIZE);
if (m && m > 0) max = m;
}
} catch (e) { /* keep the safe 2048 floor */ }
// Clamp the Bevy canvas's backing buffer to 2048px *before* the wasm
// initialises. `fit_canvas_to_parent` sizes the wgpu surface to
// #bevy-wrap, and on wasm Bevy creates the device with
// `Limits::downlevel_webgl2_defaults()` (forced by
// `WgpuSettingsPriority::WebGL2` in solitaire_web/src/lib.rs), whose
// `max_texture_dimension_2d` is a fixed **2048** — independent of the
// GPU's real MAX_TEXTURE_SIZE (which is why querying the hardware limit
// doesn't help: a 4K/integrated GPU reports e.g. 8192 but wgpu still
// caps the surface at 2048). A surface wider/taller than 2048 makes
// Surface::configure panic and kill the WASM thread on the first frame
// — e.g. a 3840x2160 display at 150% scale gives a 2560x1440 logical
// viewport → a 2560-wide surface. So the cap is the constant 2048.
// Keep in sync with the wgpu limit selected in lib.rs.
(function clampCanvasToWebgl2Limit() {
var MAX = 2048; // wgpu downlevel_webgl2_defaults().max_texture_dimension_2d
var wrap = document.getElementById("bevy-wrap");
wrap.style.maxWidth = max + "px";
wrap.style.maxHeight = max + "px";
wrap.style.maxWidth = MAX + "px";
wrap.style.maxHeight = MAX + "px";
})();
</script>
<script type="module">