From 4fb9f41e6954fe6b51faaae60dea955f133b9a7b Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:09:09 +0200 Subject: [PATCH] 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. --- crates/gpui/src/geometry.rs | 29 +++++++++++++++++++++ crates/gpui/src/platform/mac/metal_atlas.rs | 9 +++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/gpui/src/geometry.rs b/crates/gpui/src/geometry.rs index 7eec24b2d1..53f83ec78f 100644 --- a/crates/gpui/src/geometry.rs +++ b/crates/gpui/src/geometry.rs @@ -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 Sub for Size diff --git a/crates/gpui/src/platform/mac/metal_atlas.rs b/crates/gpui/src/platform/mac/metal_atlas.rs index 7c23fafcba..22401ba6d4 100644 --- a/crates/gpui/src/platform/mac/metal_atlas.rs +++ b/crates/gpui/src/platform/mac/metal_atlas.rs @@ -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 = 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());