fix(web): clamp /play canvas to GPU MAX_TEXTURE_SIZE to stop wgpu panic
Rhys hit a fatal wgpu validation panic loading /play on a 1440p display:
Surface::configure ... Requested was (2560, 1440), maximum extent for
either dimension is 2048
The earlier scale_factor_override(1.0) fix only neutralised HiDPI (CSS×DPR);
it didn't help when the *logical* viewport itself exceeds 2048. `fit_canvas_to_
parent` sizes the wgpu surface to the canvas's parent, so a 2560-wide viewport
configures a 2560-wide surface — past WebGL2's 2048 per-dimension limit on
laptop/integrated GPUs, and the panic kills the WASM thread on the first frame.
Wrap the canvas in #bevy-wrap and, before init, clamp that element's max-
width/height to the device's actual gl.MAX_TEXTURE_SIZE (falling back to the
2048 WebGL2 floor). fit_canvas_to_parent then never produces a surface larger
than the GPU allows. Only devices at the 2048 floor letterbox (centered); GPUs
that report 4096/8192 still fill the viewport.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,11 +7,44 @@
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { background: #000; overflow: hidden; }
|
||||
#bevy-canvas { display: block; width: 100vw; height: 100vh; }
|
||||
/* #bevy-wrap fills the viewport but is capped to the GPU's real
|
||||
MAX_TEXTURE_SIZE via an inline max-width/height set before init
|
||||
(see the clamp script below). fit_canvas_to_parent sizes the wgpu
|
||||
surface to this element, so capping it keeps the surface within
|
||||
WebGL2's per-dimension limit. Centered so 2048-limited devices
|
||||
letterbox symmetrically. */
|
||||
#bevy-wrap {
|
||||
width: 100vw; height: 100vh; margin: 0 auto;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
#bevy-canvas { display: block; width: 100%; height: 100%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="bevy-canvas"></canvas>
|
||||
<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 */ }
|
||||
var wrap = document.getElementById("bevy-wrap");
|
||||
wrap.style.maxWidth = max + "px";
|
||||
wrap.style.maxHeight = max + "px";
|
||||
})();
|
||||
</script>
|
||||
<script type="module">
|
||||
import init from "/web/pkg/canvas.js";
|
||||
// solitaire_wasm.js provides SolitaireGame with the full debug / automation
|
||||
|
||||
Reference in New Issue
Block a user