From 9ad1862f2fb118d83ee16da9cd7c05aaa3e25e57 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 16 Feb 2024 13:39:40 -0800 Subject: [PATCH] Enable Blade on MacOS via "macos-blade" feature (#7669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depends on https://github.com/zed-industries/font-kit/pull/2 and https://github.com/kvark/blade/pull/77 This change enables Blade to be also used on MacOS. It will also make it easier to use it on Windows. What works: most of the things. Zed loads as fast and appears equally responsive to the current renderer. Screenshot 2024-02-11 at 12 09 15 AM Things missing: - [x] video streaming. ~~Requires a bit of plumbing on both Blade and Zed sides, but all fairly straightforward.~~ - verified with a local setup - [x] resize. ~~Not sure where exactly to hook up the reaction on the window size change. Once we know where, the fix is one line.~~ - [ ] fine-tune CA Layer - this isn't a blocker for merging the PR, but it would be a blocker if we wanted to switch to the new path by default - [ ] rebase on latest, get the dependency merged (need review/merge of https://github.com/zed-industries/font-kit/pull/2!) Update: I implemented resize support as well as "surface" rendering on the Blade path (which will be useful on Linux/Windows later on). I haven't tested the latter though - not sure how to get something streaming. Would appreciate some help! I don't think this should be a blocker to this PR, anyway. The only little piece that's missing for the Blade on MacOS path to be full-featured is fine-tuning the CALayer configuration. Zed does a lot of careful logic in configuring the layer, such as switching the "present with transaction" on/off intermittently, which Blade path doesn't have yet. Release Notes: - N/A --------- Co-authored-by: Mikayla --- .github/workflows/ci.yml | 4 +- Cargo.lock | 42 +-- Cargo.toml | 3 + crates/gpui/Cargo.toml | 21 +- crates/gpui/build.rs | 11 +- crates/gpui/src/gpui.rs | 5 +- crates/gpui/src/platform.rs | 6 + crates/gpui/src/platform/blade.rs | 8 + .../platform/{linux => blade}/blade_atlas.rs | 0 .../platform/{linux => blade}/blade_belt.rs | 0 .../{linux => blade}/blade_renderer.rs | 245 ++++++++++++++++-- .../platform/{linux => blade}/shaders.wgsl | 57 +++- crates/gpui/src/platform/linux.rs | 6 - .../gpui/src/platform/linux/wayland/window.rs | 14 +- crates/gpui/src/platform/linux/x11/window.rs | 33 ++- crates/gpui/src/platform/mac.rs | 15 +- crates/gpui/src/platform/mac/display_link.rs | 10 +- crates/gpui/src/platform/mac/events.rs | 2 +- .../gpui/src/platform/mac/metal_renderer.rs | 59 +++-- crates/gpui/src/platform/mac/platform.rs | 9 +- crates/gpui/src/platform/mac/window.rs | 85 ++++-- crates/media/Cargo.toml | 4 +- script/bundle | 16 +- 23 files changed, 492 insertions(+), 163 deletions(-) create mode 100644 crates/gpui/src/platform/blade.rs rename crates/gpui/src/platform/{linux => blade}/blade_atlas.rs (100%) rename crates/gpui/src/platform/{linux => blade}/blade_belt.rs (100%) rename crates/gpui/src/platform/{linux => blade}/blade_renderer.rs (69%) rename crates/gpui/src/platform/{linux => blade}/shaders.wgsl (92%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c9ab70384..6f07444983 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,8 +91,8 @@ jobs: - name: Build collab run: cargo build -p collab - - name: Build other binaries - run: cargo build --workspace --bins --all-features + - name: Build other binaries and features + run: cargo build --workspace --bins --all-features; cargo check -p gpui --features "macos-blade" # todo!(linux): Actually run the tests linux_tests: diff --git a/Cargo.lock b/Cargo.lock index 137d0c4c7b..b1beef1343 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1396,7 +1396,7 @@ dependencies = [ [[package]] name = "blade-graphics" version = "0.3.0" -source = "git+https://github.com/kvark/blade?rev=c4f951a88b345724cb952e920ad30e39851f7760#c4f951a88b345724cb952e920ad30e39851f7760" +source = "git+https://github.com/kvark/blade?rev=e9d93a4d41f3946a03ffb76136290d6ccf7f2b80#e9d93a4d41f3946a03ffb76136290d6ccf7f2b80" dependencies = [ "ash", "ash-window", @@ -1413,7 +1413,7 @@ dependencies = [ "khronos-egl", "libloading 0.8.0", "log", - "metal 0.25.0", + "metal", "mint", "naga", "objc", @@ -1426,7 +1426,7 @@ dependencies = [ [[package]] name = "blade-macros" version = "0.2.1" -source = "git+https://github.com/kvark/blade?rev=c4f951a88b345724cb952e920ad30e39851f7760#c4f951a88b345724cb952e920ad30e39851f7760" +source = "git+https://github.com/kvark/blade?rev=e9d93a4d41f3946a03ffb76136290d6ccf7f2b80#e9d93a4d41f3946a03ffb76136290d6ccf7f2b80" dependencies = [ "proc-macro2", "quote", @@ -2359,13 +2359,13 @@ dependencies = [ [[package]] name = "core-text" -version = "19.2.0" +version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ "core-foundation", - "core-graphics 0.22.3", - "foreign-types 0.3.2", + "core-graphics 0.23.1", + "foreign-types 0.5.0", "libc", ] @@ -3511,12 +3511,12 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "font-kit" version = "0.11.0" -source = "git+https://github.com/zed-industries/font-kit?rev=d97147f#d97147ff11a9024b9707d9c9c7e3a0bdaba048ac" +source = "git+https://github.com/zed-industries/font-kit?rev=5a5c4d4#5a5c4d4ca395c74eb0abde38508e170ce0fd761a" dependencies = [ "bitflags 1.3.2", "byteorder", "core-foundation", - "core-graphics 0.22.3", + "core-graphics 0.23.1", "core-text", "dirs-next", "dwrote", @@ -4085,7 +4085,7 @@ dependencies = [ "cocoa", "collections", "core-foundation", - "core-graphics 0.22.3", + "core-graphics 0.23.1", "core-text", "cosmic-text", "ctor", @@ -4095,7 +4095,7 @@ dependencies = [ "etagere", "flume", "font-kit", - "foreign-types 0.3.2", + "foreign-types 0.5.0", "futures 0.3.28", "gpui_macros", "image", @@ -4104,7 +4104,7 @@ dependencies = [ "linkme", "log", "media", - "metal 0.21.0", + "metal", "num_cpus", "objc", "open", @@ -5350,8 +5350,8 @@ dependencies = [ "block", "bytes 1.5.0", "core-foundation", - "foreign-types 0.3.2", - "metal 0.21.0", + "foreign-types 0.5.0", + "metal", "objc", ] @@ -5423,20 +5423,6 @@ dependencies = [ "serde", ] -[[package]] -name = "metal" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "foreign-types 0.3.2", - "log", - "objc", -] - [[package]] name = "metal" version = "0.25.0" diff --git a/Cargo.toml b/Cargo.toml index 16a9dd6666..7363239a84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,6 +181,9 @@ anyhow = "1.0.57" async-compression = { version = "0.4", features = ["gzip", "futures-io"] } async-tar = "0.4.2" async-trait = "0.1" +blade-graphics = { git = "https://github.com/kvark/blade", rev = "e9d93a4d41f3946a03ffb76136290d6ccf7f2b80" } +blade-macros = { git = "https://github.com/kvark/blade", rev = "e9d93a4d41f3946a03ffb76136290d6ccf7f2b80" } +blade-rwh = { package = "raw-window-handle", version = "0.5" } chrono = { version = "0.4", features = ["serde"] } ctor = "0.2.6" derive_more = "0.99.17" diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 3421f3388e..7272fd4e43 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -16,6 +16,7 @@ test-support = [ "util/test-support", ] runtime_shaders = [] +macos-blade = ["blade-graphics", "blade-macros", "blade-rwh", "bytemuck"] [lib] path = "src/gpui.rs" @@ -26,6 +27,10 @@ anyhow.workspace = true async-task = "4.7" backtrace = { version = "0.3", optional = true } bitflags = "2.4.0" +blade-graphics = { workspace = true, optional = true } +blade-macros = { workspace = true, optional = true } +blade-rwh = { workspace = true, optional = true } +bytemuck = { version = "1", optional = true } collections.workspace = true ctor.workspace = true derive_more.workspace = true @@ -33,7 +38,7 @@ dhat = { version = "0.3", optional = true } env_logger = { version = "0.9", optional = true } etagere = "0.2" futures.workspace = true -font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "d97147f" } +font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "5a5c4d4" } gpui_macros.workspace = true image = "0.23" itertools = "0.10" @@ -48,7 +53,6 @@ pathfinder_geometry = "0.5" postage.workspace = true rand.workspace = true raw-window-handle = "0.6" -blade-rwh = { package = "raw-window-handle", version = "0.5" } refineable.workspace = true resvg = "0.14" schemars.workspace = true @@ -86,12 +90,12 @@ cbindgen = "0.26.0" block = "0.1" cocoa = "0.25" core-foundation = { version = "0.9.3", features = ["with-uuid"] } -core-graphics = "0.22.3" -core-text = "19.2" -foreign-types = "0.3" +core-graphics = "0.23" +core-text = "20.1" +foreign-types = "0.5" log.workspace = true media.workspace = true -metal = "0.21.0" +metal = "0.25" objc = "0.2" [target.'cfg(target_os = "linux")'.dependencies] @@ -105,8 +109,9 @@ wayland-protocols = { version = "0.31.2", features = ["client"] } wayland-backend = { version = "0.3.3", features = ["client_system"] } as-raw-xcb-connection = "1" #TODO: use these on all platforms -blade-graphics = { git = "https://github.com/kvark/blade", rev = "c4f951a88b345724cb952e920ad30e39851f7760" } -blade-macros = { git = "https://github.com/kvark/blade", rev = "c4f951a88b345724cb952e920ad30e39851f7760" } +blade-graphics.workspace = true +blade-macros.workspace = true +blade-rwh.workspace = true bytemuck = "1" cosmic-text = "0.10.0" xkbcommon = { version = "0.7", features = ["x11"] } diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index 3a1712b3df..6d6f384bc5 100644 --- a/crates/gpui/build.rs +++ b/crates/gpui/build.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(target_os = "macos"), allow(unused))] +#![cfg_attr(any(not(target_os = "macos"), feature = "macos-blade"), allow(unused))] use std::{ env, @@ -7,15 +7,18 @@ use std::{ use cbindgen::Config; +//TODO: consider generating shader code for WGSL +//TODO: deprecate "runtime-shaders" and "macos-blade" + fn main() { #[cfg(target_os = "macos")] generate_dispatch_bindings(); - #[cfg(target_os = "macos")] + #[cfg(all(target_os = "macos", not(feature = "macos-blade")))] let header_path = generate_shader_bindings(); - #[cfg(target_os = "macos")] + #[cfg(all(target_os = "macos", not(feature = "macos-blade")))] #[cfg(feature = "runtime_shaders")] emit_stitched_shaders(&header_path); - #[cfg(target_os = "macos")] + #[cfg(all(target_os = "macos", not(feature = "macos-blade")))] #[cfg(not(feature = "runtime_shaders"))] compile_metal_shaders(&header_path); } diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 79115a8d78..ff1daa59ea 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -60,8 +60,9 @@ //! and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). #![deny(missing_docs)] -#![allow(clippy::type_complexity)] -#![allow(clippy::collapsible_else_if)] +#![allow(clippy::type_complexity)] // Not useful, GPUI makes heavy use of callbacks +#![allow(clippy::collapsible_else_if)] // False positives in platform specific code +#![allow(unused_mut)] // False positives in platform specific code #[macro_use] mod action; diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 6739fee6fc..cf3ded1285 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -3,10 +3,16 @@ mod app_menu; mod keystroke; + #[cfg(target_os = "linux")] mod linux; + #[cfg(target_os = "macos")] mod mac; + +#[cfg(any(target_os = "linux", feature = "macos-blade"))] +mod blade; + #[cfg(any(test, feature = "test-support"))] mod test; diff --git a/crates/gpui/src/platform/blade.rs b/crates/gpui/src/platform/blade.rs new file mode 100644 index 0000000000..830f69daed --- /dev/null +++ b/crates/gpui/src/platform/blade.rs @@ -0,0 +1,8 @@ +mod blade_atlas; +mod blade_belt; +mod blade_renderer; + +pub(crate) use blade_atlas::*; +pub(crate) use blade_renderer::*; + +use blade_belt::*; diff --git a/crates/gpui/src/platform/linux/blade_atlas.rs b/crates/gpui/src/platform/blade/blade_atlas.rs similarity index 100% rename from crates/gpui/src/platform/linux/blade_atlas.rs rename to crates/gpui/src/platform/blade/blade_atlas.rs diff --git a/crates/gpui/src/platform/linux/blade_belt.rs b/crates/gpui/src/platform/blade/blade_belt.rs similarity index 100% rename from crates/gpui/src/platform/linux/blade_belt.rs rename to crates/gpui/src/platform/blade/blade_belt.rs diff --git a/crates/gpui/src/platform/linux/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs similarity index 69% rename from crates/gpui/src/platform/linux/blade_renderer.rs rename to crates/gpui/src/platform/blade/blade_renderer.rs index 5a9beec598..ce835073b1 100644 --- a/crates/gpui/src/platform/linux/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -1,14 +1,18 @@ // Doing `if let` gives you nice scoping with passes/encoders #![allow(irrefutable_let_patterns)] -use super::{BladeBelt, BladeBeltDescriptor}; +use super::{BladeAtlas, BladeBelt, BladeBeltDescriptor, PATH_TEXTURE_FORMAT}; use crate::{ - AtlasTextureKind, AtlasTile, BladeAtlas, Bounds, ContentMask, Hsla, MonochromeSprite, Path, - PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, - Underline, PATH_TEXTURE_FORMAT, + AtlasTextureKind, AtlasTile, Bounds, ContentMask, Hsla, MonochromeSprite, Path, PathId, + PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, + Underline, }; use bytemuck::{Pod, Zeroable}; use collections::HashMap; +#[cfg(target_os = "macos")] +use media::core_video::CVMetalTextureCache; +#[cfg(target_os = "macos")] +use std::ffi::c_void; use blade_graphics as gpu; use std::{mem, sync::Arc}; @@ -16,6 +20,61 @@ use std::{mem, sync::Arc}; const SURFACE_FRAME_COUNT: u32 = 3; const MAX_FRAME_TIME_MS: u32 = 1000; +pub type Context = (); +pub type Renderer = BladeRenderer; + +#[cfg(target_os = "macos")] +pub unsafe fn new_renderer( + _context: self::Context, + native_window: *mut c_void, + native_view: *mut c_void, + bounds: crate::Size, +) -> Renderer { + struct RawWindow { + window: *mut c_void, + view: *mut c_void, + } + + unsafe impl blade_rwh::HasRawWindowHandle for RawWindow { + fn raw_window_handle(&self) -> blade_rwh::RawWindowHandle { + let mut wh = blade_rwh::AppKitWindowHandle::empty(); + wh.ns_window = self.window; + wh.ns_view = self.view; + wh.into() + } + } + + unsafe impl blade_rwh::HasRawDisplayHandle for RawWindow { + fn raw_display_handle(&self) -> blade_rwh::RawDisplayHandle { + let dh = blade_rwh::AppKitDisplayHandle::empty(); + dh.into() + } + } + + let gpu = Arc::new( + gpu::Context::init_windowed( + &RawWindow { + window: native_window as *mut _, + view: native_view as *mut _, + }, + gpu::ContextDesc { + validation: cfg!(debug_assertions), + capture: false, + }, + ) + .unwrap(), + ); + + BladeRenderer::new( + gpu, + gpu::Extent { + width: bounds.width as u32, + height: bounds.height as u32, + depth: 1, + }, + ) +} + #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] struct GlobalParams { @@ -23,6 +82,31 @@ struct GlobalParams { pad: [u32; 2], } +//Note: we can't use `Bounds` directly here because +// it doesn't implement Pod + Zeroable +#[repr(C)] +#[derive(Clone, Copy, Pod, Zeroable)] +struct PodBounds { + origin: [f32; 2], + size: [f32; 2], +} + +impl From> for PodBounds { + fn from(bounds: Bounds) -> Self { + Self { + origin: [bounds.origin.x.0, bounds.origin.y.0], + size: [bounds.size.width.0, bounds.size.height.0], + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Pod, Zeroable)] +struct SurfaceParams { + bounds: PodBounds, + content_mask: PodBounds, +} + #[derive(blade_macros::ShaderData)] struct ShaderQuadsData { globals: GlobalParams, @@ -71,6 +155,15 @@ struct ShaderPolySpritesData { b_poly_sprites: gpu::BufferPiece, } +#[derive(blade_macros::ShaderData)] +struct ShaderSurfacesData { + globals: GlobalParams, + surface_locals: SurfaceParams, + t_y: gpu::TextureView, + t_cb_cr: gpu::TextureView, + s_surface: gpu::Sampler, +} + #[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] struct PathSprite { @@ -87,6 +180,7 @@ struct BladePipelines { underlines: gpu::RenderPipeline, mono_sprites: gpu::RenderPipeline, poly_sprites: gpu::RenderPipeline, + surfaces: gpu::RenderPipeline, } impl BladePipelines { @@ -96,6 +190,8 @@ impl BladePipelines { let shader = gpu.create_shader(gpu::ShaderDesc { source: include_str!("shaders.wgsl"), }); + shader.check_struct_size::(); + shader.check_struct_size::(); shader.check_struct_size::(); shader.check_struct_size::(); assert_eq!( @@ -220,6 +316,22 @@ impl BladePipelines { write_mask: gpu::ColorWrites::default(), }], }), + surfaces: gpu.create_render_pipeline(gpu::RenderPipelineDesc { + name: "surfaces", + data_layouts: &[&ShaderSurfacesData::layout()], + vertex: shader.at("vs_surface"), + primitive: gpu::PrimitiveState { + topology: gpu::PrimitiveTopology::TriangleStrip, + ..Default::default() + }, + depth_stencil: None, + fragment: shader.at("fs_surface"), + color_targets: &[gpu::ColorTargetState { + format: surface_format, + blend: Some(gpu::BlendState::ALPHA_BLENDING), + write_mask: gpu::ColorWrites::default(), + }], + }), } } } @@ -234,6 +346,8 @@ pub struct BladeRenderer { path_tiles: HashMap, atlas: Arc, atlas_sampler: gpu::Sampler, + #[cfg(target_os = "macos")] + core_video_texture_cache: CVMetalTextureCache, } impl BladeRenderer { @@ -268,6 +382,12 @@ impl BladeRenderer { ..Default::default() }); + #[cfg(target_os = "macos")] + let core_video_texture_cache = unsafe { + use foreign_types::ForeignType as _; + CVMetalTextureCache::new(gpu.metal_device().as_ptr()).unwrap() + }; + Self { gpu, command_encoder, @@ -278,6 +398,8 @@ impl BladeRenderer { path_tiles: HashMap::default(), atlas, atlas_sampler, + #[cfg(target_os = "macos")] + core_video_texture_cache, } } @@ -289,27 +411,39 @@ impl BladeRenderer { } } - pub fn destroy(&mut self) { - self.wait_for_gpu(); - self.atlas.destroy(); - self.instance_belt.destroy(&self.gpu); - self.gpu.destroy_command_encoder(&mut self.command_encoder); - } + pub fn update_drawable_size(&mut self, size: Size) { + let gpu_size = gpu::Extent { + width: size.width as u32, + height: size.height as u32, + depth: 1, + }; - pub fn resize(&mut self, size: gpu::Extent) { - self.wait_for_gpu(); - self.gpu.resize(Self::make_surface_config(size)); - self.viewport_size = size; + if gpu_size != self.viewport_size() { + self.wait_for_gpu(); + self.gpu.resize(Self::make_surface_config(gpu_size)); + self.viewport_size = gpu_size; + } } pub fn viewport_size(&self) -> gpu::Extent { self.viewport_size } - pub fn atlas(&self) -> &Arc { + pub fn sprite_atlas(&self) -> &Arc { &self.atlas } + #[cfg(target_os = "macos")] + pub fn layer(&self) -> metal::MetalLayer { + self.gpu.metal_layer().unwrap() + } + + #[cfg(target_os = "macos")] + pub fn layer_ptr(&self) -> *mut metal::CAMetalLayer { + use metal::foreign_types::ForeignType as _; + self.gpu.metal_layer().unwrap().as_ptr() + } + fn rasterize_paths(&mut self, paths: &[Path]) { self.path_tiles.clear(); let mut vertices_by_texture_id = HashMap::default(); @@ -362,6 +496,13 @@ impl BladeRenderer { } } + pub fn destroy(&mut self) { + self.wait_for_gpu(); + self.atlas.destroy(); + self.instance_belt.destroy(&self.gpu); + self.gpu.destroy_command_encoder(&mut self.command_encoder); + } + pub fn draw(&mut self, scene: &Scene) { let frame = self.gpu.acquire_frame(); self.command_encoder.start(); @@ -495,8 +636,78 @@ impl BladeRenderer { ); encoder.draw(0, 4, 0, sprites.len() as u32); } - PrimitiveBatch::Surfaces { .. } => { - unimplemented!() + PrimitiveBatch::Surfaces(surfaces) => { + let mut _encoder = pass.with(&self.pipelines.surfaces); + + for surface in surfaces { + #[cfg(not(target_os = "macos"))] + { + let _ = surface; + continue; + }; + + #[cfg(target_os = "macos")] + { + let (t_y, t_cb_cr) = { + use core_foundation::base::TCFType as _; + use std::ptr; + + assert_eq!( + surface.image_buffer.pixel_format_type(), + media::core_video::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange + ); + + let y_texture = unsafe { + self.core_video_texture_cache + .create_texture_from_image( + surface.image_buffer.as_concrete_TypeRef(), + ptr::null(), + metal::MTLPixelFormat::R8Unorm, + surface.image_buffer.plane_width(0), + surface.image_buffer.plane_height(0), + 0, + ) + .unwrap() + }; + let cb_cr_texture = unsafe { + self.core_video_texture_cache + .create_texture_from_image( + surface.image_buffer.as_concrete_TypeRef(), + ptr::null(), + metal::MTLPixelFormat::RG8Unorm, + surface.image_buffer.plane_width(1), + surface.image_buffer.plane_height(1), + 1, + ) + .unwrap() + }; + ( + gpu::TextureView::from_metal_texture( + y_texture.as_texture_ref(), + ), + gpu::TextureView::from_metal_texture( + cb_cr_texture.as_texture_ref(), + ), + ) + }; + + _encoder.bind( + 0, + &ShaderSurfacesData { + globals, + surface_locals: SurfaceParams { + bounds: surface.bounds.into(), + content_mask: surface.content_mask.bounds.into(), + }, + t_y, + t_cb_cr, + s_surface: self.atlas_sampler, + }, + ); + + _encoder.draw(0, 4, 0, 1); + } + } } } } diff --git a/crates/gpui/src/platform/linux/shaders.wgsl b/crates/gpui/src/platform/blade/shaders.wgsl similarity index 92% rename from crates/gpui/src/platform/linux/shaders.wgsl rename to crates/gpui/src/platform/blade/shaders.wgsl index 0f117b1eab..f342dfc92c 100644 --- a/crates/gpui/src/platform/linux/shaders.wgsl +++ b/crates/gpui/src/platform/blade/shaders.wgsl @@ -1,9 +1,9 @@ -struct Globals { +struct GlobalParams { viewport_size: vec2, pad: vec2, } -var globals: Globals; +var globals: GlobalParams; var t_sprite: texture_2d; var s_sprite: sampler; @@ -563,7 +563,56 @@ fn fs_poly_sprite(input: PolySpriteVarying) -> @location(0) vec4 { color = vec4(vec3(grayscale), sample.a); } color.a *= saturate(0.5 - distance); - return color;; + return color; } -// --- surface sprites --- // +// --- surfaces --- // + +struct SurfaceParams { + bounds: Bounds, + content_mask: Bounds, +} + +var surface_locals: SurfaceParams; +var t_y: texture_2d; +var t_cb_cr: texture_2d; +var s_surface: sampler; + +const ycbcr_to_RGB = mat4x4( + vec4( 1.0000f, 1.0000f, 1.0000f, 0.0), + vec4( 0.0000f, -0.3441f, 1.7720f, 0.0), + vec4( 1.4020f, -0.7141f, 0.0000f, 0.0), + vec4(-0.7010f, 0.5291f, -0.8860f, 1.0), +); + +struct SurfaceVarying { + @builtin(position) position: vec4, + @location(0) texture_position: vec2, + @location(3) clip_distances: vec4, +} + +@vertex +fn vs_surface(@builtin(vertex_index) vertex_id: u32) -> SurfaceVarying { + let unit_vertex = vec2(f32(vertex_id & 1u), 0.5 * f32(vertex_id & 2u)); + + var out = SurfaceVarying(); + out.position = to_device_position(unit_vertex, surface_locals.bounds); + out.texture_position = unit_vertex; + out.clip_distances = distance_from_clip_rect(unit_vertex, surface_locals.bounds, surface_locals.content_mask); + return out; +} + +@fragment +fn fs_surface(input: SurfaceVarying) -> @location(0) vec4 { + // Alpha clip after using the derivatives. + if (any(input.clip_distances < vec4(0.0))) { + return vec4(0.0); + } + + let y_cb_cr = vec4( + textureSampleLevel(t_y, s_surface, input.texture_position, 0.0).r, + textureSampleLevel(t_cb_cr, s_surface, input.texture_position, 0.0).rg, + 1.0); + + return ycbcr_to_RGB * y_cb_cr; +} diff --git a/crates/gpui/src/platform/linux.rs b/crates/gpui/src/platform/linux.rs index 3b61eee54e..f8d398587d 100644 --- a/crates/gpui/src/platform/linux.rs +++ b/crates/gpui/src/platform/linux.rs @@ -1,6 +1,3 @@ -mod blade_atlas; -mod blade_belt; -mod blade_renderer; mod client; mod client_dispatcher; mod dispatcher; @@ -9,10 +6,7 @@ mod text_system; mod wayland; mod x11; -pub(crate) use blade_atlas::*; pub(crate) use dispatcher::*; pub(crate) use platform::*; pub(crate) use text_system::*; pub(crate) use x11::*; - -use blade_belt::*; diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index 1842ed7d26..247c142b11 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -13,12 +13,12 @@ use raw_window_handle::{ use wayland_client::{protocol::wl_surface, Proxy}; use wayland_protocols::xdg::shell::client::xdg_toplevel; -use crate::platform::linux::blade_renderer::BladeRenderer; +use crate::platform::blade::BladeRenderer; use crate::platform::linux::wayland::display::WaylandDisplay; use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow}; use crate::scene::Scene; use crate::{ - px, Bounds, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point, PromptLevel, Size, + px, size, Bounds, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point, PromptLevel, Size, WindowAppearance, WindowBounds, WindowOptions, }; @@ -150,11 +150,9 @@ impl WaylandWindowState { let mut inner = self.inner.lock(); inner.bounds.size.width = width; inner.bounds.size.height = height; - inner.renderer.resize(gpu::Extent { - width: width as u32, - height: height as u32, - depth: 1, - }); + inner + .renderer + .update_drawable_size(size(width as f64, height as f64)); } let mut callbacks = self.callbacks.lock(); if let Some(ref mut fun) = callbacks.resize { @@ -341,7 +339,7 @@ impl PlatformWindow for WaylandWindow { fn sprite_atlas(&self) -> Arc { let inner = self.0.inner.lock(); - inner.renderer.atlas().clone() + inner.renderer.sprite_atlas().clone() } fn set_graphics_profiler_enabled(&self, enabled: bool) { diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index c834a951f1..b5904cd425 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -1,6 +1,20 @@ //todo!(linux): remove #![allow(unused)] +use crate::{ + platform::blade::BladeRenderer, size, Bounds, GlobalPixels, Pixels, PlatformDisplay, + PlatformInput, PlatformInputHandler, PlatformWindow, Point, Size, WindowAppearance, + WindowBounds, WindowOptions, X11Display, +}; +use blade_graphics as gpu; +use parking_lot::Mutex; +use raw_window_handle as rwh; + +use xcb::{ + x::{self, StackMode}, + Xid as _, +}; + use std::{ ffi::c_void, mem, @@ -10,17 +24,6 @@ use std::{ sync::{self, Arc}, }; -use blade_graphics as gpu; -use parking_lot::Mutex; -use raw_window_handle as rwh; -use xcb::{x, Xid as _}; - -use crate::platform::linux::blade_renderer::BladeRenderer; -use crate::{ - Bounds, GlobalPixels, Pixels, PlatformDisplay, PlatformInput, PlatformInputHandler, - PlatformWindow, Point, Size, WindowAppearance, WindowBounds, WindowOptions, X11Display, -}; - #[derive(Default)] struct Callbacks { request_frame: Option>, @@ -293,9 +296,13 @@ impl X11WindowState { let mut inner = self.inner.lock(); let old_bounds = mem::replace(&mut inner.bounds, bounds); do_move = old_bounds.origin != bounds.origin; + //todo!(linux): use normal GPUI types here, refactor out the double + // viewport check and extra casts ( ) let gpu_size = query_render_extent(&self.xcb_connection, self.x_window); if inner.renderer.viewport_size() != gpu_size { - inner.renderer.resize(gpu_size); + inner + .renderer + .update_drawable_size(size(gpu_size.width as f64, gpu_size.height as f64)); resize_args = Some((inner.content_size(), inner.scale_factor)); } } @@ -493,7 +500,7 @@ impl PlatformWindow for X11Window { fn sprite_atlas(&self) -> sync::Arc { let inner = self.0.inner.lock(); - inner.renderer.atlas().clone() + inner.renderer.sprite_atlas().clone() } fn set_graphics_profiler_enabled(&self, enabled: bool) { diff --git a/crates/gpui/src/platform/mac.rs b/crates/gpui/src/platform/mac.rs index ef1c830099..15d10225ba 100644 --- a/crates/gpui/src/platform/mac.rs +++ b/crates/gpui/src/platform/mac.rs @@ -4,8 +4,18 @@ mod dispatcher; mod display; mod display_link; mod events; + +#[cfg(not(feature = "macos-blade"))] mod metal_atlas; -mod metal_renderer; +#[cfg(not(feature = "macos-blade"))] +pub mod metal_renderer; + +#[cfg(not(feature = "macos-blade"))] +use metal_renderer as renderer; + +#[cfg(feature = "macos-blade")] +use crate::platform::blade as renderer; + mod open_type; mod platform; mod text_system; @@ -17,14 +27,13 @@ use cocoa::{ base::{id, nil}, foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger}, }; -use metal_renderer::*; + use objc::runtime::{BOOL, NO, YES}; use std::ops::Range; pub(crate) use dispatcher::*; pub(crate) use display::*; pub(crate) use display_link::*; -pub(crate) use metal_atlas::*; pub(crate) use platform::*; pub(crate) use text_system::*; pub(crate) use window::*; diff --git a/crates/gpui/src/platform/mac/display_link.rs b/crates/gpui/src/platform/mac/display_link.rs index 2488a08797..782c34486d 100644 --- a/crates/gpui/src/platform/mac/display_link.rs +++ b/crates/gpui/src/platform/mac/display_link.rs @@ -111,11 +111,11 @@ mod sys { pub enum CVDisplayLink {} foreign_type! { - type CType = CVDisplayLink; - fn drop = CVDisplayLinkRelease; - fn clone = CVDisplayLinkRetain; - pub struct DisplayLink; - pub struct DisplayLinkRef; + pub unsafe type DisplayLink { + type CType = CVDisplayLink; + fn drop = CVDisplayLinkRelease; + fn clone = CVDisplayLinkRetain; + } } impl Debug for DisplayLink { diff --git a/crates/gpui/src/platform/mac/events.rs b/crates/gpui/src/platform/mac/events.rs index 4653ce89b4..d8bc18bd63 100644 --- a/crates/gpui/src/platform/mac/events.rs +++ b/crates/gpui/src/platform/mac/events.rs @@ -13,7 +13,7 @@ use core_graphics::{ event_source::{CGEventSource, CGEventSourceStateID}, }; use ctor::ctor; -use foreign_types::ForeignType; +use metal::foreign_types::ForeignType as _; use objc::{class, msg_send, sel, sel_impl}; use std::{borrow::Cow, ffi::CStr, mem, os::raw::c_char, ptr}; diff --git a/crates/gpui/src/platform/mac/metal_renderer.rs b/crates/gpui/src/platform/mac/metal_renderer.rs index 6b30787b52..d7a027e5cb 100644 --- a/crates/gpui/src/platform/mac/metal_renderer.rs +++ b/crates/gpui/src/platform/mac/metal_renderer.rs @@ -1,19 +1,20 @@ +use super::metal_atlas::MetalAtlas; use crate::{ - platform::mac::ns_string, point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, - ContentMask, DevicePixels, Hsla, MetalAtlas, MonochromeSprite, Path, PathId, PathVertex, - PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, Surface, Underline, + point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, + Hsla, MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, + ScaledPixels, Scene, Shadow, Size, Surface, Underline, }; use block::ConcreteBlock; use cocoa::{ - base::{nil, NO, YES}, - foundation::{NSDictionary, NSUInteger}, + base::{NO, YES}, + foundation::NSUInteger, quartzcore::AutoresizingMask, }; use collections::HashMap; use core_foundation::base::TCFType; use foreign_types::ForeignType; use media::core_video::CVMetalTextureCache; -use metal::{CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange}; +use metal::{CAMetalLayer, CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange}; use objc::{self, msg_send, sel, sel_impl}; use parking_lot::Mutex; use smallvec::SmallVec; @@ -29,6 +30,18 @@ const SHADERS_SOURCE_FILE: &'static str = include_str!(concat!(env!("OUT_DIR"), "/stitched_shaders.metal")); const INSTANCE_BUFFER_SIZE: usize = 2 * 1024 * 1024; // This is an arbitrary decision. There's probably a more optimal value (maybe even we could adjust dynamically...) +pub type Context = Arc>>; +pub type Renderer = MetalRenderer; + +pub unsafe fn new_renderer( + context: self::Context, + _native_window: *mut c_void, + _native_view: *mut c_void, + _bounds: crate::Size, +) -> Renderer { + MetalRenderer::new(context) +} + pub(crate) struct MetalRenderer { device: metal::Device, layer: metal::MetalLayer, @@ -196,25 +209,12 @@ impl MetalRenderer { &self.layer } - pub fn sprite_atlas(&self) -> &Arc { - &self.sprite_atlas + pub fn layer_ptr(&self) -> *mut CAMetalLayer { + self.layer.as_ptr() } - /// Enables or disables the Metal HUD for debugging purposes. Note that this only works - /// when the app is bundled and it has the `MetalHudEnabled` key set to true in Info.plist. - pub fn set_hud_enabled(&mut self, enabled: bool) { - unsafe { - if enabled { - let hud_properties = NSDictionary::dictionaryWithObject_forKey_( - nil, - ns_string("default"), - ns_string("mode"), - ); - let _: () = msg_send![&*self.layer, setDeveloperHUDProperties: hud_properties]; - } else { - let _: () = msg_send![&*self.layer, setDeveloperHUDProperties: NSDictionary::dictionary(nil)]; - } - } + pub fn sprite_atlas(&self) -> &Arc { + &self.sprite_atlas } pub fn set_presents_with_transaction(&mut self, presents_with_transaction: bool) { @@ -223,6 +223,19 @@ impl MetalRenderer { .set_presents_with_transaction(presents_with_transaction); } + pub fn update_drawable_size(&mut self, size: Size) { + unsafe { + let _: () = msg_send![ + self.layer(), + setDrawableSize: size + ]; + } + } + + pub fn destroy(&mut self) { + // nothing to do + } + pub fn draw(&mut self, scene: &Scene) { let layer = self.layer.clone(); let viewport_size = layer.drawable_size(); diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 403ea274ef..473fb5978a 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -52,6 +52,8 @@ use std::{ }; use time::UtcOffset; +use super::renderer; + #[allow(non_upper_case_globals)] const NSUTF8StringEncoding: NSUInteger = 4; @@ -145,7 +147,7 @@ pub(crate) struct MacPlatformState { background_executor: BackgroundExecutor, foreground_executor: ForegroundExecutor, text_system: Arc, - instance_buffer_pool: Arc>>, + renderer_context: renderer::Context, pasteboard: id, text_hash_pasteboard_type: id, metadata_pasteboard_type: id, @@ -175,7 +177,7 @@ impl MacPlatform { background_executor: BackgroundExecutor::new(dispatcher.clone()), foreground_executor: ForegroundExecutor::new(dispatcher), text_system: Arc::new(MacTextSystem::new()), - instance_buffer_pool: Arc::default(), + renderer_context: renderer::Context::default(), pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) }, text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") }, metadata_pasteboard_type: unsafe { ns_string("zed-metadata") }, @@ -494,12 +496,11 @@ impl Platform for MacPlatform { handle: AnyWindowHandle, options: WindowOptions, ) -> Box { - let instance_buffer_pool = self.0.lock().instance_buffer_pool.clone(); Box::new(MacWindow::open( handle, options, self.foreground_executor(), - instance_buffer_pool, + self.0.lock().renderer_context.clone(), )) } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index f57f6cfe5a..715845bb65 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -1,4 +1,4 @@ -use super::{global_bounds_from_ns_rect, ns_string, MacDisplay, MetalRenderer, NSRange}; +use super::{global_bounds_from_ns_rect, ns_string, renderer, MacDisplay, NSRange}; use crate::{ global_bounds_to_ns_rect, platform::PlatformInputHandler, point, px, size, AnyWindowHandle, Bounds, DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, GlobalPixels, @@ -23,7 +23,6 @@ use cocoa::{ }; use core_graphics::display::{CGDirectDisplayID, CGRect}; use ctor::ctor; -use foreign_types::ForeignTypeRef; use futures::channel::oneshot; use objc::{ class, @@ -322,7 +321,7 @@ struct MacWindowState { native_window: id, native_view: NonNull, display_link: Option, - renderer: MetalRenderer, + renderer: renderer::Renderer, kind: WindowKind, request_frame_callback: Option>, event_callback: Option bool>>, @@ -450,6 +449,13 @@ impl MacWindowState { get_scale_factor(self.native_window) } + fn update_drawable_size(&mut self, drawable_size: NSSize) { + self.renderer.update_drawable_size(Size { + width: drawable_size.width, + height: drawable_size.height, + }) + } + fn titlebar_height(&self) -> Pixels { unsafe { let frame = NSWindow::frame(self.native_window); @@ -478,7 +484,7 @@ impl MacWindow { handle: AnyWindowHandle, options: WindowOptions, executor: ForegroundExecutor, - instance_buffer_pool: Arc>>, + renderer_context: renderer::Context, ) -> Self { unsafe { let pool = NSAutoreleasePool::new(nil); @@ -541,13 +547,32 @@ impl MacWindow { let native_view = NSView::init(native_view); assert!(!native_view.is_null()); + let window_size = { + let bounds = match options.bounds { + WindowBounds::Fullscreen | WindowBounds::Maximized => { + native_window.screen().visibleFrame() + } + WindowBounds::Fixed(bounds) => global_bounds_to_ns_rect(bounds), + }; + let scale = get_scale_factor(native_window); + size( + bounds.size.width as f32 * scale, + bounds.size.height as f32 * scale, + ) + }; + let window = Self(Arc::new(Mutex::new(MacWindowState { handle, executor, native_window, native_view: NonNull::new_unchecked(native_view), display_link: None, - renderer: MetalRenderer::new(instance_buffer_pool), + renderer: renderer::new_renderer( + renderer_context, + native_window as *mut _, + native_view as *mut _, + window_size, + ), kind: options.kind, request_frame_callback: None, event_callback: None, @@ -704,6 +729,7 @@ impl MacWindow { impl Drop for MacWindow { fn drop(&mut self) { let mut this = self.0.lock(); + this.renderer.destroy(); let window = this.native_window; this.display_link.take(); this.executor @@ -1031,7 +1057,22 @@ impl PlatformWindow for MacWindow { /// Enables or disables the Metal HUD for debugging purposes. Note that this only works /// when the app is bundled and it has the `MetalHudEnabled` key set to true in Info.plist. fn set_graphics_profiler_enabled(&self, enabled: bool) { - self.0.lock().renderer.set_hud_enabled(enabled); + let this_lock = self.0.lock(); + let layer = this_lock.renderer.layer(); + + unsafe { + if enabled { + let hud_properties = NSDictionary::dictionaryWithObject_forKey_( + nil, + ns_string("default"), + ns_string("mode"), + ); + let _: () = msg_send![layer, setDeveloperHUDProperties: hud_properties]; + } else { + let _: () = + msg_send![layer, setDeveloperHUDProperties: NSDictionary::dictionary(nil)]; + } + } } } @@ -1487,31 +1528,28 @@ extern "C" fn close_window(this: &Object, _: Sel) { extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id { let window_state = unsafe { get_window_state(this) }; let window_state = window_state.as_ref().lock(); - window_state.renderer.layer().as_ptr() as id + window_state.renderer.layer_ptr() as id } extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) { let window_state = unsafe { get_window_state(this) }; let mut lock = window_state.as_ref().lock(); + let scale_factor = lock.scale_factor() as f64; + let size = lock.content_size(); + let drawable_size: NSSize = NSSize { + width: f64::from(size.width) * scale_factor, + height: f64::from(size.height) * scale_factor, + }; unsafe { - let scale_factor = lock.scale_factor() as f64; - let size = lock.content_size(); - let drawable_size: NSSize = NSSize { - width: f64::from(size.width) * scale_factor, - height: f64::from(size.height) * scale_factor, - }; - let _: () = msg_send![ lock.renderer.layer(), setContentsScale: scale_factor ]; - let _: () = msg_send![ - lock.renderer.layer(), - setDrawableSize: drawable_size - ]; } + lock.update_drawable_size(drawable_size); + if let Some(mut callback) = lock.resize_callback.take() { let content_size = lock.content_size(); let scale_factor = lock.scale_factor(); @@ -1523,7 +1561,7 @@ extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) { extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) { let window_state = unsafe { get_window_state(this) }; - let lock = window_state.as_ref().lock(); + let mut lock = window_state.as_ref().lock(); if lock.content_size() == size.into() { return; @@ -1539,12 +1577,7 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) { height: size.height * scale_factor, }; - unsafe { - let _: () = msg_send![ - lock.renderer.layer(), - setDrawableSize: drawable_size - ]; - } + lock.update_drawable_size(drawable_size); drop(lock); let mut lock = window_state.lock(); @@ -1561,6 +1594,7 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) { let window_state = unsafe { get_window_state(this) }; let mut lock = window_state.lock(); if let Some(mut callback) = lock.request_frame_callback.take() { + #[cfg(not(feature = "macos-blade"))] lock.renderer.set_presents_with_transaction(true); lock.stop_display_link(); drop(lock); @@ -1568,6 +1602,7 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) { let mut lock = window_state.lock(); lock.request_frame_callback = Some(callback); + #[cfg(not(feature = "macos-blade"))] lock.renderer.set_presents_with_transaction(false); lock.start_display_link(); } diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml index bb9751e9da..b15190765d 100644 --- a/crates/media/Cargo.toml +++ b/crates/media/Cargo.toml @@ -16,8 +16,8 @@ bytes = "1.2" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9.3" -foreign-types = "0.3" -metal = "0.21.0" +foreign-types = "0.5" +metal = "0.25" objc = "0.2" [build-dependencies] diff --git a/script/bundle b/script/bundle index a00e9183e9..a6414febcb 100755 --- a/script/bundle +++ b/script/bundle @@ -135,24 +135,24 @@ echo "Bundled ${app_path}" if [ "$local_arch" = false ]; then echo "Uploading dSYMs" - dsymutil --flat target/aarch64-apple-darwin/release/Zed - dsymutil --flat target/x86_64-apple-darwin/release/Zed + dsymutil --flat target/aarch64-apple-darwin/${target_dir}/Zed + dsymutil --flat target/x86_64-apple-darwin/${target_dir}/Zed version="$(cargo metadata --no-deps --manifest-path crates/zed/Cargo.toml --offline --format-version=1 | jq -r '.packages | map(select(.name == "zed"))[0].version')" if [ "$channel" == "nightly" ]; then version="$version-$(git rev-parse --short HEAD)" fi echo "Removing existing gzipped dSYMs" - rm -f target/aarch64-apple-darwin/release/Zed.dwarf.gz - rm -f target/x86_64-apple-darwin/release/Zed.dwarf.gz + rm -f target/aarch64-apple-darwin/${target_dir}/Zed.dwarf.gz + rm -f target/x86_64-apple-darwin/${target_dir}/Zed.dwarf.gz echo "Gzipping dSYMs" - gzip target/aarch64-apple-darwin/release/Zed.dwarf - gzip target/x86_64-apple-darwin/release/Zed.dwarf + gzip target/aarch64-apple-darwin/${target_dir}/Zed.dwarf + gzip target/x86_64-apple-darwin/${target_dir}/Zed.dwarf echo "Uploading dSYMs" - uploadDsym target/aarch64-apple-darwin/release/Zed.dwarf.gz "$channel/Zed-$version-aarch64-apple-darwin.dwarf.gz" - uploadDsym target/x86_64-apple-darwin/release/Zed.dwarf.gz "$channel/Zed-$version-x86_64-apple-darwin.dwarf.gz" + uploadDsym target/aarch64-apple-darwin/${target_dir}/Zed.dwarf.gz "$channel/Zed-$version-aarch64-apple-darwin.dwarf.gz" + uploadDsym target/x86_64-apple-darwin/${target_dir}/Zed.dwarf.gz "$channel/Zed-$version-x86_64-apple-darwin.dwarf.gz" echo "Creating fat binaries" lipo \