From ad2b26261e5208d9dae9717534c14f9b7948e810 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 24 Feb 2026 15:01:21 -0700 Subject: [PATCH] Clamp textures on Linux too (#50025) Port of #10314 to the wgpu renderer Closes #ISSUE Before you mark this PR as ready for review, make sure that you have: - [ ] Added a solid test coverage and/or screenshots from doing manual testing - [ ] Done a self-review taking into account security and performance aspects - [ ] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Fixed a panic when rendering an image larger than the GPU could support. --- crates/gpui_wgpu/src/wgpu_atlas.rs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/crates/gpui_wgpu/src/wgpu_atlas.rs b/crates/gpui_wgpu/src/wgpu_atlas.rs index d3614ea126e3d3f7c4e83b645b0d4ac0d77e548e..ffef3a65398c3f03639a8551506463f91a862c33 100644 --- a/crates/gpui_wgpu/src/wgpu_atlas.rs +++ b/crates/gpui_wgpu/src/wgpu_atlas.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Context as _, Result}; use collections::FxHashMap; use etagere::{BucketedAtlasAllocator, size2}; use gpui::{ @@ -30,6 +30,7 @@ struct PendingUpload { struct WgpuAtlasState { device: Arc, queue: Arc, + max_texture_size: u32, storage: WgpuAtlasStorage, tiles_by_key: FxHashMap, pending_uploads: Vec, @@ -41,9 +42,11 @@ pub struct WgpuTextureInfo { impl WgpuAtlas { pub fn new(device: Arc, queue: Arc) -> Self { + let max_texture_size = device.limits().max_texture_dimension_2d; WgpuAtlas(Mutex::new(WgpuAtlasState { device, queue, + max_texture_size, storage: WgpuAtlasStorage::default(), tiles_by_key: Default::default(), pending_uploads: Vec::new(), @@ -78,7 +81,9 @@ impl PlatformAtlas for WgpuAtlas { let Some((size, bytes)) = build()? else { return Ok(None); }; - let tile = lock.allocate(size, key.texture_kind()); + let tile = lock + .allocate(size, key.texture_kind()) + .context("failed to allocate")?; lock.upload_texture(tile.texture_id, tile.bounds, &bytes); lock.tiles_by_key.insert(key.clone(), tile.clone()); Ok(Some(tile)) @@ -110,7 +115,11 @@ impl PlatformAtlas for WgpuAtlas { } impl WgpuAtlasState { - fn allocate(&mut self, size: Size, texture_kind: AtlasTextureKind) -> AtlasTile { + fn allocate( + &mut self, + size: Size, + texture_kind: AtlasTextureKind, + ) -> Option { { let textures = &mut self.storage[texture_kind]; @@ -119,14 +128,12 @@ impl WgpuAtlasState { .rev() .find_map(|texture| texture.allocate(size)) { - return tile; + return Some(tile); } } let texture = self.push_texture(size, texture_kind); - texture - .allocate(size) - .expect("Failed to allocate from newly created texture") + texture.allocate(size) } fn push_texture( @@ -138,8 +145,13 @@ impl WgpuAtlasState { width: DevicePixels(1024), height: DevicePixels(1024), }; + let max_texture_size = self.max_texture_size as i32; + let max_atlas_size = Size { + width: DevicePixels(max_texture_size), + height: DevicePixels(max_texture_size), + }; - let size = min_size.max(&DEFAULT_ATLAS_SIZE); + let size = min_size.min(&max_atlas_size).max(&DEFAULT_ATLAS_SIZE); let format = match kind { AtlasTextureKind::Monochrome => wgpu::TextureFormat::R8Unorm, AtlasTextureKind::Subpixel => wgpu::TextureFormat::Bgra8Unorm,