gpui/metal: Clamp max texture width/height to 16kB (#10314)

Fixed #10149
A user had Zed crash due to invalid font size in settings. It turned out
the width/height of glyphs does not pass validation in Metal texture
initialization with a large enough font size.

All modern Macs have a max texture width/height of 16kB (barring Apple
A8, used by iPhone 6 back in 2014, which uses 8kB). This commit clamps
texture size at 16kB. Note that while it fixes Zed crash, using a font
size that hits the limit is still pretty unusable - the users will still
have a pretty unusable editor, but at least it won't crash for them.



Release Notes:

- Fixed crashes with huge `buffer_font_size` values.
This commit is contained in:
Piotr Osiewicz 2024-04-09 14:09:09 +02:00 committed by GitHub
parent 935e0d547e
commit 4fb9f41e69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 2 deletions

View File

@ -528,6 +528,35 @@ where
},
}
}
/// Returns a new `Size` with the minimum width and height from `self` and `other`.
///
/// # Arguments
///
/// * `other` - A reference to another `Size` to compare with `self`.
///
/// # Examples
///
/// ```
/// # use zed::Size;
/// let size1 = Size { width: 30, height: 40 };
/// let size2 = Size { width: 50, height: 20 };
/// let min_size = size1.min(&size2);
/// assert_eq!(min_size, Size { width: 30, height: 20 });
/// ```
pub fn min(&self, other: &Self) -> Self {
Size {
width: if self.width >= other.width {
other.width.clone()
} else {
self.width.clone()
},
height: if self.height >= other.height {
other.height.clone()
} else {
self.height.clone()
},
}
}
}
impl<T> Sub for Size<T>

View File

@ -83,6 +83,7 @@ impl MetalAtlasState {
AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
AtlasTextureKind::Path => &mut self.path_textures,
};
textures
.iter_mut()
.rev()
@ -102,8 +103,12 @@ impl MetalAtlasState {
width: DevicePixels(1024),
height: DevicePixels(1024),
};
let size = min_size.max(&DEFAULT_ATLAS_SIZE);
// Max texture size on all modern Apple GPUs. Anything bigger than that crashes in validateWithDevice.
const MAX_ATLAS_SIZE: Size<DevicePixels> = Size {
width: DevicePixels(16384),
height: DevicePixels(16384),
};
let size = min_size.min(&MAX_ATLAS_SIZE).max(&DEFAULT_ATLAS_SIZE);
let texture_descriptor = metal::TextureDescriptor::new();
texture_descriptor.set_width(size.width.into());
texture_descriptor.set_height(size.height.into());