From 81893788c1036f645fe574eae8440b207a14ee55 Mon Sep 17 00:00:00 2001 From: funman300 Date: Wed, 24 Jun 2026 09:18:07 -0700 Subject: [PATCH] fix(web): use adapter limits (Functionality) so /play renders at native res MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 2048 surface limit was never wgpu's or the GPU's — it's downlevel_webgl2_defaults().max_texture_dimension_2d (2048), which WgpuSettingsPriority::WebGL2 forces. Switch to Functionality: on the WebGL2 (Gl) backend Bevy then adopts the adapter's real limits, which are still WebGL2-constrained for features/buffers (shaders stay GLES-compatible) but report the GPU's true max texture dimension (e.g. 16384). The device is requested with exactly what the adapter offers, so creation can't fail, the surface is no longer capped, and large viewports (4K) render with no letterbox and no hardcoded cap. Removes the resize_constraints cap and the play.html max-width/height caps. Co-Authored-By: Claude Opus 4.8 (1M context) --- solitaire_server/web/play.html | 21 +++------------- solitaire_web/src/lib.rs | 45 ++++++++++++++-------------------- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/solitaire_server/web/play.html b/solitaire_server/web/play.html index 50ea186..9c33444 100644 --- a/solitaire_server/web/play.html +++ b/solitaire_server/web/play.html @@ -7,23 +7,10 @@ diff --git a/solitaire_web/src/lib.rs b/solitaire_web/src/lib.rs index c64a2b5..2a99f7e 100644 --- a/solitaire_web/src/lib.rs +++ b/solitaire_web/src/lib.rs @@ -13,7 +13,7 @@ use bevy::asset::AssetMetaCheck; use bevy::prelude::*; use bevy::render::RenderPlugin; use bevy::render::settings::{RenderCreation, WgpuSettings, WgpuSettingsPriority}; -use bevy::window::{Window, WindowPlugin, WindowResizeConstraints, WindowResolution}; +use bevy::window::{Window, WindowPlugin, WindowResolution}; use solitaire_data::LocalOnlyProvider; use solitaire_engine::CoreGamePlugin; use wasm_bindgen::prelude::*; @@ -34,27 +34,15 @@ pub fn start() { fit_canvas_to_parent: true, // Prevent the browser stealing keyboard events and scroll. prevent_default_event_handling: true, - // Force scale_factor = 1.0 so the wgpu surface is sized in - // CSS/logical pixels rather than physical pixels. Without this, - // HiDPI displays (devicePixelRatio ≥ 2) produce a framebuffer - // whose physical width can exceed WebGL2's 2048-pixel per- - // dimension limit, causing a wgpu validation panic on the first - // resize event and killing the WASM thread. + // Render at CSS/logical pixels (scale_factor 1.0) rather + // than physical (CSS × devicePixelRatio). This keeps the + // surface smaller on HiDPI displays — lighter GPU load and + // stable sizing — at the cost of some crispness. The wgpu + // texture-dimension limit is now taken from the adapter (see + // the RenderPlugin below), so this is purely a quality/perf + // choice, no longer a crash-avoidance hack. resolution: WindowResolution::default() .with_scale_factor_override(1.0), - // Cap the surface at WebGL2's max texture dimension (2048). - // On wasm Bevy creates the device with - // `Limits::downlevel_webgl2_defaults()` (max_texture_dimension_2d - // = 2048), so a larger surface — e.g. a 4K display at 150% scale - // gives a 2560x1440 logical viewport — makes Surface::configure - // panic on the first frame. winit maps this constraint to the - // canvas's `max-width`/`max-height` style, so the surface can - // never exceed it. Viewports wider/taller than 2048 letterbox. - resize_constraints: WindowResizeConstraints { - max_width: 2048.0, - max_height: 2048.0, - ..default() - }, ..default() }), ..default() @@ -66,14 +54,19 @@ pub fn start() { meta_check: AssetMetaCheck::Never, ..default() }) - // WebGL2 priority constrains naga (the shader translator) to emit - // GLES 300es-compatible GLSL. Without this, Chromium's ANGLE driver - // rejects certain shader constructs (storage buffers, tight component - // limits) causing a fatal wgpu "Shader translation error". Firefox is - // more lenient; this setting makes both browsers work identically. + // `Functionality` makes wgpu adopt the *adapter's* real limits + // instead of the conservative `downlevel_webgl2_defaults()` that + // `WebGL2` priority forces. On the WebGL2 (Gl) backend the adapter + // already reports WebGL2-constrained features/limits — no storage + // buffers, etc., so shaders stay GLES-compatible on both Firefox and + // Chromium — but it reports the GPU's *true* `max_texture_dimension` + // (e.g. 16384) rather than 2048. The device is requested with exactly + // what the adapter offers, so creation can't fail, and the surface is + // no longer capped at 2048: large viewports (4K, etc.) render natively + // with no letterbox and no hardcoded cap. .set(RenderPlugin { render_creation: RenderCreation::Automatic(WgpuSettings { - priority: WgpuSettingsPriority::WebGL2, + priority: WgpuSettingsPriority::Functionality, ..default() }), ..default() -- 2.47.3