aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-11-25 00:00:46 -0500
committerGitHub <noreply@github.com>2019-11-25 00:00:46 -0500
commitea3249550467bd9f5a1de8271ed4fcaa70a7cdda (patch)
treed7b4e5a7c79c34a953a2c6cc38201645a2759d6a
parentc8791c0dbb0a9bf3cad94744750f9961ae03ade7 (diff)
parent47e39ec1e3f5ee8b6d72212872898b21e2bc7220 (diff)
downloadservo-ea3249550467bd9f5a1de8271ed4fcaa70a7cdda.tar.gz
servo-ea3249550467bd9f5a1de8271ed4fcaa70a7cdda.zip
Auto merge of #24708 - szeged:webgpu-base, r=gterzian,kvark
Initial implementation of WebGPU API <!-- Please describe your changes on the following line: --> - Added the WebIDL bindings for GPU and GPUadapter interfaces. - Created a background thread for WebGPU api calls. - Established the async communication between the background thread and the WebGPU interfaces. - Implemented the `requesAdapter` function of `navigator.gpu` `./mach test-tidy` reports an error due to the different `arrayvec` version used in `servo` and `webgpu`, so added it to the ignore list in `servo-tidy.toml` --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [ ] `./mach test-tidy` does not report any errors - [ ] These changes addresses a part of #https://github.com/servo/servo/issues/24706 <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> cc @jdm, cc @kvark <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24708) <!-- Reviewable:end -->
-rw-r--r--Cargo.lock323
-rw-r--r--Cargo.toml2
-rw-r--r--components/config/opts.rs6
-rw-r--r--components/config/prefs.rs3
-rw-r--r--components/constellation/Cargo.toml1
-rw-r--r--components/constellation/constellation.rs21
-rw-r--r--components/constellation/pipeline.rs7
-rw-r--r--components/script/Cargo.toml1
-rw-r--r--components/script/dom/bindings/codegen/Bindings.conf5
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/gpu.rs158
-rw-r--r--components/script/dom/gpuadapter.rs63
-rw-r--r--components/script/dom/mod.rs2
-rw-r--r--components/script/dom/navigator.rs8
-rw-r--r--components/script/dom/webidls/GPU.webidl21
-rw-r--r--components/script/dom/webidls/GPUAdapter.webidl14
-rw-r--r--components/script/dom/webidls/Navigator.webidl5
-rw-r--r--components/script/dom/webidls/WorkerNavigator.webidl5
-rw-r--r--components/script/dom/window.rs11
-rw-r--r--components/script/dom/workernavigator.rs8
-rw-r--r--components/script/script_thread.rs6
-rw-r--r--components/script_traits/Cargo.toml1
-rw-r--r--components/script_traits/lib.rs3
-rw-r--r--components/servo/Cargo.toml1
-rw-r--r--components/servo/lib.rs4
-rw-r--r--components/webgpu/Cargo.toml20
-rw-r--r--components/webgpu/lib.rs153
-rw-r--r--docs/ORGANIZATION.md2
-rw-r--r--python/tidy/servo_tidy/tidy.py1
-rw-r--r--resources/prefs.json1
-rw-r--r--servo-tidy.toml1
31 files changed, 853 insertions, 7 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0947f0385e9..c216acf7031 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -126,12 +126,33 @@ dependencies = [
]
[[package]]
+name = "arrayvec"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
+
+[[package]]
name = "ascii"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50"
[[package]]
+name = "ash"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "003d1fb2eb12eb06d4a03dbe02eea67a9fac910fa97932ab9e3a75b96a1ea5e5"
+dependencies = [
+ "shared_library",
+]
+
+[[package]]
+name = "atom"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
+
+[[package]]
name = "atomic_refcell"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -672,6 +693,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
[[package]]
+name = "colorful"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bca1619ff57dd7a56b58a8e25ef4199f123e78e503fe1653410350a1b98ae65"
+
+[[package]]
name = "combine"
version = "3.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -754,6 +781,7 @@ dependencies = [
"servo_remutex",
"servo_url",
"style_traits",
+ "webgpu",
"webrender_api",
"webvr_traits",
"webxr-api",
@@ -783,6 +811,12 @@ dependencies = [
]
[[package]]
+name = "copyless"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
+
+[[package]]
name = "core-foundation"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -866,7 +900,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
dependencies = [
- "arrayvec",
+ "arrayvec 0.4.6",
"cfg-if",
"crossbeam-utils",
"lazy_static",
@@ -942,6 +976,17 @@ dependencies = [
]
[[package]]
+name = "d3d12"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7ed48e89905e5e146bcc1951cc3facb9e44aea9adf5dc01078cda1bd24b662"
+dependencies = [
+ "bitflags",
+ "libloading",
+ "winapi",
+]
+
+[[package]]
name = "darling"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1497,6 +1542,12 @@ dependencies = [
]
[[package]]
+name = "gcc"
+version = "0.3.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
+
+[[package]]
name = "generic-array"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1566,6 +1617,123 @@ dependencies = [
]
[[package]]
+name = "gfx-auxil"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "572eee952a9a23c99cfe3e4fd95d277784058a89ac3c77ff6fa3d80a4e321919"
+dependencies = [
+ "fxhash",
+ "gfx-hal",
+ "spirv_cross",
+]
+
+[[package]]
+name = "gfx-backend-dx11"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66c77836ff26cf9916e5c8745715a22eae1fc61d994ffa0bea8a7dbd708ece2"
+dependencies = [
+ "bitflags",
+ "gfx-auxil",
+ "gfx-hal",
+ "libloading",
+ "log",
+ "parking_lot",
+ "range-alloc",
+ "raw-window-handle",
+ "smallvec",
+ "spirv_cross",
+ "winapi",
+ "wio",
+]
+
+[[package]]
+name = "gfx-backend-dx12"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6e913cc800fb12eaba2c420091a02aca9aafbefd672600dfc5b52654343d341"
+dependencies = [
+ "bitflags",
+ "d3d12",
+ "gfx-auxil",
+ "gfx-hal",
+ "log",
+ "range-alloc",
+ "raw-window-handle",
+ "smallvec",
+ "spirv_cross",
+ "winapi",
+]
+
+[[package]]
+name = "gfx-backend-empty"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d383e6bc48867cb37d298a20139fd1eec298f8f6d594690cd1c50ef25470cc7"
+dependencies = [
+ "gfx-hal",
+ "raw-window-handle",
+]
+
+[[package]]
+name = "gfx-backend-metal"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de5c71f18ba805c95b84d6c78c472ef44485a6fc46e3b49fe1e6739c8d7b0c0"
+dependencies = [
+ "arrayvec 0.5.1",
+ "bitflags",
+ "block",
+ "cocoa 0.19.1",
+ "copyless",
+ "core-graphics",
+ "foreign-types",
+ "gfx-auxil",
+ "gfx-hal",
+ "lazy_static",
+ "log",
+ "metal",
+ "objc",
+ "parking_lot",
+ "range-alloc",
+ "raw-window-handle",
+ "smallvec",
+ "spirv_cross",
+ "storage-map",
+]
+
+[[package]]
+name = "gfx-backend-vulkan"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62538fedd66a78968a162e8e1a29d085ffbc97f8782634684b2f7da7aea59207"
+dependencies = [
+ "arrayvec 0.5.1",
+ "ash",
+ "byteorder",
+ "core-graphics",
+ "gfx-hal",
+ "lazy_static",
+ "log",
+ "objc",
+ "raw-window-handle",
+ "smallvec",
+ "winapi",
+ "x11",
+]
+
+[[package]]
+name = "gfx-hal"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c88981665c780447bb08eb099e1ded330754a7246719bab927ee4a949c0ba7f"
+dependencies = [
+ "bitflags",
+ "raw-window-handle",
+ "smallvec",
+]
+
+[[package]]
name = "gfx_traits"
version = "0.0.1"
dependencies = [
@@ -2131,6 +2299,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
+name = "hibitset"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e7292fd9f7fe89fa35c98048f2d0a69b79ed243604234d18f6f8a1aa6f408d"
+dependencies = [
+ "atom",
+]
+
+[[package]]
name = "histogram"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2293,7 +2470,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7371aa3c98fad60de2d9b517e2e1ed45593c32b0c77249310fa507749a2a318b"
dependencies = [
- "arrayvec",
+ "arrayvec 0.4.6",
"byteorder",
"num-traits",
]
@@ -2764,6 +2941,7 @@ dependencies = [
"style_traits",
"surfman",
"webdriver_server",
+ "webgpu",
"webrender",
"webrender_api",
"webrender_traits",
@@ -2833,7 +3011,7 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69589b8844c0b3745cc031a35b62bc33b0fb9e5ba7613756d802c52861dcdb4c"
dependencies = [
- "arrayvec",
+ "arrayvec 0.4.6",
"euclid",
"num-traits",
]
@@ -2989,6 +3167,21 @@ dependencies = [
]
[[package]]
+name = "metal"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddf8052f20601c7af6293d3f7bf7b9159aee5974804fe65d871d437f933ec1eb"
+dependencies = [
+ "bitflags",
+ "block",
+ "cocoa 0.19.1",
+ "core-graphics",
+ "foreign-types",
+ "log",
+ "objc",
+]
+
+[[package]]
name = "metrics"
version = "0.0.1"
dependencies = [
@@ -3393,6 +3586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
dependencies = [
"malloc_buf",
+ "objc_exception",
]
[[package]]
@@ -3407,6 +3601,15 @@ dependencies = [
]
[[package]]
+name = "objc_exception"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "098cd29a2fa3c230d3463ae069cecccc3fdfd64c0d2496ab5b96f82dab6a00dc"
+dependencies = [
+ "gcc",
+]
+
+[[package]]
name = "objc_id"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3893,6 +4096,12 @@ dependencies = [
]
[[package]]
+name = "range-alloc"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd5927936723a9e8b715d37d7e4b390455087c4bdf25b9f702309460577b14f9"
+
+[[package]]
name = "raqote"
version = "0.7.4-alpha.0"
source = "git+https://github.com/jrmuizel/raqote#2a801bca7253e053767ef5ea11b0ee77c52617c9"
@@ -3906,6 +4115,15 @@ dependencies = [
]
[[package]]
+name = "raw-window-handle"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9db80d08d3ed847ce4fb3def46de0af4bfb6155bd09bd6eaf28b5ac72541c1f1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "rayon"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3989,6 +4207,16 @@ dependencies = [
]
[[package]]
+name = "relevant"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbc232e13d37f4547f5b9b42a5efc380cabe5dbc1807f8b893580640b2ab0308"
+dependencies = [
+ "cfg-if",
+ "log",
+]
+
+[[package]]
name = "remove_dir_all"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3998,6 +4226,33 @@ dependencies = [
]
[[package]]
+name = "rendy-descriptor"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f475bcc0505946e998590f1f0545c52ef4b559174a1b353a7ce6638def8b621e"
+dependencies = [
+ "gfx-hal",
+ "log",
+ "relevant",
+ "smallvec",
+]
+
+[[package]]
+name = "rendy-memory"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed492161a819feae7f27f418bb16035276ac20649c60d756699152cb5c1960ec"
+dependencies = [
+ "colorful",
+ "gfx-hal",
+ "hibitset",
+ "log",
+ "relevant",
+ "slab",
+ "smallvec",
+]
+
+[[package]]
name = "rle-decode-fast"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4077,7 +4332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
dependencies = [
"approx",
- "arrayvec",
+ "arrayvec 0.4.6",
"ordered-float",
"stb_truetype",
]
@@ -4199,6 +4454,7 @@ dependencies = [
"utf-8",
"uuid",
"webdriver",
+ "webgpu",
"webrender_api",
"webvr_traits",
"webxr-api",
@@ -4291,6 +4547,7 @@ dependencies = [
"time",
"url",
"webdriver",
+ "webgpu",
"webrender_api",
"webvr_traits",
"webxr-api",
@@ -4905,6 +5162,14 @@ dependencies = [
]
[[package]]
+name = "spirv_cross"
+version = "0.16.0"
+source = "git+https://github.com/kvark/spirv_cross?branch=wgpu#636677bad724797789239c16e6d332e9b4d97b86"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4927,6 +5192,15 @@ dependencies = [
]
[[package]]
+name = "storage-map"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd0a4829a5c591dc24a944a736d6b1e4053e51339a79fd5d4702c4c999a9c45e"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
name = "string"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4971,7 +5245,7 @@ name = "style"
version = "0.0.1"
dependencies = [
"app_units",
- "arrayvec",
+ "arrayvec 0.4.6",
"atomic_refcell",
"bindgen",
"bitflags",
@@ -5583,7 +5857,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f"
dependencies = [
- "arrayvec",
+ "arrayvec 0.4.6",
]
[[package]]
@@ -5897,6 +6171,19 @@ dependencies = [
]
[[package]]
+name = "webgpu"
+version = "0.0.1"
+dependencies = [
+ "embedder_traits",
+ "ipc-channel",
+ "log",
+ "malloc_size_of",
+ "serde",
+ "servo_config",
+ "wgpu-native",
+]
+
+[[package]]
name = "webrender"
version = "0.60.0"
source = "git+https://github.com/servo/webrender#4f2d78adb6e07e3e5ab2da9765613ecf9e07eee0"
@@ -6038,6 +6325,30 @@ dependencies = [
]
[[package]]
+name = "wgpu-native"
+version = "0.4.0"
+source = "git+https://github.com/zakorgy/wgpu?branch=v0.4#128a16b9887a60a087a9d41ff68b20ce07cf6265"
+dependencies = [
+ "arrayvec 0.5.1",
+ "bitflags",
+ "copyless",
+ "fxhash",
+ "gfx-backend-dx11",
+ "gfx-backend-dx12",
+ "gfx-backend-empty",
+ "gfx-backend-metal",
+ "gfx-backend-vulkan",
+ "gfx-hal",
+ "log",
+ "parking_lot",
+ "rendy-descriptor",
+ "rendy-memory",
+ "serde",
+ "smallvec",
+ "vec_map",
+]
+
+[[package]]
name = "which"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index ee35ba935a9..3bb824b3417 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,3 +29,5 @@ opt-level = 3
mio = { git = "https://github.com/servo/mio.git", branch = "servo" }
# https://github.com/retep998/winapi-rs/pull/816
winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" }
+spirv_cross = { git = "https://github.com/kvark/spirv_cross", branch = "wgpu" }
+wgpu-native = { git = "https://github.com/zakorgy/wgpu", branch = "v0.4" }
diff --git a/components/config/opts.rs b/components/config/opts.rs
index 292d06c67dc..fb4e3112837 100644
--- a/components/config/opts.rs
+++ b/components/config/opts.rs
@@ -713,6 +713,12 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
"A preference to set to enable",
"dom.bluetooth.enabled",
);
+ opts.optmulti(
+ "",
+ "pref",
+ "A preference to set to enable",
+ "dom.webgpu.enabled",
+ );
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
opts.optflag("w", "webrender", "Use webrender backend");
opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl");
diff --git a/components/config/prefs.rs b/components/config/prefs.rs
index 7e4fb7551a5..a1e8f96b906 100644
--- a/components/config/prefs.rs
+++ b/components/config/prefs.rs
@@ -159,6 +159,9 @@ mod gen {
},
},
dom: {
+ webgpu: {
+ enabled: bool,
+ },
bluetooth: {
enabled: bool,
testing: {
diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml
index ec360006aad..893930c701a 100644
--- a/components/constellation/Cargo.toml
+++ b/components/constellation/Cargo.toml
@@ -47,6 +47,7 @@ servo_geometry = {path = "../geometry"}
servo_rand = {path = "../rand"}
servo_remutex = {path = "../remutex"}
servo_url = {path = "../url"}
+webgpu = {path = "../webgpu"}
webvr_traits = {path = "../webvr_traits"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 82b99938f3b..3bd77ebf137 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -172,6 +172,7 @@ use std::sync::Arc;
use std::thread;
use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
+use webgpu::WebGPU;
use webvr_traits::{WebVREvent, WebVRMsg};
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;
@@ -440,6 +441,10 @@ pub struct Constellation<Message, LTF, STF> {
/// Entry point to create and get channels to a WebGLThread.
webgl_threads: Option<WebGLThreads>,
+ /// An IPC channel for the constellation to send messages to the
+ /// WebGPU threads.
+ webgpu: Option<WebGPU>,
+
/// A channel through which messages can be sent to the webvr thread.
webvr_chan: Option<IpcSender<WebVRMsg>>,
@@ -521,6 +526,9 @@ pub struct InitialConstellationState {
/// Entry point to create and get channels to a WebGLThread.
pub webgl_threads: Option<WebGLThreads>,
+ /// A channel to the WebGPU threads.
+ pub webgpu: Option<WebGPU>,
+
/// A channel to the webgl thread.
pub webvr_chan: Option<IpcSender<WebVRMsg>>,
@@ -836,6 +844,7 @@ where
(rng, prob)
}),
webgl_threads: state.webgl_threads,
+ webgpu: state.webgpu,
webvr_chan: state.webvr_chan,
webxr_registry: state.webxr_registry,
canvas_chan: CanvasPaintThread::start(),
@@ -1090,6 +1099,7 @@ where
.webgl_threads
.as_ref()
.map(|threads| threads.pipeline()),
+ webgpu: self.webgpu.clone(),
webvr_chan: self.webvr_chan.clone(),
webxr_registry: self.webxr_registry.clone(),
player_context: self.player_context.clone(),
@@ -2355,6 +2365,17 @@ where
}
}
+ if let Some(webgpu) = self.webgpu.as_ref() {
+ debug!("Exiting WebGPU thread.");
+ let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!");
+ if let Err(e) = webgpu.exit(sender) {
+ warn!("Exit WebGPU Thread failed ({})", e);
+ }
+ if let Err(e) = receiver.recv() {
+ warn!("Failed to receive exit response from WebGPU ({})", e);
+ }
+ }
+
if let Some(chan) = self.webvr_chan.as_ref() {
debug!("Exiting WebVR thread.");
if let Err(e) = chan.send(WebVRMsg::Exit) {
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index 3ac5ded15ed..fd7202aa9ec 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -46,6 +46,7 @@ use std::process;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
+use webgpu::WebGPU;
use webvr_traits::WebVRMsg;
/// A `Pipeline` is the constellation's view of a `Document`. Each pipeline has an
@@ -188,6 +189,9 @@ pub struct InitialPipelineState {
/// A channel to the WebGL thread.
pub webgl_chan: Option<WebGLPipeline>,
+ /// A channel to the WebGPU threads.
+ pub webgpu: Option<WebGPU>,
+
/// A channel to the webvr thread.
pub webvr_chan: Option<IpcSender<WebVRMsg>>,
@@ -299,6 +303,7 @@ impl Pipeline {
webrender_document: state.webrender_document,
webgl_chan: state.webgl_chan,
webvr_chan: state.webvr_chan,
+ webgpu: state.webgpu,
webxr_registry: state.webxr_registry,
player_context: state.player_context,
};
@@ -504,6 +509,7 @@ pub struct UnprivilegedPipelineContent {
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
webgl_chan: Option<WebGLPipeline>,
+ webgpu: Option<WebGPU>,
webvr_chan: Option<IpcSender<WebVRMsg>>,
webxr_registry: webxr_api::Registry,
player_context: WindowGLContext,
@@ -556,6 +562,7 @@ impl UnprivilegedPipelineContent {
pipeline_namespace_id: self.pipeline_namespace_id,
content_process_shutdown_chan: content_process_shutdown_chan,
webgl_chan: self.webgl_chan,
+ webgpu: self.webgpu,
webvr_chan: self.webvr_chan,
webxr_registry: self.webxr_registry,
webrender_document: self.webrender_document,
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index c44a9a06a54..855d3d4dbc8 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -113,6 +113,7 @@ utf-8 = "0.7"
uuid = {version = "0.8", features = ["v4"]}
xml5ever = "0.16"
webdriver = "0.40"
+webgpu = {path = "../webgpu"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf
index 3ff7a044b53..5dc9e141ed5 100644
--- a/components/script/dom/bindings/codegen/Bindings.conf
+++ b/components/script/dom/bindings/codegen/Bindings.conf
@@ -134,7 +134,10 @@ DOMInterfaces = {
'XR': {
'inCompartments': ['SupportsSessionMode', 'RequestSession'],
-}
+},
+'GPU': {
+ 'inCompartments': ['RequestAdapter'],
+}
}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 2051a1a19d8..fbd4da02d5b 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -145,6 +145,7 @@ use tendril::stream::LossyDecoder;
use tendril::{StrTendril, TendrilSink};
use time::{Duration, Timespec};
use uuid::Uuid;
+use webgpu::{WebGPU, WebGPUAdapter};
use webrender_api::{DocumentId, ImageKey, RenderApiSender};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
use webxr_api::SwapChainId as WebXRSwapChainId;
@@ -502,6 +503,8 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId);
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
unsafe_no_jsmanaged_fields!(WebGLVersion);
unsafe_no_jsmanaged_fields!(WebGLSLVersion);
+unsafe_no_jsmanaged_fields!(WebGPU);
+unsafe_no_jsmanaged_fields!(WebGPUAdapter);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
diff --git a/components/script/dom/gpu.rs b/components/script/dom/gpu.rs
new file mode 100644
index 00000000000..cbde108bc01
--- /dev/null
+++ b/components/script/dom/gpu.rs
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::compartments::InCompartment;
+use crate::dom::bindings::codegen::Bindings::GPUBinding::GPURequestAdapterOptions;
+use crate::dom::bindings::codegen::Bindings::GPUBinding::{self, GPUMethods, GPUPowerPreference};
+use crate::dom::bindings::error::Error;
+use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::DOMString;
+use crate::dom::globalscope::GlobalScope;
+use crate::dom::gpuadapter::GPUAdapter;
+use crate::dom::promise::Promise;
+use crate::task_source::TaskSource;
+use dom_struct::dom_struct;
+use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::router::ROUTER;
+use js::jsapi::Heap;
+use std::rc::Rc;
+use webgpu::wgpu;
+use webgpu::{WebGPU, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
+
+#[dom_struct]
+pub struct GPU {
+ reflector_: Reflector,
+}
+
+impl GPU {
+ pub fn new_inherited() -> GPU {
+ GPU {
+ reflector_: Reflector::new(),
+ }
+ }
+
+ pub fn new(global: &GlobalScope) -> DomRoot<GPU> {
+ reflect_dom_object(Box::new(GPU::new_inherited()), global, GPUBinding::Wrap)
+ }
+
+ fn wgpu_channel(&self) -> Option<WebGPU> {
+ self.global().as_window().webgpu_channel()
+ }
+}
+
+pub trait AsyncWGPUListener {
+ fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>);
+}
+
+struct WGPUResponse<T: AsyncWGPUListener + DomObject> {
+ trusted: TrustedPromise,
+ receiver: Trusted<T>,
+}
+
+impl<T: AsyncWGPUListener + DomObject> WGPUResponse<T> {
+ #[allow(unrooted_must_root)]
+ fn response(self, response: WebGPUResponseResult) {
+ let promise = self.trusted.root();
+ match response {
+ Ok(response) => self.receiver.root().handle_response(response, &promise),
+ Err(error) => promise.reject_error(Error::Type(format!(
+ "Received error from WebGPU thread: {}",
+ error
+ ))),
+ }
+ }
+}
+
+pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
+ promise: &Rc<Promise>,
+ receiver: &T,
+) -> IpcSender<WebGPUResponseResult> {
+ let (action_sender, action_receiver) = ipc::channel().unwrap();
+ let (task_source, canceller) = receiver
+ .global()
+ .as_window()
+ .task_manager()
+ .dom_manipulation_task_source_with_canceller();
+ let mut trusted = Some(TrustedPromise::new(promise.clone()));
+ let trusted_receiver = Trusted::new(receiver);
+ ROUTER.add_route(
+ action_receiver.to_opaque(),
+ Box::new(move |message| {
+ let trusted = if let Some(trusted) = trusted.take() {
+ trusted
+ } else {
+ error!("WebGPU callback called twice!");
+ return;
+ };
+
+ let context = WGPUResponse {
+ trusted,
+ receiver: trusted_receiver.clone(),
+ };
+ let result = task_source.queue_with_canceller(
+ task!(process_webgpu_task: move|| {
+ context.response(message.to().unwrap());
+ }),
+ &canceller,
+ );
+ if let Err(err) = result {
+ error!("Failed to queue GPU listener-task: {:?}", err);
+ }
+ }),
+ );
+ action_sender
+}
+
+impl GPUMethods for GPU {
+ // https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter
+ fn RequestAdapter(
+ &self,
+ options: &GPURequestAdapterOptions,
+ comp: InCompartment,
+ ) -> Rc<Promise> {
+ let promise = Promise::new_in_current_compartment(&self.global(), comp);
+ let sender = response_async(&promise, self);
+ let power_preference = match options.powerPreference {
+ Some(GPUPowerPreference::Low_power) => wgpu::PowerPreference::LowPower,
+ Some(GPUPowerPreference::High_performance) => wgpu::PowerPreference::HighPerformance,
+ None => wgpu::PowerPreference::Default,
+ };
+
+ match self.wgpu_channel() {
+ Some(channel) => {
+ channel
+ .0
+ .send(WebGPURequest::RequestAdapter(
+ sender,
+ wgpu::RequestAdapterOptions { power_preference },
+ ))
+ .unwrap();
+ },
+ None => promise.reject_error(Error::Type("No WebGPU thread...".to_owned())),
+ };
+ promise
+ }
+}
+
+impl AsyncWGPUListener for GPU {
+ fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
+ match response {
+ WebGPUResponse::RequestAdapter(name, adapter) => {
+ let adapter = GPUAdapter::new(
+ &self.global(),
+ DOMString::from(name),
+ Heap::default(),
+ adapter,
+ );
+ promise.resolve_native(&adapter);
+ },
+ response => promise.reject_error(Error::Type(format!(
+ "Wrong response received for GPU from WebGPU thread {:?}",
+ response,
+ ))),
+ }
+ }
+}
diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs
new file mode 100644
index 00000000000..ec970439e8a
--- /dev/null
+++ b/components/script/dom/gpuadapter.rs
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{self, GPUAdapterMethods};
+use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::DOMString;
+use crate::dom::globalscope::GlobalScope;
+use crate::script_runtime::JSContext as SafeJSContext;
+use dom_struct::dom_struct;
+use js::jsapi::{Heap, JSObject};
+use std::ptr::NonNull;
+use webgpu::WebGPUAdapter;
+
+#[dom_struct]
+pub struct GPUAdapter {
+ reflector_: Reflector,
+ name: DOMString,
+ #[ignore_malloc_size_of = "mozjs"]
+ extensions: Heap<*mut JSObject>,
+ adapter: WebGPUAdapter,
+}
+
+impl GPUAdapter {
+ pub fn new_inherited(
+ name: DOMString,
+ extensions: Heap<*mut JSObject>,
+ adapter: WebGPUAdapter,
+ ) -> GPUAdapter {
+ GPUAdapter {
+ reflector_: Reflector::new(),
+ name,
+ extensions,
+ adapter,
+ }
+ }
+
+ pub fn new(
+ global: &GlobalScope,
+ name: DOMString,
+ extensions: Heap<*mut JSObject>,
+ adapter: WebGPUAdapter,
+ ) -> DomRoot<GPUAdapter> {
+ reflect_dom_object(
+ Box::new(GPUAdapter::new_inherited(name, extensions, adapter)),
+ global,
+ GPUAdapterBinding::Wrap,
+ )
+ }
+}
+
+impl GPUAdapterMethods for GPUAdapter {
+ // https://gpuweb.github.io/gpuweb/#dom-gpuadapter-name
+ fn Name(&self) -> DOMString {
+ self.name.clone()
+ }
+
+ // https://gpuweb.github.io/gpuweb/#dom-gpuadapter-extensions
+ fn Extensions(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
+ NonNull::new(self.extensions.get()).unwrap()
+ }
+}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index ef562931bee..9fbf2e0cc6e 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -315,6 +315,8 @@ pub mod gamepadbuttonlist;
pub mod gamepadevent;
pub mod gamepadlist;
pub mod globalscope;
+pub mod gpu;
+pub mod gpuadapter;
pub mod hashchangeevent;
pub mod headers;
pub mod history;
diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs
index 127883dd956..cb8fb2365cd 100644
--- a/components/script/dom/navigator.rs
+++ b/components/script/dom/navigator.rs
@@ -11,6 +11,7 @@ use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::bluetooth::Bluetooth;
use crate::dom::gamepadlist::GamepadList;
+use crate::dom::gpu::GPU;
use crate::dom::mediadevices::MediaDevices;
use crate::dom::mediasession::MediaSession;
use crate::dom::mimetypearray::MimeTypeArray;
@@ -36,6 +37,7 @@ pub struct Navigator {
gamepads: MutNullableDom<GamepadList>,
permissions: MutNullableDom<Permissions>,
mediasession: MutNullableDom<MediaSession>,
+ gpu: MutNullableDom<GPU>,
}
impl Navigator {
@@ -51,6 +53,7 @@ impl Navigator {
gamepads: Default::default(),
permissions: Default::default(),
mediasession: Default::default(),
+ gpu: Default::default(),
}
}
@@ -205,4 +208,9 @@ impl NavigatorMethods for Navigator {
MediaSession::new(window)
})
}
+
+ // https://gpuweb.github.io/gpuweb/#dom-navigator-gpu
+ fn Gpu(&self) -> DomRoot<GPU> {
+ self.gpu.or_init(|| GPU::new(&self.global()))
+ }
}
diff --git a/components/script/dom/webidls/GPU.webidl b/components/script/dom/webidls/GPU.webidl
new file mode 100644
index 00000000000..856c5027569
--- /dev/null
+++ b/components/script/dom/webidls/GPU.webidl
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+// https://gpuweb.github.io/gpuweb/#gpu-interface
+[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
+interface GPU {
+ // May reject with DOMException // TODO: DOMException("OperationError")?
+ Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {});
+};
+
+// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions
+dictionary GPURequestAdapterOptions {
+ GPUPowerPreference powerPreference;
+};
+
+// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference
+enum GPUPowerPreference {
+ "low-power",
+ "high-performance"
+};
diff --git a/components/script/dom/webidls/GPUAdapter.webidl b/components/script/dom/webidls/GPUAdapter.webidl
new file mode 100644
index 00000000000..0c2118a5f56
--- /dev/null
+++ b/components/script/dom/webidls/GPUAdapter.webidl
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+// https://gpuweb.github.io/gpuweb/#gpuadapter
+[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
+interface GPUAdapter {
+ readonly attribute DOMString name;
+ readonly attribute object extensions;
+ //readonly attribute GPULimits limits; Don’t expose higher limits for now.
+
+ // May reject with DOMException // TODO: DOMException("OperationError")?
+ // Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
+};
diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl
index 6b5b1e1f283..b51e2ba52f0 100644
--- a/components/script/dom/webidls/Navigator.webidl
+++ b/components/script/dom/webidls/Navigator.webidl
@@ -75,3 +75,8 @@ partial interface Navigator {
partial interface Navigator {
[Pref="dom.gamepad.enabled"] GamepadList getGamepads();
};
+
+[Exposed=Window]
+partial interface Navigator {
+ [SameObject, Pref="dom.webgpu.enabled"] readonly attribute GPU gpu;
+};
diff --git a/components/script/dom/webidls/WorkerNavigator.webidl b/components/script/dom/webidls/WorkerNavigator.webidl
index 119e22ea11f..5be43960802 100644
--- a/components/script/dom/webidls/WorkerNavigator.webidl
+++ b/components/script/dom/webidls/WorkerNavigator.webidl
@@ -15,3 +15,8 @@ WorkerNavigator includes NavigatorLanguage;
partial interface WorkerNavigator {
[Pref="dom.permissions.enabled"] readonly attribute Permissions permissions;
};
+
+[Exposed=DedicatedWorker]
+partial interface WorkerNavigator {
+ [SameObject, Pref="dom.webgpu.enabled"] readonly attribute GPU gpu;
+};
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 0c3a2db0899..4ae94520f1f 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -136,6 +136,7 @@ use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::CssRuleType;
use style_traits::{CSSPixel, DevicePixel, ParsingMode};
use url::Position;
+use webgpu::WebGPU;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId, RenderApiSender};
use webvr_traits::WebVRMsg;
@@ -267,6 +268,10 @@ pub struct Window {
#[ignore_malloc_size_of = "channels are hard"]
webgl_chan: Option<WebGLChan>,
+ #[ignore_malloc_size_of = "channels are hard"]
+ /// A handle for communicating messages to the WebGPU threads.
+ webgpu: Option<WebGPU>,
+
/// A handle for communicating messages to the webvr thread, if available.
#[ignore_malloc_size_of = "channels are hard"]
webvr_chan: Option<IpcSender<WebVRMsg>>,
@@ -462,6 +467,10 @@ impl Window {
.map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker()))
}
+ pub fn webgpu_channel(&self) -> Option<WebGPU> {
+ self.webgpu.clone()
+ }
+
pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
self.webvr_chan.clone()
}
@@ -2206,6 +2215,7 @@ impl Window {
navigation_start: u64,
navigation_start_precise: u64,
webgl_chan: Option<WebGLChan>,
+ webgpu: Option<WebGPU>,
webvr_chan: Option<IpcSender<WebVRMsg>>,
webxr_registry: webxr_api::Registry,
microtask_queue: Rc<MicrotaskQueue>,
@@ -2285,6 +2295,7 @@ impl Window {
media_query_lists: DOMTracker::new(),
test_runner: Default::default(),
webgl_chan,
+ webgpu,
webvr_chan,
webxr_registry,
permission_state_invocation_results: Default::default(),
diff --git a/components/script/dom/workernavigator.rs b/components/script/dom/workernavigator.rs
index 92dfa9951e5..cc1dfee13bd 100644
--- a/components/script/dom/workernavigator.rs
+++ b/components/script/dom/workernavigator.rs
@@ -7,6 +7,7 @@ use crate::dom::bindings::codegen::Bindings::WorkerNavigatorBinding::WorkerNavig
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
+use crate::dom::gpu::GPU;
use crate::dom::navigatorinfo;
use crate::dom::permissions::Permissions;
use crate::dom::workerglobalscope::WorkerGlobalScope;
@@ -17,6 +18,7 @@ use dom_struct::dom_struct;
pub struct WorkerNavigator {
reflector_: Reflector,
permissions: MutNullableDom<Permissions>,
+ gpu: MutNullableDom<GPU>,
}
impl WorkerNavigator {
@@ -24,6 +26,7 @@ impl WorkerNavigator {
WorkerNavigator {
reflector_: Reflector::new(),
permissions: Default::default(),
+ gpu: Default::default(),
}
}
@@ -97,4 +100,9 @@ impl WorkerNavigatorMethods for WorkerNavigator {
self.permissions
.or_init(|| Permissions::new(&self.global()))
}
+
+ // https://gpuweb.github.io/gpuweb/#dom-navigator-gpu
+ fn Gpu(&self) -> DomRoot<GPU> {
+ self.gpu.or_init(|| GPU::new(&self.global()))
+ }
}
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index eb6e267c740..b69eb851f2f 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -163,6 +163,7 @@ use style::dom::OpaqueNode;
use style::thread_state::{self, ThreadState};
use time::{at_utc, get_time, precise_time_ns, Timespec};
use url::Position;
+use webgpu::WebGPU;
use webrender_api::units::LayoutPixel;
use webrender_api::{DocumentId, RenderApiSender};
use webvr_traits::{WebVREvent, WebVRMsg};
@@ -629,6 +630,9 @@ pub struct ScriptThread {
/// A handle to the WebGL thread
webgl_chan: Option<WebGLPipeline>,
+ /// A handle to the WebGPU threads
+ webgpu: Option<WebGPU>,
+
/// A handle to the webvr thread, if available
webvr_chan: Option<IpcSender<WebVRMsg>>,
@@ -1338,6 +1342,7 @@ impl ScriptThread {
layout_to_constellation_chan: state.layout_to_constellation_chan,
webgl_chan: state.webgl_chan,
+ webgpu: state.webgpu,
webvr_chan: state.webvr_chan,
webxr_registry: state.webxr_registry,
@@ -3247,6 +3252,7 @@ impl ScriptThread {
incomplete.navigation_start,
incomplete.navigation_start_precise,
self.webgl_chan.as_ref().map(|chan| chan.channel()),
+ self.webgpu.clone(),
self.webvr_chan.clone(),
self.webxr_registry.clone(),
self.microtask_queue.clone(),
diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml
index 3fbdfd1f918..6d736ff3492 100644
--- a/components/script_traits/Cargo.toml
+++ b/components/script_traits/Cargo.toml
@@ -39,6 +39,7 @@ style_traits = {path = "../style_traits", features = ["servo"]}
time = "0.1.12"
url = "2.0"
webdriver = "0.40"
+webgpu = {path = "../webgpu"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index a8a19b5a40a..efa877adb17 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -60,6 +60,7 @@ use std::sync::Arc;
use std::time::Duration;
use style_traits::CSSPixel;
use style_traits::SpeculativePainter;
+use webgpu::WebGPU;
use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId, ImageKey, RenderApiSender};
use webvr_traits::{WebVREvent, WebVRMsg};
@@ -656,6 +657,8 @@ pub struct InitialScriptState {
pub content_process_shutdown_chan: Sender<()>,
/// A channel to the WebGL thread used in this pipeline.
pub webgl_chan: Option<WebGLPipeline>,
+ /// A channel to the WebGPU threads.
+ pub webgpu: Option<WebGPU>,
/// A channel to the webvr thread, if available.
pub webvr_chan: Option<IpcSender<WebVRMsg>>,
/// The XR device registry
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index 458ffb114a0..83f298fb96b 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -79,6 +79,7 @@ servo_url = {path = "../url"}
sparkle = "0.1"
style = {path = "../style", features = ["servo"]}
style_traits = {path = "../style_traits", features = ["servo"]}
+webgpu = {path = "../webgpu"}
webrender = {git = "https://github.com/servo/webrender"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webrender_traits = {path = "../webrender_traits"}
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index d201bc2d757..811a4a002d9 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -49,6 +49,7 @@ pub use servo_geometry;
pub use servo_url;
pub use style;
pub use style_traits;
+pub use webgpu;
pub use webrender_api;
pub use webrender_traits;
pub use webvr;
@@ -863,6 +864,8 @@ fn create_constellation(
let resource_sender = public_resource_threads.sender();
+ let webgpu = webgpu::WebGPU::new();
+
let initial_state = InitialConstellationState {
compositor_proxy,
embedder_proxy,
@@ -877,6 +880,7 @@ fn create_constellation(
webrender_document,
webrender_api_sender,
webgl_threads,
+ webgpu,
webvr_chan,
webxr_registry,
glplayer_threads,
diff --git a/components/webgpu/Cargo.toml b/components/webgpu/Cargo.toml
new file mode 100644
index 00000000000..7581cf768bd
--- /dev/null
+++ b/components/webgpu/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "webgpu"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+license = "MPL-2.0"
+edition = "2018"
+publish = false
+
+[lib]
+name = "webgpu"
+path = "lib.rs"
+
+[dependencies]
+embedder_traits = {path = "../embedder_traits"}
+ipc-channel = "0.12"
+log = "0.4"
+malloc_size_of = { path = "../malloc_size_of" }
+serde = "1.0"
+servo_config = {path = "../config"}
+wgpu-native = { version = "0.4.0", features = ["serde"] }
diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs
new file mode 100644
index 00000000000..5cb449c6c3c
--- /dev/null
+++ b/components/webgpu/lib.rs
@@ -0,0 +1,153 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate serde;
+#[macro_use]
+pub extern crate wgpu_native as wgpu;
+
+use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
+use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
+use servo_config::pref;
+use wgpu::adapter_get_info;
+use wgpu::TypedId;
+
+#[derive(Debug, Deserialize, Serialize)]
+pub enum WebGPUResponse {
+ RequestAdapter(String, WebGPUAdapter),
+ RequestDevice,
+}
+
+pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
+
+#[derive(Debug, Deserialize, Serialize)]
+pub enum WebGPURequest {
+ RequestAdapter(IpcSender<WebGPUResponseResult>, wgpu::RequestAdapterOptions),
+ RequestDevice,
+ Exit(IpcSender<()>),
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct WebGPU(pub IpcSender<WebGPURequest>);
+
+impl WebGPU {
+ pub fn new() -> Option<Self> {
+ if !pref!(dom.webgpu.enabled) {
+ return None;
+ }
+ let (sender, receiver) = match ipc::channel() {
+ Ok(sender_and_receiver) => sender_and_receiver,
+ Err(e) => {
+ warn!(
+ "Failed to create sender and receiciver for WGPU thread ({})",
+ e
+ );
+ return None;
+ },
+ };
+
+ if let Err(e) = std::thread::Builder::new()
+ .name("WGPU".to_owned())
+ .spawn(move || {
+ WGPU::new(receiver).run();
+ })
+ {
+ warn!("Failed to spwan WGPU thread ({})", e);
+ return None;
+ }
+ Some(WebGPU(sender))
+ }
+
+ pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> {
+ self.0
+ .send(WebGPURequest::Exit(sender))
+ .map_err(|_| "Failed to send Exit message")
+ }
+}
+
+struct WGPU {
+ receiver: IpcReceiver<WebGPURequest>,
+ global: wgpu::Global,
+ adapters: Vec<WebGPUAdapter>,
+ // Track invalid adapters https://gpuweb.github.io/gpuweb/#invalid
+ _invalid_adapters: Vec<WebGPUAdapter>,
+}
+
+impl WGPU {
+ fn new(receiver: IpcReceiver<WebGPURequest>) -> Self {
+ WGPU {
+ receiver,
+ global: wgpu::Global::new("webgpu-native"),
+ adapters: Vec::new(),
+ _invalid_adapters: Vec::new(),
+ }
+ }
+
+ fn deinit(self) {
+ self.global.delete()
+ }
+
+ fn run(mut self) {
+ while let Ok(msg) = self.receiver.recv() {
+ match msg {
+ WebGPURequest::RequestAdapter(sender, options) => {
+ let adapter_id = match wgpu::request_adapter(
+ &self.global,
+ &options,
+ // TODO: The ids we pass here should be generated by the client
+ &[
+ wgpu::Id::zip(0, 0, wgpu::Backend::Vulkan),
+ wgpu::Id::zip(0, 0, wgpu::Backend::Metal),
+ wgpu::Id::zip(0, 0, wgpu::Backend::Dx12),
+ ],
+ ) {
+ Some(id) => id,
+ None => {
+ if let Err(e) =
+ sender.send(Err("Failed to get webgpu adapter".to_string()))
+ {
+ warn!(
+ "Failed to send response to WebGPURequest::RequestAdapter ({})",
+ e
+ )
+ }
+ return;
+ },
+ };
+ let adapter = WebGPUAdapter(adapter_id);
+ self.adapters.push(adapter);
+ let info =
+ gfx_select!(adapter_id => adapter_get_info(&self.global, adapter_id));
+ if let Err(e) =
+ sender.send(Ok(WebGPUResponse::RequestAdapter(info.name, adapter)))
+ {
+ warn!(
+ "Failed to send response to WebGPURequest::RequestAdapter ({})",
+ e
+ )
+ }
+ },
+ WebGPURequest::RequestDevice => {},
+ WebGPURequest::Exit(sender) => {
+ self.deinit();
+ if let Err(e) = sender.send(()) {
+ warn!("Failed to send response to WebGPURequest::Exit ({})", e)
+ }
+ return;
+ },
+ }
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+pub struct WebGPUAdapter(pub wgpu::AdapterId);
+
+impl MallocSizeOf for WebGPUAdapter {
+ fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
+ 0
+ }
+}
diff --git a/docs/ORGANIZATION.md b/docs/ORGANIZATION.md
index 2ec15f28b1c..d369a0b50b3 100644
--- a/docs/ORGANIZATION.md
+++ b/docs/ORGANIZATION.md
@@ -54,6 +54,8 @@
* assorted utility methods and types that are commonly used throughout the project.
* webdriver_server
* In-process server to allow manipulating browser instances via a WebDriver client.
+ * webgpu
+ * Implementation of threads for the WebGPU API.
* etc
* Useful tools and scripts for developers.
* mach
diff --git a/python/tidy/servo_tidy/tidy.py b/python/tidy/servo_tidy/tidy.py
index f14112df5da..d2840cc884c 100644
--- a/python/tidy/servo_tidy/tidy.py
+++ b/python/tidy/servo_tidy/tidy.py
@@ -100,6 +100,7 @@ WEBIDL_STANDARDS = [
"//webaudio.github.io",
"//immersive-web.github.io/",
"//github.com/immersive-web/webxr-test-api/",
+ "//gpuweb.github.io",
# Not a URL
"// This interface is entirely internal to Servo, and should not be" +
" accessible to\n// web pages."
diff --git a/resources/prefs.json b/resources/prefs.json
index d715ffab76f..8d5cd69c407 100644
--- a/resources/prefs.json
+++ b/resources/prefs.json
@@ -26,6 +26,7 @@
"dom.testing.htmlinputelement.select_files.enabled": false,
"dom.webgl.dom_to_texture.enabled": false,
"dom.webgl2.enabled": false,
+ "dom.webgpu.enabled": false,
"dom.webrtc.enabled": false,
"dom.webvr.enabled": false,
"dom.webvr.event_polling_interval": 500,
diff --git a/servo-tidy.toml b/servo-tidy.toml
index 46181a8bf54..71f9fb08e36 100644
--- a/servo-tidy.toml
+++ b/servo-tidy.toml
@@ -27,6 +27,7 @@ rand = [
[ignore]
# Ignored packages with duplicated versions
packages = [
+ "arrayvec",
"cgl",
"cocoa",
"gleam",