From fe780a6f839e152451dd017cd9ae91af7ae09cc9 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 5 Nov 2025 14:02:02 -0800 Subject: [PATCH] DRAFT: Add `set_web_canvas_size` option. --- deno_webgpu/surface.rs | 1 + examples/features/src/framework.rs | 1 + .../standalone/02_hello_window/src/main.rs | 1 + wgpu-core/src/device/resource.rs | 1 + wgpu-hal/examples/halmark/main.rs | 1 + wgpu-hal/examples/ray-traced-triangle/main.rs | 1 + wgpu-hal/src/gles/web.rs | 18 +++++++------- wgpu-hal/src/lib.rs | 4 ++++ wgpu-types/src/lib.rs | 24 +++++++++++++++++++ wgpu/src/api/surface.rs | 1 + wgpu/src/backend/webgpu.rs | 18 +++++++------- 11 files changed, 55 insertions(+), 16 deletions(-) diff --git a/deno_webgpu/surface.rs b/deno_webgpu/surface.rs index 60df27ce0e1..bba3ac40770 100644 --- a/deno_webgpu/surface.rs +++ b/deno_webgpu/surface.rs @@ -81,6 +81,7 @@ impl GPUCanvasContext { format, width: *self.width.borrow(), height: *self.height.borrow(), + set_web_canvas_size: false, // GPUCanvasConfiguration does not contain width,height present_mode: configuration .present_mode .map(Into::into) diff --git a/examples/features/src/framework.rs b/examples/features/src/framework.rs index 854afddeee8..828931b932b 100644 --- a/examples/features/src/framework.rs +++ b/examples/features/src/framework.rs @@ -557,6 +557,7 @@ impl From> format, width: params.width, height: params.height, + set_web_canvas_size: true, desired_maximum_frame_latency: 2, present_mode: wgpu::PresentMode::Fifo, alpha_mode: wgpu::CompositeAlphaMode::Auto, diff --git a/examples/standalone/02_hello_window/src/main.rs b/examples/standalone/02_hello_window/src/main.rs index 6da07c9f750..98af749e7ce 100644 --- a/examples/standalone/02_hello_window/src/main.rs +++ b/examples/standalone/02_hello_window/src/main.rs @@ -62,6 +62,7 @@ impl State { alpha_mode: wgpu::CompositeAlphaMode::Auto, width: self.size.width, height: self.size.height, + set_web_canvas_size: false, desired_maximum_frame_latency: 2, present_mode: wgpu::PresentMode::AutoVsync, }; diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 39dc2026b7e..0cd1ac234d5 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -4933,6 +4933,7 @@ impl Device { height: config.height, depth_or_array_layers: 1, }, + set_web_canvas_size: config.set_web_canvas_size, usage: conv::map_texture_usage( config.usage, hal::FormatAspects::COLOR, diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index f5391012ca3..18691643ba5 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -149,6 +149,7 @@ impl Example { height: window_size.1, depth_or_array_layers: 1, }, + set_web_canvas_size: false, usage: wgpu_types::TextureUses::COLOR_TARGET, view_formats: vec![], }; diff --git a/wgpu-hal/examples/ray-traced-triangle/main.rs b/wgpu-hal/examples/ray-traced-triangle/main.rs index 69c4ff2cf4e..138f3ed04b8 100644 --- a/wgpu-hal/examples/ray-traced-triangle/main.rs +++ b/wgpu-hal/examples/ray-traced-triangle/main.rs @@ -304,6 +304,7 @@ impl Example { height: window_size.1, depth_or_array_layers: 1, }, + set_web_canvas_size: false, usage: wgpu_types::TextureUses::COLOR_TARGET | wgpu_types::TextureUses::COPY_DST, view_formats: vec![surface_format], }; diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index 485686e91e6..06fc710c4b5 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -315,14 +315,16 @@ impl crate::Surface for Surface { device: &super::Device, config: &crate::SurfaceConfiguration, ) -> Result<(), crate::SurfaceError> { - match self.canvas { - Canvas::Canvas(ref canvas) => { - canvas.set_width(config.extent.width); - canvas.set_height(config.extent.height); - } - Canvas::Offscreen(ref canvas) => { - canvas.set_width(config.extent.width); - canvas.set_height(config.extent.height); + if config.set_web_canvas_size { + match self.canvas { + Canvas::Canvas(ref canvas) => { + canvas.set_width(config.extent.width); + canvas.set_height(config.extent.height); + } + Canvas::Offscreen(ref canvas) => { + canvas.set_width(config.extent.width); + canvas.set_height(config.extent.height); + } } } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 8620d05a849..f60dc7f94d7 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -2380,6 +2380,10 @@ pub struct SurfaceConfiguration { /// Requested texture extent. Must be in /// `SurfaceCapabilities::extents` range. pub extent: wgt::Extent3d, + /// Whether, when the [`Surface`] being configured refers to a HTML `` element, + /// the `width` and `height` of this configuration are used to set the `width` and `height` + /// attributes of the canvas element. + pub set_web_canvas_size: bool, /// Allowed usage of surface textures, pub usage: wgt::TextureUses, /// Allows views of swapchain texture to have a different format diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 4c02d67bf5b..83cd86c583f 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5821,6 +5821,29 @@ pub struct SurfaceConfiguration { /// but platform-specific, and may change in the future (currently macOS /// scales the surface, other platforms may do something else). pub height: u32, + /// Whether, when the [`Surface`] being configured refers to a HTML `` element, + /// the `width` and `height` of this configuration are used to set the `width` and `height` + /// attributes of the canvas element. + /// + /// This option is ignored by all backends except for WebGPU and WebGL 2. + /// + /// Set this to `true` if you wish this configuration to control the resolution of + /// the image rendered to the canvas. + /// If you are also using DOM layout information to determine + /// the width and height you provide here, then you must ensure that the computed size of the + /// canvas element is being controlled by explicit CSS (such as + /// `#my-canvas { width: 100%; height: 100%; }`) + /// rather than intrinsic size, as otherwise, you will get runaway resizing if + /// `window.devicePixelRatio` is not equal to 1. + /// + /// Set this to `false` if the canvas `width` and `height` are being managed by other code or + /// static HTML, if your code does not know whether it is rendering to a canvas or how that + /// canvas is being managed, or if you want behavior maximally like the WebGPU API + /// (which does not accept a size in `GPUCanvasConfiguration`). + /// + /// If you are writing code that is not going to be used in a web page, or if you do not + /// understand what to put here, `false` is the safe default choice. + pub set_web_canvas_size: bool, /// Presentation mode of the swap chain. Fifo is the only mode guaranteed to be supported. /// `FifoRelaxed`, `Immediate`, and `Mailbox` will crash if unsupported, while `AutoVsync` and /// `AutoNoVsync` will gracefully do a designed sets of fallbacks if their primary modes are @@ -5879,6 +5902,7 @@ impl SurfaceConfiguration { format: self.format, width: self.width, height: self.height, + set_web_canvas_size: self.set_web_canvas_size, present_mode: self.present_mode, desired_maximum_frame_latency: self.desired_maximum_frame_latency, alpha_mode: self.alpha_mode, diff --git a/wgpu/src/api/surface.rs b/wgpu/src/api/surface.rs index 113f46639e6..5e9c7f6d622 100644 --- a/wgpu/src/api/surface.rs +++ b/wgpu/src/api/surface.rs @@ -69,6 +69,7 @@ impl Surface<'_> { format: *caps.formats.first()?, width, height, + set_web_canvas_size: false, desired_maximum_frame_latency: 2, present_mode: *caps.present_modes.first()?, alpha_mode: wgt::CompositeAlphaMode::Auto, diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index 800820bbb39..7c725101949 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -3852,14 +3852,16 @@ impl dispatch::SurfaceInterface for WebSurface { fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) { let device = device.as_webgpu(); - match self.canvas { - Canvas::Canvas(ref canvas) => { - canvas.set_width(config.width); - canvas.set_height(config.height); - } - Canvas::Offscreen(ref canvas) => { - canvas.set_width(config.width); - canvas.set_height(config.height); + if config.set_web_canvas_size { + match self.canvas { + Canvas::Canvas(ref canvas) => { + canvas.set_width(config.width); + canvas.set_height(config.height); + } + Canvas::Offscreen(ref canvas) => { + canvas.set_width(config.width); + canvas.set_height(config.height); + } } }