@@ -347,6 +347,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 {
@@ -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();