diff --git a/Cargo.lock b/Cargo.lock index 6d0071e860..c5b09849fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -312,15 +312,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" -[[package]] -name = "ash" -version = "0.37.3+1.3.251" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" -dependencies = [ - "libloading 0.7.4", -] - [[package]] name = "async-broadcast" version = "0.4.1" @@ -1170,6 +1161,25 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" +[[package]] +name = "cbindgen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49" +dependencies = [ + "clap 3.2.25", + "heck 0.4.1", + "indexmap 1.9.3", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 1.0.109", + "tempfile", + "toml 0.5.11", +] + [[package]] name = "cc" version = "1.0.83" @@ -1441,7 +1451,7 @@ dependencies = [ "cocoa-foundation", "core-foundation", "core-graphics", - "foreign-types 0.3.2", + "foreign-types", "libc", "objc", ] @@ -1454,22 +1464,12 @@ dependencies = [ "bitflags 1.3.2", "block", "core-foundation", - "core-graphics-types 0.1.1", - "foreign-types 0.3.2", + "core-graphics-types", + "foreign-types", "libc", "objc", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "collab" version = "0.20.0" @@ -1597,12 +1597,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" -[[package]] -name = "com-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" - [[package]] name = "combine" version = "4.6.6" @@ -1760,8 +1754,8 @@ source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2f dependencies = [ "bitflags 1.3.2", "core-foundation", - "core-graphics-types 0.1.1", - "foreign-types 0.3.2", + "core-graphics-types", + "foreign-types", "libc", ] @@ -1772,18 +1766,7 @@ source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2f dependencies = [ "bitflags 1.3.2", "core-foundation", - "foreign-types 0.3.2", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", + "foreign-types", "libc", ] @@ -1804,7 +1787,7 @@ checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" dependencies = [ "core-foundation", "core-graphics", - "foreign-types 0.3.2", + "foreign-types", "libc", ] @@ -2104,17 +2087,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "d3d12" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20" -dependencies = [ - "bitflags 2.4.0", - "libloading 0.8.0", - "winapi 0.3.9", -] - [[package]] name = "dashmap" version = "5.5.1" @@ -2752,28 +2724,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared 0.3.1", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "foreign-types-shared", ] [[package]] @@ -2782,12 +2733,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - [[package]] name = "form_urlencoded" version = "1.2.0" @@ -3169,18 +3114,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "glow" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "go_to_line" version = "0.1.0" @@ -3196,58 +3129,6 @@ dependencies = [ "workspace", ] -[[package]] -name = "gpu-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.4.0", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.4.0", -] - -[[package]] -name = "gpu-allocator" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" -dependencies = [ - "backtrace", - "log", - "thiserror", - "winapi 0.3.9", - "windows 0.44.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" -dependencies = [ - "bitflags 1.3.2", - "gpu-descriptor-types", - "hashbrown 0.12.3", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "gpui" version = "0.1.0" @@ -3269,7 +3150,7 @@ dependencies = [ "env_logger 0.9.3", "etagere", "font-kit", - "foreign-types 0.3.2", + "foreign-types", "futures 0.3.28", "gpui_macros", "image", @@ -3277,7 +3158,7 @@ dependencies = [ "lazy_static", "log", "media", - "metal 0.21.0", + "metal", "num_cpus", "objc", "ordered-float", @@ -3350,6 +3231,7 @@ dependencies = [ "bindgen 0.65.1", "block", "bytemuck", + "cbindgen", "cocoa", "collections", "core-foundation", @@ -3361,7 +3243,7 @@ dependencies = [ "env_logger 0.9.3", "etagere", "font-kit", - "foreign-types 0.3.2", + "foreign-types", "futures 0.3.28", "gpui3_macros", "gpui_macros", @@ -3370,6 +3252,7 @@ dependencies = [ "lazy_static", "log", "media", + "metal", "num_cpus", "objc", "ordered-float", @@ -3380,7 +3263,6 @@ dependencies = [ "png", "postage", "rand 0.8.5", - "raw-window-handle", "refineable", "resvg", "schemars", @@ -3402,7 +3284,6 @@ dependencies = [ "util", "uuid 1.4.1", "waker-fn", - "wgpu", ] [[package]] @@ -3504,21 +3385,6 @@ dependencies = [ "hashbrown 0.14.0", ] -[[package]] -name = "hassle-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" -dependencies = [ - "bitflags 1.3.2", - "com-rs", - "libc", - "libloading 0.7.4", - "thiserror", - "widestring", - "winapi 0.3.9", -] - [[package]] name = "headers" version = "0.3.8" @@ -3592,12 +3458,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - [[package]] name = "hkdf" version = "0.12.3" @@ -4101,17 +3961,6 @@ dependencies = [ "winapi-build", ] -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.4", - "pkg-config", -] - [[package]] name = "kurbo" version = "0.8.3" @@ -4369,7 +4218,7 @@ dependencies = [ "collections", "core-foundation", "core-graphics", - "foreign-types 0.3.2", + "foreign-types", "futures 0.3.28", "gpui", "hmac 0.12.1", @@ -4544,8 +4393,8 @@ dependencies = [ "block", "bytes 1.4.0", "core-foundation", - "foreign-types 0.3.2", - "metal 0.21.0", + "foreign-types", + "metal", "objc", ] @@ -4607,26 +4456,11 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "foreign-types 0.3.2", + "foreign-types", "log", "objc", ] -[[package]] -name = "metal" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623b5e6cefd76e58f774bd3cc0c6f5c7615c58c03a97815245a25c3c9bdee318" -dependencies = [ - "bitflags 2.4.0", - "block", - "core-graphics-types 0.1.2", - "foreign-types 0.5.0", - "log", - "objc", - "paste", -] - [[package]] name = "mime" version = "0.3.17" @@ -4776,26 +4610,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" -[[package]] -name = "naga" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ceaaa4eedaece7e4ec08c55c640ba03dbb73fb812a6570a59bcf1930d0f70e" -dependencies = [ - "bit-set", - "bitflags 2.4.0", - "codespan-reporting", - "hexf-parse", - "indexmap 1.9.3", - "log", - "num-traits", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - [[package]] name = "nanoid" version = "0.4.0" @@ -5200,7 +5014,7 @@ checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", - "foreign-types 0.3.2", + "foreign-types", "libc", "once_cell", "openssl-macros", @@ -5744,12 +5558,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "profiling" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f10e75d83c7aec79a6aa46f897075890e156b105eebe51cfa0abce51af025f" - [[package]] name = "project" version = "0.1.0" @@ -6137,12 +5945,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - [[package]] name = "raw-window-handle" version = "0.5.2" @@ -6338,12 +6140,6 @@ dependencies = [ "bytecheck", ] -[[package]] -name = "renderdoc-sys" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" - [[package]] name = "reqwest" version = "0.11.19" @@ -7521,16 +7317,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags 1.3.2", - "num-traits", -] - [[package]] name = "spsc-buffer" version = "0.1.1" @@ -9002,12 +8788,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "unicode_categories" version = "0.1.1" @@ -9716,105 +9496,6 @@ dependencies = [ "workspace", ] -[[package]] -name = "wgpu" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7472f3b69449a8ae073f6ec41d05b6f846902d92a6c45313c50cb25857b736ce" -dependencies = [ - "arrayvec 0.7.4", - "cfg-if 1.0.0", - "js-sys", - "log", - "naga", - "parking_lot 0.12.1", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecf7454d9386f602f7399225c92dd2fbdcde52c519bc8fb0bd6fbeb388075dc2" -dependencies = [ - "arrayvec 0.7.4", - "bit-vec", - "bitflags 2.4.0", - "codespan-reporting", - "log", - "naga", - "parking_lot 0.12.1", - "profiling", - "raw-window-handle", - "rustc-hash", - "smallvec", - "thiserror", - "web-sys", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6654a13885a17f475e8324efb46dc6986d7aaaa98353330f8de2077b153d0101" -dependencies = [ - "android_system_properties", - "arrayvec 0.7.4", - "ash", - "bit-set", - "bitflags 2.4.0", - "block", - "core-graphics-types 0.1.2", - "d3d12", - "glow", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading 0.8.0", - "log", - "metal 0.26.0", - "naga", - "objc", - "parking_lot 0.12.1", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "rustc-hash", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi 0.3.9", -] - -[[package]] -name = "wgpu-types" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee64d7398d0c2f9ca48922c902ef69c42d000c759f3db41e355f4a570b052b67" -dependencies = [ - "bitflags 2.4.0", - "js-sys", - "web-sys", -] - [[package]] name = "which" version = "4.4.0" @@ -9836,12 +9517,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "widestring" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" - [[package]] name = "wiggle" version = "0.38.3" @@ -9927,15 +9602,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows" version = "0.46.0" diff --git a/crates/gpui3/Cargo.toml b/crates/gpui3/Cargo.toml index bc52090c83..38eba26bb8 100644 --- a/crates/gpui3/Cargo.toml +++ b/crates/gpui3/Cargo.toml @@ -57,8 +57,6 @@ waker-fn = "1.1.0" slotmap = "1.0.6" bytemuck = "1.14.0" schemars.workspace = true -raw-window-handle = "0.5.2" -wgpu = "0.17.0" plane-split = "0.18.0" [dev-dependencies] @@ -71,6 +69,7 @@ simplelog = "0.9" [build-dependencies] bindgen = "0.65.1" +cbindgen = "0.26.0" [target.'cfg(target_os = "macos")'.dependencies] media = { path = "../media" } @@ -83,4 +82,5 @@ core-text = "19.2" font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "b2f77d56f450338aa4f7dd2f0197d8c9acb0cf18" } foreign-types = "0.3" log.workspace = true +metal = "0.21.0" objc = "0.2" diff --git a/crates/gpui3/build.rs b/crates/gpui3/build.rs index 0aa3ab251e..1dbff6f051 100644 --- a/crates/gpui3/build.rs +++ b/crates/gpui3/build.rs @@ -1,7 +1,13 @@ -use std::{env, path::PathBuf}; +use std::{ + env, + path::{Path, PathBuf}, + process::{self, Command}, +}; fn main() { generate_dispatch_bindings(); + let header_path = generate_shader_bindings(); + compile_metal_shaders(&header_path); } fn generate_dispatch_bindings() { @@ -22,3 +28,78 @@ fn generate_dispatch_bindings() { .write_to_file(out_path.join("dispatch_sys.rs")) .expect("couldn't write dispatch bindings"); } + +fn generate_shader_bindings() -> PathBuf { + let output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("scene.h"); + let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + cbindgen::Builder::new() + .with_language(cbindgen::Language::C) + .with_include_guard("SCENE_H") + .with_src(crate_dir.join("src/scene.rs")) + .with_src(crate_dir.join("src/geometry.rs")) + .with_src(crate_dir.join("src/color.rs")) + .with_no_includes() + .include_item("Quad") + .include_item("Bounds") + .include_item("Corners") + .include_item("Edges") + .include_item("Size") + .include_item("Pixels") + .include_item("Point") + .include_item("Hsla") + .generate() + .expect("Unable to generate bindings") + .write_to_file(&output_path); + output_path +} + +fn compile_metal_shaders(header_path: &Path) { + let shader_path = "./src/platform/mac/shaders.metal"; + let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air"); + let metallib_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.metallib"); + + println!("cargo:rerun-if-changed={}", header_path.display()); + println!("cargo:rerun-if-changed={}", shader_path); + + let output = Command::new("xcrun") + .args([ + "-sdk", + "macosx", + "metal", + "-gline-tables-only", + "-mmacosx-version-min=10.15.7", + "-MO", + "-c", + shader_path, + "-include", + &header_path.to_str().unwrap(), + "-o", + ]) + .arg(&air_output_path) + .output() + .unwrap(); + + if !output.status.success() { + eprintln!( + "metal shader compilation failed:\n{}", + String::from_utf8_lossy(&output.stderr) + ); + process::exit(1); + } + + let output = Command::new("xcrun") + .args(["-sdk", "macosx", "metallib"]) + .arg(air_output_path) + .arg("-o") + .arg(metallib_output_path) + .output() + .unwrap(); + + if !output.status.success() { + eprintln!( + "metallib compilation failed:\n{}", + String::from_utf8_lossy(&output.stderr) + ); + process::exit(1); + } +} diff --git a/crates/gpui3/src/geometry.rs b/crates/gpui3/src/geometry.rs index 2eb9114674..ae2b3aff15 100644 --- a/crates/gpui3/src/geometry.rs +++ b/crates/gpui3/src/geometry.rs @@ -77,6 +77,7 @@ unsafe impl Pod for Point {} #[derive(Refineable, Default, Clone, Copy, Debug, PartialEq)] #[refineable(debug)] +#[repr(C)] pub struct Size { pub width: T, pub height: T, @@ -133,6 +134,7 @@ impl Size { #[derive(Refineable, Clone, Default, Debug, PartialEq)] #[refineable(debug)] +#[repr(C)] pub struct Bounds { pub origin: Point, pub size: Size, @@ -170,6 +172,7 @@ impl Copy for Bounds {} #[derive(Refineable, Clone, Default, Debug)] #[refineable(debug)] +#[repr(C)] pub struct Edges { pub top: T, pub right: T, @@ -242,6 +245,7 @@ impl Edges { #[derive(Refineable, Clone, Default, Debug)] #[refineable(debug)] +#[repr(C)] pub struct Corners { pub top_left: T, pub top_right: T, diff --git a/crates/gpui3/src/gpui3.rs b/crates/gpui3/src/gpui3.rs index f8f6cab941..f95187c2d9 100644 --- a/crates/gpui3/src/gpui3.rs +++ b/crates/gpui3/src/gpui3.rs @@ -5,7 +5,6 @@ mod elements; mod executor; mod geometry; mod platform; -mod renderer; mod scene; mod style; mod style_helpers; @@ -26,7 +25,6 @@ pub use geometry::*; pub use gpui3_macros::*; pub use platform::*; pub use refineable::*; -use renderer::*; pub use scene::*; pub use serde; pub use serde_json; diff --git a/crates/gpui3/src/platform.rs b/crates/gpui3/src/platform.rs index 0b1020e199..9c6e087323 100644 --- a/crates/gpui3/src/platform.rs +++ b/crates/gpui3/src/platform.rs @@ -7,14 +7,11 @@ mod test; use crate::{ AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, GlyphId, - LineLayout, Pixels, Point, RenderTarget, Result, RunStyle, SharedString, Size, + LineLayout, Pixels, Point, Result, RunStyle, SharedString, Size, }; use anyhow::anyhow; use async_task::Runnable; use futures::channel::oneshot; -use raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, -}; use seahash::SeaHasher; use serde::{Deserialize, Serialize}; use std::ffi::c_void; @@ -117,9 +114,6 @@ impl Debug for PlatformScreenHandle { unsafe impl Send for PlatformScreenHandle {} pub trait PlatformWindow { - fn raw_window_handle(&self) -> RawWindowHandle; - fn raw_display_handle(&self) -> RawDisplayHandle; - fn bounds(&self) -> WindowBounds; fn content_size(&self) -> Size; fn scale_factor(&self) -> f32; @@ -153,25 +147,6 @@ pub trait PlatformWindow { fn is_topmost_for_position(&self, position: Point) -> bool; } -unsafe impl<'a> HasRawWindowHandle for &'a dyn PlatformWindow { - fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle { - (*self).raw_window_handle() - } -} - -unsafe impl<'a> HasRawDisplayHandle for &'a dyn PlatformWindow { - fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { - (*self).raw_display_handle() - } -} - -impl<'a> RenderTarget for &'a dyn PlatformWindow { - fn content_device_size(&self) -> Size { - self.content_size() - .map(|d| d.to_device_pixels(self.scale_factor())) - } -} - pub trait PlatformDispatcher: Send + Sync { fn is_main_thread(&self) -> bool; fn run_on_main_thread(&self, task: Runnable); diff --git a/crates/gpui3/src/platform/mac.rs b/crates/gpui3/src/platform/mac.rs index e44cf1a03b..40d9db3c28 100644 --- a/crates/gpui3/src/platform/mac.rs +++ b/crates/gpui3/src/platform/mac.rs @@ -2,6 +2,7 @@ ///! an origin at the bottom left of the main display. mod dispatcher; mod events; +mod metal_renderer; mod open_type; mod platform; mod screen; diff --git a/crates/gpui3/src/platform/mac/metal_renderer.rs b/crates/gpui3/src/platform/mac/metal_renderer.rs new file mode 100644 index 0000000000..3a23281fe9 --- /dev/null +++ b/crates/gpui3/src/platform/mac/metal_renderer.rs @@ -0,0 +1,153 @@ +// use cocoa::{ +// base::{NO, YES}, +// foundation::NSUInteger, +// quartzcore::AutoresizingMask, +// }; +// use core_foundation::base::TCFType; +// use foreign_types::ForeignTypeRef; +// use log::warn; +// use media::core_video::{self, CVMetalTextureCache}; +// use metal::{CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange}; +// use objc::{self, msg_send, sel, sel_impl}; +// use shaders::ToFloat2 as _; +// use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, ptr, sync::Arc, vec}; + +// use crate::{Quad, Scene}; + +// const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib")); +// const BUFFER_SIZE: usize = 8192 * 1024; // This is an arbitrary decision. There's probably a more optimal value. + +// pub struct Renderer { +// layer: metal::MetalLayer, +// command_queue: CommandQueue, +// quad_pipeline_state: metal::RenderPipelineState, +// buffer: metal::Buffer, +// } + +// impl Renderer { +// pub fn new(is_opaque: bool, fonts: Arc) -> Self { +// const PIXEL_FORMAT: MTLPixelFormat = MTLPixelFormat::BGRA8Unorm; + +// let device: metal::Device = if let Some(device) = metal::Device::system_default() { +// device +// } else { +// log::error!("unable to access a compatible graphics device"); +// std::process::exit(1); +// }; + +// let layer = metal::MetalLayer::new(); +// layer.set_device(&device); +// layer.set_pixel_format(PIXEL_FORMAT); +// layer.set_presents_with_transaction(true); +// layer.set_opaque(is_opaque); +// unsafe { +// let _: () = msg_send![&*layer, setAllowsNextDrawableTimeout: NO]; +// let _: () = msg_send![&*layer, setNeedsDisplayOnBoundsChange: YES]; +// let _: () = msg_send![ +// &*layer, +// setAutoresizingMask: AutoresizingMask::WIDTH_SIZABLE +// | AutoresizingMask::HEIGHT_SIZABLE +// ]; +// } + +// let library = device +// .new_library_with_data(SHADERS_METALLIB) +// .expect("error building metal library"); + +// let buffer = device.new_buffer(BUFFER_SIZE as u64, MTLResourceOptions::StorageModeManaged); + +// let quad_pipeline_state = build_pipeline_state( +// &device, +// &library, +// "quad", +// "quad_vertex", +// "quad_fragment", +// PIXEL_FORMAT, +// ); + +// Self { +// layer, +// command_queue: device.new_command_queue(), +// quad_pipeline_state, +// buffer, +// } +// } + +// pub fn draw(&mut self, scene: &Scene) { +// draw_quads(scene); +// } + +// fn draw_quads( +// &mut self, +// quads: &[Quad], +// scale_factor: f32, +// offset: &mut usize, +// drawable_size: Vector2F, +// command_encoder: &metal::RenderCommandEncoderRef, +// ) { +// if quads.is_empty() { +// return; +// } +// align_offset(offset); +// let next_offset = *offset + quads.len() * mem::size_of::(); +// assert!( +// next_offset <= INSTANCE_BUFFER_SIZE, +// "instance buffer exhausted" +// ); + +// command_encoder.set_render_pipeline_state(&self.quad_pipeline_state); +// command_encoder.set_vertex_buffer( +// shaders::GPUIQuadInputIndex_GPUIQuadInputIndexVertices as u64, +// Some(&self.unit_vertices), +// 0, +// ); +// command_encoder.set_vertex_buffer( +// shaders::GPUIQuadInputIndex_GPUIQuadInputIndexQuads as u64, +// Some(&self.instances), +// *offset as u64, +// ); +// command_encoder.set_vertex_bytes( +// shaders::GPUIQuadInputIndex_GPUIQuadInputIndexUniforms as u64, +// mem::size_of::() as u64, +// [shaders::GPUIUniforms { +// viewport_size: drawable_size.to_float2(), +// }] +// .as_ptr() as *const c_void, +// ); + +// let buffer_contents = unsafe { +// (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIQuad +// }; +// for (ix, quad) in quads.iter().enumerate() { +// let bounds = quad.bounds * scale_factor; +// let shader_quad = shaders::GPUIQuad { +// origin: bounds.origin().round().to_float2(), +// size: bounds.size().round().to_float2(), +// background_color: quad +// .background +// .unwrap_or_else(Color::transparent_black) +// .to_uchar4(), +// border_top: quad.border.top * scale_factor, +// border_right: quad.border.right * scale_factor, +// border_bottom: quad.border.bottom * scale_factor, +// border_left: quad.border.left * scale_factor, +// border_color: quad.border.color.to_uchar4(), +// corner_radius_top_left: quad.corner_radii.top_left * scale_factor, +// corner_radius_top_right: quad.corner_radii.top_right * scale_factor, +// corner_radius_bottom_right: quad.corner_radii.bottom_right * scale_factor, +// corner_radius_bottom_left: quad.corner_radii.bottom_left * scale_factor, +// }; +// unsafe { +// *(buffer_contents.add(ix)) = shader_quad; +// } +// } + +// command_encoder.draw_primitives_instanced( +// metal::MTLPrimitiveType::Triangle, +// 0, +// 6, +// quads.len() as u64, +// ); +// *offset = next_offset; +// } +// } diff --git a/crates/gpui3/src/shader.frag.wgsl b/crates/gpui3/src/platform/mac/shaders.metal similarity index 100% rename from crates/gpui3/src/shader.frag.wgsl rename to crates/gpui3/src/platform/mac/shaders.metal diff --git a/crates/gpui3/src/platform/mac/window.rs b/crates/gpui3/src/platform/mac/window.rs index 6c8ac56045..092cb839e5 100644 --- a/crates/gpui3/src/platform/mac/window.rs +++ b/crates/gpui3/src/platform/mac/window.rs @@ -1,9 +1,9 @@ use crate::{ - point, px, size, AnyWindowHandle, Bounds, DevicePixels, Event, InputHandler, KeyDownEvent, - Keystroke, MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, - MouseMovedEvent, MouseUpEvent, NSRectExt, Pixels, Platform, PlatformDispatcher, PlatformScreen, - PlatformWindow, Point, RenderTarget, Size, Timer, WindowAppearance, WindowBounds, WindowKind, - WindowOptions, WindowPromptLevel, + point, px, size, AnyWindowHandle, Bounds, Event, InputHandler, KeyDownEvent, Keystroke, + MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, + MouseUpEvent, NSRectExt, Pixels, Platform, PlatformDispatcher, PlatformScreen, PlatformWindow, + Point, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions, + WindowPromptLevel, }; use block::ConcreteBlock; use cocoa::{ @@ -26,10 +26,6 @@ use objc::{ sel, sel_impl, }; use parking_lot::Mutex; -use raw_window_handle::{ - AppKitDisplayHandle, AppKitWindowHandle, HasRawDisplayHandle, HasRawWindowHandle, - RawDisplayHandle, RawWindowHandle, -}; use std::{ any::Any, cell::{Cell, RefCell}, @@ -626,19 +622,6 @@ impl Drop for MacWindow { } impl PlatformWindow for MacWindow { - fn raw_window_handle(&self) -> RawWindowHandle { - let ns_window = self.0.lock().native_window; - let ns_view = unsafe { ns_window.contentView() }; - let mut handle = AppKitWindowHandle::empty(); - handle.ns_window = ns_window as *mut c_void; - handle.ns_view = ns_view as *mut c_void; - handle.into() - } - - fn raw_display_handle(&self) -> RawDisplayHandle { - AppKitDisplayHandle::empty().into() - } - fn bounds(&self) -> WindowBounds { self.0.as_ref().lock().bounds() } diff --git a/crates/gpui3/src/renderer.rs b/crates/gpui3/src/renderer.rs deleted file mode 100644 index 5fae274241..0000000000 --- a/crates/gpui3/src/renderer.rs +++ /dev/null @@ -1,180 +0,0 @@ -use crate::{DevicePixels, Scene, Size}; -use futures::{future::BoxFuture, FutureExt}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; -use wgpu::Backends; - -pub struct Renderer { - device: wgpu::Device, - queue: wgpu::Queue, - surface: wgpu::Surface, - surface_config: wgpu::SurfaceConfiguration, - quad_pipeline: wgpu::RenderPipeline, - vertex_buffer: wgpu::Buffer, - vertex_count: u32, - uniforms_buffer: wgpu::Buffer, -} - -pub(crate) trait RenderTarget: HasRawWindowHandle + HasRawDisplayHandle { - fn content_device_size(&self) -> Size; -} - -impl Renderer { - pub(crate) fn new<'a, W>(window: &'a W) -> BoxFuture<'static, Self> - where - W: RenderTarget, - { - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: Backends::METAL, - ..Default::default() - }); - let surface = unsafe { instance.create_surface(window).unwrap() }; - let width = window.content_device_size().width; - let height = window.content_device_size().height; - - async move { - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions::default()) - .await - .unwrap(); - - let (device, queue) = adapter - .request_device(&wgpu::DeviceDescriptor::default(), None) - .await - .unwrap(); - - let surface_config = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: wgpu::TextureFormat::Bgra8UnormSrgb, - width: width.into(), - height: height.into(), - - // "FIFO" mode renders frames in queue synced with the display's refresh rate. - // Avoids screen tearing but may not offer the lowest latency. Ideal when image - // quality takes priority over input latency. - present_mode: wgpu::PresentMode::Fifo, - - // When blending, assume the RGB have not yet been multiplied by the alpha channel. - alpha_mode: wgpu::CompositeAlphaMode::PostMultiplied, -PostMultiplied - // Specify the color formats for the views the surface can have. - // In this case, the format is BGRA (blue, green, red, alpha) with unsigned - // normalised integers in the 8-bit range and the color space is sRGB (standard RGB). - // sRGB is the standard color space for displaying images and video on digital displays, - // as it optimises color accuracy and consistency. - view_formats: vec![wgpu::TextureFormat::Bgra8UnormSrgb], - }; - - surface.configure(&device, &surface_config); - - let vs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Vertex Shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shader.vert.wgsl").into()), - }); - - let fs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Fragment Shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shader.frag.wgsl").into()), - }); - - let uniforms_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Uniforms Buffer"), - size: std::mem::size_of::() as wgpu::BufferAddress, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - bind_group_layouts: &[], - push_constant_ranges: &[], - }); - - let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Vertex Buffer"), - size: 0, - usage: wgpu::BufferUsages::VERTEX, - mapped_at_creation: false, - }); - - let quad_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &vs_module, - entry_point: "quad", - buffers: &[], - }, - fragment: Some(wgpu::FragmentState { - module: &fs_module, - entry_point: "quad", - targets: &[Some(wgpu::ColorTargetState { - format: surface_config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleStrip, - ..Default::default() - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview: None, - }); - - Self { - device, - queue, - surface, - surface_config, - quad_pipeline, - vertex_buffer, - vertex_count: 0, - uniforms_buffer, - } - } - .boxed() - } - - pub fn render(&mut self, scene: &Scene) { - let frame = self.surface.get_current_texture().unwrap(); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - - self.queue.write_buffer( - &self.vertex_buffer, - 0, - bytemuck::cast_slice(&scene.opaque_primitives().quads), - ); - self.vertex_count = scene.opaque_primitives().quads.len() as u32; - - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); - - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: true, - }, - })], - depth_stencil_attachment: None, - }); - - render_pass.set_pipeline(&self.quad_pipeline); - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.set_bind_group(0, &self.uniforms_buffer, &[]); - render_pass.draw(0..self.vertex_count, 0..1); - } - - self.queue.submit(std::iter::once(encoder.finish())); - } -} diff --git a/crates/gpui3/src/scene.rs b/crates/gpui3/src/scene.rs index c26f98851b..b08b17c744 100644 --- a/crates/gpui3/src/scene.rs +++ b/crates/gpui3/src/scene.rs @@ -102,6 +102,16 @@ impl From for Primitive { } } +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub(crate) struct QuadUniforms { + viewport_size: [f32; 2], +} + +unsafe impl Zeroable for QuadUniforms {} + +unsafe impl Pod for QuadUniforms {} + #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct RenderedGlyph { diff --git a/crates/gpui3/src/shader.vert.wgsl b/crates/gpui3/src/shader.vert.wgsl deleted file mode 100644 index 094edbe81e..0000000000 --- a/crates/gpui3/src/shader.vert.wgsl +++ /dev/null @@ -1,88 +0,0 @@ -[[stage(vertex)]] -fn quad_vertex(input: QuadVertexInput) -> QuadVertexOutput { - var output: QuadVertexOutput; - - // Apply clip bounds - input.bounds_origin = max(input.bounds_origin, input.clip_bounds.xy); - input.bounds_size = min(input.bounds_size, input.clip_bounds.zw); - - var ndc: vec2 = (input.bounds_origin / uniforms.window_size) * 2.0 - 1.0; - - output.position = vec4(ndc, 0.0, 1.0); - output.position.y = -output.position.y; // Inverting since NDC's origin is at the center and y is up - output.color = input.color; - output.bounds = input.bounds_size / uniforms.window_size; // Convert size to NDC - output.corner_radii = input.corner_radii / uniforms.window_size; // Convert corner radii to NDC - output.clip_bounds = input.clip_bounds / uniforms.window_size; // Convert clip bounds to NDC - output.clip_corner_radii = input.corner_radii / uniforms.window_size; // Convert clip corner radii to NDC - - return output; -} - -// #[derive(Debug, Clone, Copy)] -// #[repr(C)] -// pub struct gpui3::scene::Quad { -// pub order: f32, -// pub bounds: Bounds, -// pub clip_bounds: Bounds, -// pub clip_corner_radii: Corners, -// pub background: Hsla, -// pub border_color: Hsla, -// pub corner_radii: Corners, -// pub border_widths: Edges, -// } - -struct QuadVertexInput { - [[location(0)]] order: f32; - [[location(1)]] bounds: vec4; // Bounds - [[location(2)]] clip_bounds: vec4; // Bounds - [[location(3)]] clip_corner_radii: vec4; // Corners - [[location(4)]] color: vec4; // Hsla - [[location(5)]] border_color: vec4; // Hsla - [[location(6)]] corner_radii: vec4; // Corners - [[location(7)]] border_widths: vec4; // Edges -}; - -[[block]] -struct Uniforms { - viewport: vec2; -}; - -[[binding(0), group(0)]] var uniforms: Uniforms; - -struct QuadVertexOutput { - [[builtin(position)]] position: vec4; - [[location(0)]] color: vec4; - [[location(1)]] border_color: vec4; - [[location(2)]] bounds: vec4; - [[location(3)]] corner_radii: vec4; // assuming topLeft, topRight, bottomRight, bottomLeft - [[location(4)]] clip_bounds: vec4; - [[location(5)]] clip_corner_radii: vec4; - [[location(6)]] border_widths: vec4; -}; - -[[stage(fragment)]] -fn quad_fragment(input: QuadVertexOutput) -> [[location(0)]] vec4 { - var output_color: vec4; - var sdf = rounded_quad_sdf(input.position, input.bounds, input.corner_radii); - var alpha = clamp(1.0 - sdf, 0.0, 1.0); - var border_color: vec4 = input.border_color; - var mix_factor: f32 = 1.0 - clamp(sdf, 0.0, 1.0); // Mixing factor dependent on sdf distance - - var border_width_factor: vec4 = normalize(input.border_widths); // Normalizing the border width to account for directional widths - - output_color = mix(input.color, border_color, mix_factor * border_width_factor); // Modulate the mix_factor with the border_width_factor to handle different border widths - - output_color.a = alpha; - - return output_color; -} - -[[stage(fragment)]] -fn rounded_quad_sdf(p: vec2, b: vec2, r: vec4) -> f32 { - var rx: vec2; - rx = select(r.xy, r.zw, greaterThan(p.x, 0.0)); - rx.x = select(rx.x, rx.y, greaterThan(p.y, 0.0)); - var q: vec2 = abs(p)-b+rx.x; - return min(max(q.x,q.y),0.0) + length(max(q, vec2(0.0, 0.0))) - rx.x; -} diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index 18bc650cd6..35b9555e78 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -1,7 +1,7 @@ use crate::{ - px, renderer::Renderer, taffy::LayoutId, AppContext, AvailableSpace, Bounds, Context, EntityId, - Handle, MainThreadOnly, Pixels, Platform, PlatformWindow, Point, Reference, Size, Style, - TaffyLayoutEngine, TextStyle, TextStyleRefinement, WindowOptions, + px, AppContext, AvailableSpace, Bounds, Context, EntityId, Handle, LayoutId, MainThreadOnly, + Pixels, Platform, PlatformWindow, Point, Reference, Size, Style, TaffyLayoutEngine, TextStyle, + TextStyleRefinement, WindowOptions, }; use anyhow::Result; use derive_more::{Deref, DerefMut}; @@ -18,7 +18,6 @@ pub struct AnyWindow {} pub struct Window { handle: AnyWindowHandle, platform_window: MainThreadOnly>, - renderer: Renderer, rem_size: Pixels, layout_engine: TaffyLayoutEngine, text_style_stack: Vec, @@ -33,16 +32,13 @@ impl Window { platform: &dyn Platform, ) -> impl Future + 'static { let platform_window = platform.open_window(handle, options); - let renderer = Renderer::new(&platform_window.as_ref()); let mouse_position = platform_window.mouse_position(); let platform_window = MainThreadOnly::new(Arc::new(platform_window), platform.dispatcher()); async move { - let renderer = renderer.await; Window { handle, platform_window, - renderer, rem_size: px(16.), layout_engine: TaffyLayoutEngine::new(), text_style_stack: Vec::new(),