Clamp textures on Linux too

Conrad Irwin created

Port of #10314 to the wgpu renderer

Change summary

crates/gpui/src/platform/wgpu/wgpu_atlas.rs | 28 ++++++++++++++++------
1 file changed, 20 insertions(+), 8 deletions(-)

Detailed changes

crates/gpui/src/platform/wgpu/wgpu_atlas.rs 🔗

@@ -2,7 +2,7 @@ use crate::{
     AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
     Point, Size, platform::AtlasTextureList,
 };
-use anyhow::Result;
+use anyhow::{Context as _, Result};
 use collections::FxHashMap;
 use etagere::{BucketedAtlasAllocator, size2};
 use parking_lot::Mutex;
@@ -30,6 +30,7 @@ struct PendingUpload {
 struct WgpuAtlasState {
     device: Arc<wgpu::Device>,
     queue: Arc<wgpu::Queue>,
+    max_texture_size: u32,
     storage: WgpuAtlasStorage,
     tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
     pending_uploads: Vec<PendingUpload>,
@@ -41,9 +42,11 @@ pub struct WgpuTextureInfo {
 
 impl WgpuAtlas {
     pub(crate) fn new(device: Arc<wgpu::Device>, queue: Arc<wgpu::Queue>) -> 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<DevicePixels>, texture_kind: AtlasTextureKind) -> AtlasTile {
+    fn allocate(
+        &mut self,
+        size: Size<DevicePixels>,
+        texture_kind: AtlasTextureKind,
+    ) -> Option<AtlasTile> {
         {
             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,