From 496e115fd3a7ec42a19bb2ff3588ffe5e8e6df7f Mon Sep 17 00:00:00 2001 From: "zed-zippy[bot]" <234243425+zed-zippy[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:11:13 +0000 Subject: [PATCH] Clamp window size on wgpu (#50329) (cherry-pick to preview) (#50346) Cherry-pick of #50329 to preview ---- Fixes ZED-59P Release Notes: - Linux: Fix panic when requested window size was larger than supported by your GPU Co-authored-by: Conrad Irwin --- crates/gpui_linux/src/linux/wayland/window.rs | 6 +++ crates/gpui_linux/src/linux/x11/window.rs | 34 ++++++++------- crates/gpui_wgpu/src/wgpu_renderer.rs | 42 ++++++++++++++++--- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/crates/gpui_linux/src/linux/wayland/window.rs b/crates/gpui_linux/src/linux/wayland/window.rs index c1006a816a3844db22ea8932177b0f0b2ff1c99f..f464053ed7d0d9580a255ba0db5cd9e2befc7731 100644 --- a/crates/gpui_linux/src/linux/wayland/window.rs +++ b/crates/gpui_linux/src/linux/wayland/window.rs @@ -345,6 +345,12 @@ impl WaylandWindowState { if let Some(title) = options.titlebar.and_then(|titlebar| titlebar.title) { xdg_state.toplevel.set_title(title.to_string()); } + // Set max window size based on the GPU's maximum texture dimension. + // This prevents the window from being resized larger than what the GPU can render. + let max_texture_size = renderer.max_texture_size() as i32; + xdg_state + .toplevel + .set_max_size(max_texture_size, max_texture_size); } Ok(Self { diff --git a/crates/gpui_linux/src/linux/x11/window.rs b/crates/gpui_linux/src/linux/x11/window.rs index 8060e4c4457c6ef4575d86c4d975e3ead901f693..89084189d7cae90cee47012f7b7b700abce11bfe 100644 --- a/crates/gpui_linux/src/linux/x11/window.rs +++ b/crates/gpui_linux/src/linux/x11/window.rs @@ -497,21 +497,6 @@ impl X11WindowState { ), )?; - if let Some(size) = params.window_min_size { - let mut size_hints = WmSizeHints::new(); - let min_size = (f32::from(size.width) as i32, f32::from(size.height) as i32); - size_hints.min_size = Some(min_size); - check_reply( - || { - format!( - "X11 change of WM_SIZE_HINTS failed. min_size: {:?}", - min_size - ) - }, - size_hints.set_normal_hints(xcb, x_window), - )?; - } - let reply = get_reply(|| "X11 GetGeometry failed.", xcb.get_geometry(x_window))?; if reply.x == 0 && reply.y == 0 { bounds.origin.x.0 += 2; @@ -697,6 +682,25 @@ impl X11WindowState { WgpuRenderer::new(gpu_context, &raw_window, config)? }; + // Set max window size hints based on the GPU's maximum texture dimension. + // This prevents the window from being resized larger than what the GPU can render. + let max_texture_size = renderer.max_texture_size(); + let mut size_hints = WmSizeHints::new(); + if let Some(size) = params.window_min_size { + size_hints.min_size = + Some((f32::from(size.width) as i32, f32::from(size.height) as i32)); + } + size_hints.max_size = Some((max_texture_size as i32, max_texture_size as i32)); + check_reply( + || { + format!( + "X11 change of WM_SIZE_HINTS failed. max_size: {:?}", + max_texture_size + ) + }, + size_hints.set_normal_hints(xcb, x_window), + )?; + let display = Rc::new(X11Display::new(xcb, scale_factor, x_screen_index)?); Ok(Self { diff --git a/crates/gpui_wgpu/src/wgpu_renderer.rs b/crates/gpui_wgpu/src/wgpu_renderer.rs index ee9cf05bb76802ff4858715f8a5efdcac9bdba7d..2a56a10036b4daf97e0588027671c70264a1f758 100644 --- a/crates/gpui_wgpu/src/wgpu_renderer.rs +++ b/crates/gpui_wgpu/src/wgpu_renderer.rs @@ -116,6 +116,7 @@ pub struct WgpuRenderer { adapter_info: wgpu::AdapterInfo, transparent_alpha_mode: wgpu::CompositeAlphaMode, opaque_alpha_mode: wgpu::CompositeAlphaMode, + max_texture_size: u32, } impl WgpuRenderer { @@ -215,11 +216,27 @@ impl WgpuRenderer { opaque_alpha_mode }; + let device = Arc::clone(&context.device); + let max_texture_size = device.limits().max_texture_dimension_2d; + + let requested_width = config.size.width.0 as u32; + let requested_height = config.size.height.0 as u32; + let clamped_width = requested_width.min(max_texture_size); + let clamped_height = requested_height.min(max_texture_size); + + if clamped_width != requested_width || clamped_height != requested_height { + warn!( + "Requested surface size ({}, {}) exceeds maximum texture dimension {}. \ + Clamping to ({}, {}). Window content may not fill the entire window.", + requested_width, requested_height, max_texture_size, clamped_width, clamped_height + ); + } + let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - width: config.size.width.0 as u32, - height: config.size.height.0 as u32, + width: clamped_width.max(1), + height: clamped_height.max(1), present_mode: wgpu::PresentMode::Fifo, desired_maximum_frame_latency: 2, alpha_mode, @@ -227,7 +244,6 @@ impl WgpuRenderer { }; surface.configure(&context.device, &surface_config); - let device = Arc::clone(&context.device); let queue = Arc::clone(&context.queue); let dual_source_blending = context.supports_dual_source_blending(); @@ -348,6 +364,7 @@ impl WgpuRenderer { adapter_info, transparent_alpha_mode, opaque_alpha_mode, + max_texture_size, }) } @@ -762,6 +779,17 @@ impl WgpuRenderer { let height = size.height.0 as u32; if width != self.surface_config.width || height != self.surface_config.height { + let clamped_width = width.min(self.max_texture_size); + let clamped_height = height.min(self.max_texture_size); + + if clamped_width != width || clamped_height != height { + warn!( + "Requested surface size ({}, {}) exceeds maximum texture dimension {}. \ + Clamping to ({}, {}). Window content may not fill the entire window.", + width, height, self.max_texture_size, clamped_width, clamped_height + ); + } + // Wait for any in-flight GPU work to complete before destroying textures if let Err(e) = self.device.poll(wgpu::PollType::Wait { submission_index: None, @@ -778,8 +806,8 @@ impl WgpuRenderer { texture.destroy(); } - self.surface_config.width = width.max(1); - self.surface_config.height = height.max(1); + self.surface_config.width = clamped_width.max(1); + self.surface_config.height = clamped_height.max(1); self.surface.configure(&self.device, &self.surface_config); // Invalidate intermediate textures - they will be lazily recreated @@ -864,6 +892,10 @@ impl WgpuRenderer { } } + pub fn max_texture_size(&self) -> u32 { + self.max_texture_size + } + pub fn draw(&mut self, scene: &Scene) { self.atlas.before_frame();