Checkpoint

Nathan Sobo created

Change summary

Cargo.lock                                  | 402 ++++++++++++++++++++++
crates/storybook/Cargo.toml                 |   4 
crates/storybook/src/gpui3/color.rs         |  12 
crates/storybook/src/gpui3/geometry.rs      |  20 +
crates/storybook/src/gpui3/mod.rs           |   3 
crates/storybook/src/gpui3/ordered.rs       |  24 -
crates/storybook/src/gpui3/renderer.rs      | 164 +++++++++
crates/storybook/src/gpui3/scene.rs         | 120 +++++-
crates/storybook/src/gpui3/shader.frag.wgsl |   1 
crates/storybook/src/gpui3/shader.vert.wgsl |   0 
10 files changed, 679 insertions(+), 71 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -312,6 +312,15 @@ 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"
@@ -1036,9 +1045,9 @@ dependencies = [
 
 [[package]]
 name = "bytemuck"
-version = "1.13.1"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
 
 [[package]]
 name = "byteorder"
@@ -1432,7 +1441,7 @@ dependencies = [
  "cocoa-foundation",
  "core-foundation",
  "core-graphics",
- "foreign-types",
+ "foreign-types 0.3.2",
  "libc",
  "objc",
 ]
@@ -1445,12 +1454,22 @@ dependencies = [
  "bitflags 1.3.2",
  "block",
  "core-foundation",
- "core-graphics-types",
- "foreign-types",
+ "core-graphics-types 0.1.1",
+ "foreign-types 0.3.2",
  "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"
@@ -1578,6 +1597,12 @@ 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"
@@ -1735,8 +1760,8 @@ source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2f
 dependencies = [
  "bitflags 1.3.2",
  "core-foundation",
- "core-graphics-types",
- "foreign-types",
+ "core-graphics-types 0.1.1",
+ "foreign-types 0.3.2",
  "libc",
 ]
 
@@ -1747,7 +1772,18 @@ source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2f
 dependencies = [
  "bitflags 1.3.2",
  "core-foundation",
- "foreign-types",
+ "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",
  "libc",
 ]
 
@@ -1768,7 +1804,7 @@ checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
 dependencies = [
  "core-foundation",
  "core-graphics",
- "foreign-types",
+ "foreign-types 0.3.2",
  "libc",
 ]
 
@@ -2068,6 +2104,17 @@ 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"
@@ -2705,7 +2752,28 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 dependencies = [
- "foreign-types-shared",
+ "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",
 ]
 
 [[package]]
@@ -2714,6 +2782,12 @@ 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"
@@ -3095,6 +3169,18 @@ 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"
@@ -3110,6 +3196,58 @@ 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"
@@ -3131,7 +3269,7 @@ dependencies = [
  "env_logger 0.9.3",
  "etagere",
  "font-kit",
- "foreign-types",
+ "foreign-types 0.3.2",
  "futures 0.3.28",
  "gpui_macros",
  "image",
@@ -3139,7 +3277,7 @@ dependencies = [
  "lazy_static",
  "log",
  "media",
- "metal",
+ "metal 0.21.0",
  "num_cpus",
  "objc",
  "ordered-float",
@@ -3292,6 +3430,21 @@ 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"
@@ -3365,6 +3518,12 @@ 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"
@@ -3877,6 +4036,17 @@ 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"
@@ -4134,7 +4304,7 @@ dependencies = [
  "collections",
  "core-foundation",
  "core-graphics",
- "foreign-types",
+ "foreign-types 0.3.2",
  "futures 0.3.28",
  "gpui",
  "hmac 0.12.1",
@@ -4309,8 +4479,8 @@ dependencies = [
  "block",
  "bytes 1.4.0",
  "core-foundation",
- "foreign-types",
- "metal",
+ "foreign-types 0.3.2",
+ "metal 0.21.0",
  "objc",
 ]
 
@@ -4372,11 +4542,26 @@ dependencies = [
  "bitflags 1.3.2",
  "block",
  "cocoa-foundation",
- "foreign-types",
+ "foreign-types 0.3.2",
  "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"
@@ -4526,6 +4711,26 @@ 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"
@@ -4930,7 +5135,7 @@ checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e"
 dependencies = [
  "bitflags 1.3.2",
  "cfg-if 1.0.0",
- "foreign-types",
+ "foreign-types 0.3.2",
  "libc",
  "once_cell",
  "openssl-macros",
@@ -5271,6 +5476,17 @@ version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 
+[[package]]
+name = "plane-split"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c1f7d82649829ecdef8e258790b0587acf0a8403f0ce963473d8e918acc1643"
+dependencies = [
+ "euclid",
+ "log",
+ "smallvec",
+]
+
 [[package]]
 name = "plist"
 version = "1.5.0"
@@ -5463,6 +5679,12 @@ 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"
@@ -5850,6 +6072,12 @@ 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"
@@ -6045,6 +6273,12 @@ 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"
@@ -7222,6 +7456,16 @@ 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"
@@ -7385,10 +7629,13 @@ name = "storybook"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "bytemuck",
  "derive_more",
  "gpui2",
  "itertools 0.11.0",
  "log",
+ "plane-split",
+ "raw-window-handle",
  "refineable",
  "rust-embed",
  "serde",
@@ -7397,6 +7644,7 @@ dependencies = [
  "slotmap",
  "theme",
  "util",
+ "wgpu",
 ]
 
 [[package]]
@@ -8680,6 +8928,12 @@ 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"
@@ -9388,6 +9642,105 @@ 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"
@@ -9409,6 +9762,12 @@ 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"
@@ -9494,6 +9853,15 @@ 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"

crates/storybook/Cargo.toml 🔗

@@ -10,10 +10,13 @@ path = "src/storybook.rs"
 
 [dependencies]
 anyhow.workspace = true
+bytemuck = "1.14.0"
 derive_more.workspace = true
 gpui2 = { path = "../gpui2" }
 itertools = "0.11.0"
 log.workspace = true
+plane-split = "0.18.0"
+raw-window-handle = "0.5.2"
 refineable = { path = "../refineable" }
 rust-embed.workspace = true
 serde.workspace = true
@@ -22,6 +25,7 @@ simplelog = "0.9"
 slotmap = "1.0.6"
 theme = { path = "../theme" }
 util = { path = "../util" }
+wgpu = "0.17.0"
 
 [dev-dependencies]
 gpui2 = { path = "../gpui2", features = ["test-support"] }

crates/storybook/src/gpui3/color.rs 🔗

@@ -1,5 +1,6 @@
 #![allow(dead_code)]
 
+use bytemuck::{Pod, Zeroable};
 use serde::de::{self, Deserialize, Deserializer, Visitor};
 use std::fmt;
 use std::num::ParseIntError;
@@ -101,6 +102,7 @@ impl TryFrom<&'_ str> for Rgba {
 }
 
 #[derive(Default, Copy, Clone, Debug, PartialEq)]
+#[repr(C)]
 pub struct Hsla {
     pub h: f32,
     pub s: f32,
@@ -108,6 +110,9 @@ pub struct Hsla {
     pub a: f32,
 }
 
+unsafe impl Zeroable for Hsla {}
+unsafe impl Pod for Hsla {}
+
 pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
     Hsla {
         h: h.clamp(0., 1.),
@@ -126,6 +131,13 @@ pub fn black() -> Hsla {
     }
 }
 
+impl Hsla {
+    /// Returns true if the HSLA color is fully transparent, false otherwise.
+    pub fn is_transparent(&self) -> bool {
+        self.a == 0.0
+    }
+}
+
 impl From<Rgba> for Hsla {
     fn from(color: Rgba) -> Self {
         let r = color.r;

crates/storybook/src/gpui3/geometry.rs 🔗

@@ -1,3 +1,4 @@
+use bytemuck::{Pod, Zeroable};
 use core::fmt::Debug;
 use derive_more::{Add, AddAssign, Div, Mul, Sub};
 use refineable::Refineable;
@@ -5,11 +6,18 @@ use std::ops::Mul;
 
 #[derive(Refineable, Default, Add, AddAssign, Sub, Mul, Div, Copy, Debug, PartialEq, Eq, Hash)]
 #[refineable(debug)]
+#[repr(C)]
 pub struct Point<T: Clone + Debug> {
     pub x: T,
     pub y: T,
 }
 
+impl<T: Clone + Debug> Point<T> {
+    pub fn new(x: T, y: T) -> Self {
+        Self { x, y }
+    }
+}
+
 impl<T: Clone + Debug> Clone for Point<T> {
     fn clone(&self) -> Self {
         Self {
@@ -19,7 +27,11 @@ impl<T: Clone + Debug> Clone for Point<T> {
     }
 }
 
-#[derive(Refineable, Default, Clone, Debug)]
+unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Point<T> {}
+
+unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Point<T> {}
+
+#[derive(Refineable, Default, Clone, Copy, Debug)]
 #[refineable(debug)]
 pub struct Size<T: Clone + Debug> {
     pub width: T,
@@ -60,6 +72,8 @@ pub struct Bounds<T: Clone + Debug> {
     pub size: Size<T>,
 }
 
+impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
+
 #[derive(Refineable, Clone, Default, Debug)]
 #[refineable(debug)]
 pub struct Edges<T: Clone + Debug> {
@@ -127,8 +141,12 @@ impl Edges<Pixels> {
 }
 
 #[derive(Clone, Copy, Default, Add, AddAssign, Sub, Mul, Div, PartialEq)]
+#[repr(transparent)]
 pub struct Pixels(pub(crate) f32);
 
+unsafe impl bytemuck::Pod for Pixels {}
+unsafe impl bytemuck::Zeroable for Pixels {}
+
 impl Debug for Pixels {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(f, "{} px", self.0)

crates/storybook/src/gpui3/mod.rs 🔗

@@ -3,7 +3,7 @@ mod color;
 mod element;
 mod elements;
 mod geometry;
-mod ordered;
+mod renderer;
 mod scene;
 mod style;
 mod taffy;
@@ -18,7 +18,6 @@ pub use elements::*;
 pub use geometry::*;
 pub use gpui2::ArcCow;
 use gpui2::Reference;
-use ordered::*;
 pub use scene::*;
 pub use style::*;
 pub use taffy::LayoutId;

crates/storybook/src/gpui3/ordered.rs 🔗

@@ -1,24 +0,0 @@
-pub struct Ordered<P> {
-    pub order: u32,
-    pub primitive: P,
-}
-
-impl<P> Ord for Ordered<P> {
-    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
-        self.order.cmp(&other.order)
-    }
-}
-
-impl<P> PartialOrd for Ordered<P> {
-    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl<P> Eq for Ordered<P> {}
-
-impl<P> PartialEq for Ordered<P> {
-    fn eq(&self, other: &Self) -> bool {
-        self.order == other.order
-    }
-}

crates/storybook/src/gpui3/renderer.rs 🔗

@@ -0,0 +1,164 @@
+use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
+
+use super::{Scene, Size};
+
+pub struct Renderer {
+    device: wgpu::Device,
+    queue: wgpu::Queue,
+    surface: wgpu::Surface,
+    surface_config: wgpu::SurfaceConfiguration,
+    pipeline: wgpu::RenderPipeline,
+    vertex_buffer: wgpu::Buffer,
+    vertex_count: u32,
+}
+
+pub trait Window: HasRawWindowHandle + HasRawDisplayHandle {
+    fn inner_size(&self) -> Size<u32>;
+}
+
+impl Renderer {
+    pub async fn new<W>(window: &W) -> Self
+    where
+        W: Window,
+    {
+        let instance = wgpu::Instance::new(Default::default());
+        let surface = unsafe { instance.create_surface(window).unwrap() };
+
+        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: window.inner_size().width,
+            height: window.inner_size().height,
+
+            // "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,
+
+            // Use the Premultiplied alpha mode. With premultiplication, the color components
+            // are multiplied by the alpha value before storage or blending, meaning calculations
+            // with colors already factor in the influence of alpha. This typically results
+            // in better performance and avoids a separate multiplication operation during blending.
+            alpha_mode: wgpu::CompositeAlphaMode::PreMultiplied,
+
+            // 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 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 pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+            label: Some("Render Pipeline"),
+            layout: Some(&pipeline_layout),
+            vertex: wgpu::VertexState {
+                module: &vs_module,
+                entry_point: "main",
+                buffers: &[],
+            },
+            fragment: Some(wgpu::FragmentState {
+                module: &fs_module,
+                entry_point: "main",
+                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,
+            pipeline,
+            vertex_buffer,
+            vertex_count: 0,
+        }
+    }
+
+    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.pipeline);
+            render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
+            render_pass.draw(0..self.vertex_count, 0..1);
+        }
+
+        self.queue.submit(std::iter::once(encoder.finish()));
+    }
+}

crates/storybook/src/gpui3/scene.rs 🔗

@@ -1,45 +1,111 @@
-use super::Ordered;
+use super::{Bounds, Hsla, Pixels, Point};
+use bytemuck::{Pod, Zeroable};
+use plane_split::BspSplitter;
 
-/// A platform neutral representation of all geometry to be drawn for the current frame.
 pub struct Scene {
-    quads: Vec<Ordered<Quad>>,
-    glyphs: Vec<Ordered<Glyph>>,
+    opaque_primitives: PrimitiveBatch,
+    transparent_primitives: slotmap::SlotMap<slotmap::DefaultKey, Primitive>,
+    splitter: BspSplitter<slotmap::DefaultKey>,
 }
 
 impl Scene {
-    pub fn new() -> Self {
+    pub fn new() -> Scene {
         Scene {
-            quads: Vec::new(),
-            glyphs: Vec::new(),
+            opaque_primitives: PrimitiveBatch::default(),
+            transparent_primitives: slotmap::SlotMap::new(),
+            splitter: BspSplitter::new(),
         }
     }
 
-    pub fn add(&mut self, order: u32, primitive: impl Into<Primitive>) {
-        match primitive.into() {
-            Primitive::Quad(primitive) => self.quads.push(Ordered { order, primitive }),
-            Primitive::Glyph(primitive) => self.glyphs.push(Ordered { order, primitive }),
+    pub fn insert(&mut self, primitive: impl Into<Primitive>, is_transparent: bool) {
+        if is_transparent {
+            self.transparent_primitives.insert(primitive.into());
+        } else {
+            match primitive.into() {
+                Primitive::Quad(quad) => self.opaque_primitives.quads.push(quad),
+                Primitive::Glyph(glyph) => self.opaque_primitives.glyphs.push(glyph),
+            }
         }
     }
 
-    pub fn draw(&mut self) {
-        self.quads.sort_unstable();
-        self.glyphs.sort_unstable();
+    pub fn opaque_primitives(&self) -> &PrimitiveBatch {
+        &self.opaque_primitives
     }
 }
 
+#[derive(Clone, Debug)]
 pub enum Primitive {
     Quad(Quad),
     Glyph(Glyph),
-    // Icon(Icon),
-    // Image(Image),
-    // Shadow(Shadow),
-    // Curve(Curve),
-}
-
-#[derive(Eq, Ord, PartialEq, PartialOrd)]
-pub struct Quad {}
-pub struct Glyph {}
-// pub struct Icon {}
-// pub struct Image {}
-// pub struct Shadow {}
-// pub struct Curve {}
+}
+
+impl Primitive {
+    pub fn is_transparent(&self) -> bool {
+        match self {
+            Primitive::Quad(quad) => {
+                quad.background.is_transparent() && quad.border_color.is_transparent()
+            }
+            Primitive::Glyph(glyph) => glyph.color.is_transparent(),
+        }
+    }
+}
+
+#[derive(Default)]
+pub struct PrimitiveBatch {
+    pub quads: Vec<Quad>,
+    pub glyphs: Vec<Glyph>,
+}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Quad {
+    pub order: f32,
+    pub bounds: Bounds<Pixels>,
+    pub background: Hsla,
+    pub border_color: Hsla,
+    pub corner_radius: Pixels,
+    pub border_left: Pixels,
+    pub border_right: Pixels,
+    pub border_top: Pixels,
+    pub border_bottom: Pixels,
+}
+
+impl Quad {
+    pub fn vertices(&self) -> impl Iterator<Item = Point<Pixels>> {
+        let x1 = self.bounds.origin.x;
+        let y1 = self.bounds.origin.y;
+        let x2 = x1 + self.bounds.size.width;
+        let y2 = y1 + self.bounds.size.height;
+        [
+            Point::new(x1, y1),
+            Point::new(x2, y1),
+            Point::new(x2, y2),
+            Point::new(x1, y2),
+        ]
+        .into_iter()
+    }
+}
+
+unsafe impl Zeroable for Quad {}
+
+unsafe impl Pod for Quad {}
+
+#[derive(Debug, Clone)]
+pub struct Glyph {
+    pub order: f32,
+    pub bounds: Bounds<Pixels>,
+    pub color: Hsla,
+    // ...
+}
+
+impl From<Quad> for Primitive {
+    fn from(quad: Quad) -> Self {
+        Primitive::Quad(quad)
+    }
+}
+
+impl From<Glyph> for Primitive {
+    fn from(glyph: Glyph) -> Self {
+        Primitive::Glyph(glyph)
+    }
+}