From bdf1d4edea065cb2a82f8bdcb415a68de537e6d4 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 23 Jul 2024 09:56:45 -0600 Subject: [PATCH] linux: Better GPU debugging (#14706) Release Notes: - linux: Added GPU information to `editor: Copy System Specs to Clipboard` - linux: Show a prominant warning before running under llvmpipe and similar. --- Cargo.lock | 27 +++++++------------ Cargo.toml | 6 ++--- crates/feedback/src/system_specs.rs | 21 +++++++++++++-- crates/gpui/Cargo.toml | 2 +- crates/gpui/src/gpui.rs | 13 +++++++++ crates/gpui/src/platform.rs | 5 ++-- .../gpui/src/platform/blade/blade_renderer.rs | 18 ++++++++++--- .../gpui/src/platform/linux/wayland/window.rs | 6 ++++- crates/gpui/src/platform/linux/x11/window.rs | 10 ++++--- crates/gpui/src/platform/mac/window.rs | 4 +++ crates/gpui/src/platform/test/window.rs | 10 ++++--- crates/gpui/src/platform/windows/window.rs | 4 +++ crates/gpui/src/window.rs | 8 +++++- crates/media/Cargo.toml | 2 +- crates/zed/src/zed.rs | 24 +++++++++++++++++ docs/src/linux.md | 24 ++++++++++------- 16 files changed, 136 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2000a385ee9d2c6ef21ae95ff4b6de8fec921fe..4b87d306586e0c2bc56494329e1f746f45edbdc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1651,7 +1651,7 @@ dependencies = [ [[package]] name = "blade-graphics" version = "0.4.0" -source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818" +source = "git+https://github.com/zed-industries/blade?rev=7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e#7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" dependencies = [ "ash", "ash-window", @@ -1681,7 +1681,7 @@ dependencies = [ [[package]] name = "blade-macros" version = "0.2.1" -source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818" +source = "git+https://github.com/zed-industries/blade?rev=7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e#7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" dependencies = [ "proc-macro2", "quote", @@ -1691,7 +1691,7 @@ dependencies = [ [[package]] name = "blade-util" version = "0.1.0" -source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818" +source = "git+https://github.com/zed-industries/blade?rev=7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e#7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" dependencies = [ "blade-graphics", "bytemuck", @@ -6644,11 +6644,11 @@ dependencies = [ [[package]] name = "metal" -version = "0.25.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550b24b0cd4cf923f36bae78eca457b3a10d8a6a14a9c84cb2687b527e6a84af" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "block", "core-graphics-types", "foreign-types 0.5.0", @@ -6749,8 +6749,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "naga" -version = "0.20.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=425526828f738c95ec50b016c6a761bc00d2fb25#425526828f738c95ec50b016c6a761bc00d2fb25" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09eeccb9b50f4f7839b214aa3e08be467159506a986c18e0702170ccf720a453" dependencies = [ "arrayvec", "bit-set 0.6.0", @@ -7180,16 +7181,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c564ffcb3a3eefdc5417aa3806c91d6bdfbca568..518b51819bc2dc397d8339305e077b380266a18a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -295,9 +295,9 @@ async-watch = "0.3.1" async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] } base64 = "0.13" bitflags = "2.6.0" -blade-graphics = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" } -blade-macros = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" } -blade-util = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" } +blade-graphics = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" } +blade-macros = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" } +blade-util = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" } cap-std = "3.0" cargo_toml = "0.20" chrono = { version = "0.4", features = ["serde"] } diff --git a/crates/feedback/src/system_specs.rs b/crates/feedback/src/system_specs.rs index e0448867eff859125560af84d2326beb331b945a..a5701801871b81d44e077d6620a70b02eb812659 100644 --- a/crates/feedback/src/system_specs.rs +++ b/crates/feedback/src/system_specs.rs @@ -1,10 +1,11 @@ use client::telemetry; -use gpui::{AppContext, Task}; +use gpui::Task; use human_bytes::human_bytes; use release_channel::{AppCommitSha, AppVersion, ReleaseChannel}; use serde::Serialize; use std::{env, fmt::Display}; use sysinfo::{MemoryRefreshKind, RefreshKind, System}; +use ui::WindowContext; #[derive(Clone, Debug, Serialize)] pub struct SystemSpecs { @@ -15,10 +16,11 @@ pub struct SystemSpecs { memory: u64, architecture: &'static str, commit_sha: Option, + gpu_specs: Option, } impl SystemSpecs { - pub fn new(cx: &AppContext) -> Task { + pub fn new(cx: &WindowContext) -> Task { let app_version = AppVersion::global(cx).to_string(); let release_channel = ReleaseChannel::global(cx); let os_name = telemetry::os_name(); @@ -34,6 +36,15 @@ impl SystemSpecs { _ => None, }; + let gpu_specs = if let Some(specs) = cx.gpu_specs() { + Some(format!( + "{} || {} || {}", + specs.device_name, specs.driver_name, specs.driver_info + )) + } else { + None + }; + cx.background_executor().spawn(async move { let os_version = telemetry::os_version(); SystemSpecs { @@ -44,6 +55,7 @@ impl SystemSpecs { memory, architecture, commit_sha, + gpu_specs, } }) } @@ -67,6 +79,11 @@ impl Display for SystemSpecs { format!("Architecture: {}", self.architecture), ] .into_iter() + .chain( + self.gpu_specs + .as_ref() + .map(|specs| format!("GPU: {}", specs)), + ) .collect::>() .join("\n"); diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 018cd3d723f81934f22b775c93c3f140c57faf46..ad2748eeb6b64c3c4a9e5ea192eee9c1f9998732 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -98,7 +98,7 @@ core-text = "20.1" foreign-types = "0.5" log.workspace = true media.workspace = true -metal = "0.25" +metal = "0.29" objc = "0.2" [target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies] diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 29ffed710da2c6417e9825f3518a6747220448ef..fa75d7ea0357cd323e5bc9a1e5700e57f7c92224 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -341,3 +341,16 @@ impl Flatten for Result { self } } + +#[derive(Default, Debug)] +/// Information about the GPU GPUI is running on +pub struct GPUSpecs { + /// true if the GPU is really a fake (like llvmpipe) running on the CPU + pub is_software_emulated: bool, + /// Name of the device as reported by vulkan + pub device_name: String, + /// Name of the driver as reported by vulkan + pub driver_name: String, + /// Further driver info as reported by vulkan + pub driver_info: String, +} diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 75a0c806c4b390e79384c08258857b6686309e09..8fc940532894c5eadedf172cbbf3b1a487d10cc2 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -24,8 +24,8 @@ mod windows; use crate::{ point, Action, AnyWindowHandle, AsyncWindowContext, BackgroundExecutor, Bounds, DevicePixels, - DispatchEventResult, Font, FontId, FontMetrics, FontRun, ForegroundExecutor, GlyphId, Keymap, - LineLayout, Pixels, PlatformInput, Point, RenderGlyphParams, RenderImageParams, + DispatchEventResult, Font, FontId, FontMetrics, FontRun, ForegroundExecutor, GPUSpecs, GlyphId, + Keymap, LineLayout, Pixels, PlatformInput, Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Scene, SharedString, Size, Task, TaskLabel, WindowContext, DEFAULT_WINDOW_SIZE, }; @@ -366,6 +366,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { } } fn set_client_inset(&self, _inset: Pixels) {} + fn gpu_specs(&self) -> Option; #[cfg(any(test, feature = "test-support"))] fn as_test(&mut self) -> Option<&mut TestWindow> { diff --git a/crates/gpui/src/platform/blade/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs index ee6026184678666eb90446257f870074e8e27a06..27e76b977855f4f2b5a9af5b2686014bef4ce21d 100644 --- a/crates/gpui/src/platform/blade/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -3,9 +3,9 @@ use super::{BladeAtlas, PATH_TEXTURE_FORMAT}; use crate::{ - AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, Hsla, MonochromeSprite, Path, - PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, - Underline, + AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, GPUSpecs, Hsla, + MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, + ScaledPixels, Scene, Shadow, Size, Underline, }; use bytemuck::{Pod, Zeroable}; use collections::HashMap; @@ -451,6 +451,18 @@ impl BladeRenderer { &self.atlas } + #[cfg_attr(target_os = "macos", allow(dead_code))] + pub fn gpu_specs(&self) -> GPUSpecs { + let info = self.gpu.device_information(); + + GPUSpecs { + is_software_emulated: info.is_software_emulated, + device_name: info.device_name.clone(), + driver_name: info.driver_name.clone(), + driver_info: info.driver_info.clone(), + } + } + #[cfg(target_os = "macos")] pub fn layer(&self) -> metal::MetalLayer { self.gpu.metal_layer().unwrap() diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index ba97f202fce5cdc335446ecbbb6169014b76ff88..c43ec18d0877abcef88e89bb5d115a8c69a5dc49 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -25,7 +25,7 @@ use crate::platform::linux::wayland::serial::SerialKind; use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow}; use crate::scene::Scene; use crate::{ - px, size, AnyWindowHandle, Bounds, Decorations, Globals, Modifiers, Output, Pixels, + px, size, AnyWindowHandle, Bounds, Decorations, GPUSpecs, Globals, Modifiers, Output, Pixels, PlatformDisplay, PlatformInput, Point, PromptLevel, ResizeEdge, Size, Tiling, WaylandClientStatePtr, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, WindowParams, @@ -1007,6 +1007,10 @@ impl PlatformWindow for WaylandWindow { update_window(state); } } + + fn gpu_specs(&self) -> Option { + self.borrow().renderer.gpu_specs().into() + } } fn update_window(mut state: RefMut) { diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index fb077634a9641e80d479a653427d90e522201a67..9e4908627ed9b2f6b33bdeb4d5edcab4aa070236 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -2,9 +2,9 @@ use anyhow::Context; use crate::{ platform::blade::{BladeRenderer, BladeSurfaceConfig}, - px, size, AnyWindowHandle, Bounds, Decorations, DevicePixels, ForegroundExecutor, Modifiers, - Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, - Point, PromptLevel, ResizeEdge, Scene, Size, Tiling, WindowAppearance, + px, size, AnyWindowHandle, Bounds, Decorations, DevicePixels, ForegroundExecutor, GPUSpecs, + Modifiers, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, + PlatformWindow, Point, PromptLevel, ResizeEdge, Scene, Size, Tiling, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowDecorations, WindowKind, WindowParams, X11ClientStatePtr, }; @@ -1385,4 +1385,8 @@ impl PlatformWindow for X11Window { appearance_changed(); } } + + fn gpu_specs(&self) -> Option { + self.0.state.borrow().renderer.gpu_specs().into() + } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index b5ce6719ee176371fe1a4820f6332a0e8a0c4ed2..35489115189b7d8f855befaad31112f3d3fd0bb6 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -1096,6 +1096,10 @@ impl PlatformWindow for MacWindow { fn sprite_atlas(&self) -> Arc { self.0.lock().renderer.sprite_atlas().clone() } + + fn gpu_specs(&self) -> Option { + None + } } impl rwh::HasWindowHandle for MacWindow { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 8c7ee5507a6daabbbcf9589703abcf4886342ab8..79a1c0440170c51b627348d8fb443b667bf226e4 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -1,7 +1,7 @@ use crate::{ - AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DispatchEventResult, Pixels, - PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, - Size, TestPlatform, TileId, WindowAppearance, WindowBackgroundAppearance, WindowBounds, + AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DispatchEventResult, GPUSpecs, + Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, + Point, Size, TestPlatform, TileId, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowParams, }; use collections::HashMap; @@ -273,6 +273,10 @@ impl PlatformWindow for TestWindow { fn start_window_move(&self) { unimplemented!() } + + fn gpu_specs(&self) -> Option { + None + } } pub(crate) struct TestAtlasState { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 50cdf063e2fa3f84f9cf0ef3b958139c1dec0188..01a71f70e0aaf1f4395bb799b288a8e57b709ba8 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -654,6 +654,10 @@ impl PlatformWindow for WindowsWindow { fn get_raw_handle(&self) -> HWND { self.0.hwnd } + + fn gpu_specs(&self) -> Option { + Some(self.0.state.borrow().renderer.gpu_specs()) + } } #[implement(IDropTarget)] diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index c5bada903eb721dbebe95990196f122d05231d52..4b2ebcbda1520998fbde515e61167b4249a69c09 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -3,7 +3,7 @@ use crate::{ AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, - FileDropEvent, Flatten, FontId, Global, GlobalElementId, GlyphId, Hsla, ImageData, + FileDropEvent, Flatten, FontId, GPUSpecs, Global, GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, @@ -3733,6 +3733,12 @@ impl<'a> WindowContext<'a> { .dispatch_tree .on_action(action_type, Rc::new(listener)); } + + /// Read information about the GPU backing this window. + /// Currently returns None on Mac and Windows. + pub fn gpu_specs(&self) -> Option { + self.window.platform_window.gpu_specs() + } } #[cfg(target_os = "windows")] diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml index ac22eccde675dba08d5f9c17305db39174df9d87..de26ac1203dc08cc87ef48ffc44b71cb4cb9320b 100644 --- a/crates/media/Cargo.toml +++ b/crates/media/Cargo.toml @@ -18,7 +18,7 @@ anyhow.workspace = true [target.'cfg(target_os = "macos")'.dependencies] core-foundation.workspace = true foreign-types = "0.5" -metal = "0.25" +metal = "0.29" objc = "0.2" [build-dependencies] diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 23573d458830b96586ecb080b34808c64b4fd319..7cdfbaeda0b568a8740ef785e6578322d1adf923 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -139,6 +139,30 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { }) .detach(); + if let Some(specs) = cx.gpu_specs() { + log::info!("Using GPU: {:?}", specs); + if specs.is_software_emulated && std::env::var("ZED_ALLOW_EMULATED_GPU").is_err() { + let message = format!(db::indoc!{r#" + Zed uses Vulkan for rendering and requires a compatible GPU. + + Currently you are using a software emulated GPU ({}) which + will result in awful performance. + + For troubleshooting see: https://zed.dev/docs/linux + "#}, specs.device_name); + let prompt = cx.prompt(PromptLevel::Critical, "Unsupported GPU", Some(&message), + &["Troubleshoot and Quit"]); + cx.spawn(|_, mut cx| async move { + if prompt.await == Ok(0) { + cx.update(|cx| { + cx.open_url("https://zed.dev/docs/linux#zed-fails-to-open-windows"); + cx.quit(); + }).ok(); + } + }).detach() + } + } + let inline_completion_button = cx.new_view(|cx| { inline_completion_button::InlineCompletionButton::new(app_state.fs.clone(), cx) }); diff --git a/docs/src/linux.md b/docs/src/linux.md index 27aaa951302b1a7f80497deac2c631e5dcbed7c4..537815d188511e37da4ee6ef8041c7720467273b 100644 --- a/docs/src/linux.md +++ b/docs/src/linux.md @@ -12,11 +12,14 @@ We also offer a preview build of Zed which receives updates about a week ahead o curl -f https://zed.dev/install.sh | ZED_CHANNEL=preview sh ``` -The install script does not work on systems that: -* have no system-wide glibc (for example on NixOS or Alpine) +The Zed installed by the script does not work on systems that: +* have no Vulkan compatible GPU available (for example Linux on an M-series macBook) +* have no system-wide glibc (for example on NixOS or Alpine by default) * have a glibc older than version 2.29 (for example Amazon Linux 2 or Ubuntu 18 and earlier) * use an architecture other than 64-bit Intel or 64-bit ARM (for example a 32-bit or RISC-V machine) +Both Nix and Alpine have third-party Zed packages available (though they are currently a few weeks out of date). If you'd like to use our builds they do work if you install a glibc compatibility layer. On NixOS you can try [nix-ld](https://github.com/Mic92/nix-ld), and on Alpine [gcompat](https://wiki.alpinelinux.org/wiki/Running_glibc_programs). + ## Other ways to install Zed on Linux Zed is open source, and [you can install from source](./development/linux.md). @@ -80,30 +83,31 @@ Linux works on a large variety of systems configured in many different ways. We If you see an error like "/lib64/libc.so.6: version 'GLIBC_2.29' not found" it means that your distribution's version of glibc is too old. You can either upgrade your system, or [install Zed from source](./development/linux.md). ### Zed fails to open windows +### Zed is very slow Zed requires a GPU to run effectively. Under the hood, we use [Vulkan](https://www.vulkan.org/) to communicate with your GPU. If you are seeing problems with performance, or Zed fails to load, it is possible that Vulkan is the culprit. If you're using an AMD GPU, you might get a 'Broken Pipe' error. Try using the RADV or Mesa drivers. (See the following GitHub issue for more details: [#13880](https://github.com/zed-industries/zed/issues/13880)). -Otherwise, if you see error messages like: "Zed failed to open a window: NoSupportedDeviceFound" or "called `Result::unwrap()` on an `Err` value: ERROR_INITIALIZATION_FAILED", you can begin troubleshooting Vulkan, by installing the `vulkan-tools` package, and running: +If you see a notification saying `Zed failed to open a window: NoSupportedDeviceFound` this means that Vulkan cannot find a compatible GPU. You can begin troubleshooting Vulkan by installing the `vulkan-tools` package and running: ```sh vkcube ``` -This should output a line describing your current graphics setup. If it contains `llvmpipe` then Vulkan is not using a GPU, which will make Zed run very slowly. +This should output a line describing your current graphics setup and show a rotating cube. If this does not work, you should be able to fix it by installing Vulkan compatible GPU drivers, however in some cases (for example running Linux on an Arm-based MacBook) there is no Vulkan support yet. -In most cases this can be fixed by configuring Vulkan and installing compatible GPU drivers, however in some cases (for example running Linux on an Arm-based MacBook) there is no Vulkan support yet. +If you see errors like `ERROR_INITIALIZATION_FAILED` or `GPU Crashed` or `ERROR_SURFACE_LOST_KHR` then you may be able to work around this by installing different drivers for your GPU, or by selecting a different GPU to run on. (See the following GitHub issue for more details: [#14225](https://github.com/zed-industries/zed/issues/14225)) -For more information, the [Arch guide to Vulkan](https://wiki.archlinux.org/title/Vulkan) has some good steps. +As of Zed v0.146.x we log the selected GPU driver and you should see `Using GPU: ...` in the Zed log (`~/.local/share/zed/logs/Zed.log`). -### Zed is very slow +If Zed is selecting your integrated GPU instead of your discrete GPU, you can fix this by exporting the environment variable `DRI_PRIME=1` before running Zed. -If you're on relatively modern hardware Zed should feel fast to use. That said, we do rely on the GPU to make rendering quick. +If you are using Mesa, and want more control over which GPU is selected you can run `MESA_VK_DEVICE_SELECT=list zed --foreground` to get a list of available GPUs and then export `MESA_VK_DEVICE_SELECT=xxxx:yyyy` to choose a specific device. -If you install the `vulkan-tools` package and run `vkcube` and you see `llvmpipe` in the output, you need to make sure your GPU is configured correctly. +If you are using `amdvlk` you may find that zed only opens when run with `sudo $(which zed)`. To fix this, remove the `amdvlk` and `lib32-amdvlk` packages and install mesa/vulkan instead. ([#14141](https://github.com/zed-industries/zed/issues/14141). -For more information, the [Arch guide to Vulkan](https://wiki.archlinux.org/title/Vulkan) has some good troubleshooting steps. +For more information, the [Arch guide to Vulkan](https://wiki.archlinux.org/title/Vulkan) has some good steps that translate well to most distributions. If Vulkan is configured correctly, and Zed is still slow for you, please [file an issue](https://github.com/zed-industries/zed) with as much information as possible.