From a751b1c3d7400ce7b2b8ebbeee076e3eb1a2c106 Mon Sep 17 00:00:00 2001 From: Zakor Gyula Date: Wed, 20 Nov 2019 09:03:10 +0100 Subject: [PATCH] Only start WebGPU thread if an adapter is requested --- Cargo.lock | 1 + components/constellation/constellation.rs | 95 +++++++++++++++++++---- components/constellation/pipeline.rs | 7 -- components/script/dom/bindings/trace.rs | 1 + components/script/dom/gpu.rs | 41 +++++----- components/script/dom/gpuadapter.rs | 27 +++++-- components/script/dom/gpubuffer.rs | 11 +-- components/script/dom/gpudevice.rs | 73 +++++++---------- components/script/dom/window.rs | 11 --- components/script/script_thread.rs | 6 -- components/script_traits/Cargo.toml | 1 + components/script_traits/lib.rs | 3 - components/script_traits/script_msg.rs | 9 +++ components/servo/lib.rs | 3 - components/webgpu/lib.rs | 58 ++++++++------ 15 files changed, 200 insertions(+), 147 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b94f4d42777..df3badcb5f65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4639,6 +4639,7 @@ dependencies = [ "serde", "servo_atoms", "servo_url", + "smallvec 0.6.10", "style_traits", "time", "url", diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index c5fd3a5fd396..89d0b4462a14 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -173,7 +173,7 @@ use std::sync::Arc; use std::thread; use style_traits::viewport::ViewportConstraints; use style_traits::CSSPixel; -use webgpu::WebGPU; +use webgpu::{WebGPU, WebGPURequest}; use webvr_traits::{WebVREvent, WebVRMsg}; type PendingApprovalNavigations = HashMap; @@ -242,6 +242,9 @@ struct BrowsingContextGroup { /// share an event loop, since they can use `document.domain` /// to become same-origin, at which point they can share DOM objects. event_loops: HashMap>, + + /// The set of all WebGPU channels in this BrowsingContextGroup. + webgpus: HashMap, } /// The `Constellation` itself. In the servo browser, there is one @@ -450,10 +453,6 @@ pub struct Constellation { /// Entry point to create and get channels to a WebGLThread. webgl_threads: Option, - /// An IPC channel for the constellation to send messages to the - /// WebGPU threads. - webgpu: Option, - /// A channel through which messages can be sent to the webvr thread. webvr_chan: Option>, @@ -537,9 +536,6 @@ pub struct InitialConstellationState { /// Entry point to create and get channels to a WebGLThread. pub webgl_threads: Option, - /// A channel to the WebGPU threads. - pub webgpu: Option, - /// A channel to the webgl thread. pub webvr_chan: Option>, @@ -973,7 +969,6 @@ where (rng, prob) }), webgl_threads: state.webgl_threads, - webgpu: state.webgpu, webvr_chan: state.webvr_chan, webxr_registry: state.webxr_registry, canvas_chan, @@ -1230,7 +1225,6 @@ 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(), @@ -1945,9 +1939,65 @@ where EmbedderMsg::MediaSessionEvent(event), )); }, + FromScriptMsg::RequestAdapter(sender, options, ids) => self + .handle_request_wgpu_adapter( + source_pipeline_id, + BrowsingContextId::from(source_top_ctx_id), + FromScriptMsg::RequestAdapter(sender, options, ids), + ), } } + fn handle_request_wgpu_adapter( + &mut self, + source_pipeline_id: PipelineId, + browsing_context_id: BrowsingContextId, + request: FromScriptMsg, + ) { + let browsing_context_group_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(bc) => &bc.bc_group_id, + None => return warn!("Browsing context not found"), + }; + let host = match self + .pipelines + .get(&source_pipeline_id) + .map(|pipeline| &pipeline.url) + { + Some(ref url) => match reg_host(&url) { + Some(host) => host, + None => return warn!("Invalid host url"), + }, + None => return warn!("ScriptMsg from closed pipeline {:?}.", source_pipeline_id), + }; + match self + .browsing_context_group_set + .get_mut(&browsing_context_group_id) + { + Some(browsing_context_group) => { + let adapter_request = + if let FromScriptMsg::RequestAdapter(sender, options, ids) = request { + WebGPURequest::RequestAdapter(sender, options, ids) + } else { + return warn!("Wrong message type in handle_request_wgpu_adapter"); + }; + let send = match browsing_context_group.webgpus.entry(host) { + Entry::Vacant(v) => v + .insert(match WebGPU::new() { + Some(webgpu) => webgpu, + None => return warn!("Failed to create new WebGPU thread"), + }) + .0 + .send(adapter_request), + Entry::Occupied(o) => o.get().0.send(adapter_request), + }; + if send.is_err() { + return warn!("Failed to send request adapter message on WebGPU channel"); + } + }, + None => return warn!("Browsing context group not found"), + }; + } + fn handle_request_from_layout(&mut self, message: FromLayoutMsg) { debug!("Constellation got {:?} message", message); match message { @@ -2496,12 +2546,25 @@ 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); - } + debug!("Exiting WebGPU threads."); + let receivers = self + .browsing_context_group_set + .values() + .map(|browsing_context_group| { + browsing_context_group.webgpus.values().map(|webgpu| { + let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); + if let Err(e) = webgpu.exit(sender) { + warn!("Exit WebGPU Thread failed ({})", e); + None + } else { + Some(receiver) + } + }) + }) + .flatten() + .filter_map(|r| r); + + for receiver in receivers { if let Err(e) = receiver.recv() { warn!("Failed to receive exit response from WebGPU ({})", e); } diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index defa7f2e7a9d..e81f1ab58aee 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -48,7 +48,6 @@ 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 @@ -194,9 +193,6 @@ pub struct InitialPipelineState { /// A channel to the WebGL thread. pub webgl_chan: Option, - /// A channel to the WebGPU threads. - pub webgpu: Option, - /// A channel to the webvr thread. pub webvr_chan: Option>, @@ -309,7 +305,6 @@ 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, }; @@ -516,7 +511,6 @@ pub struct UnprivilegedPipelineContent { webrender_image_api_sender: net_traits::WebrenderIpcSender, webrender_document: webrender_api::DocumentId, webgl_chan: Option, - webgpu: Option, webvr_chan: Option>, webxr_registry: webxr_api::Registry, player_context: WindowGLContext, @@ -569,7 +563,6 @@ 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/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 3bad24b1b1d5..f15358684e69 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -521,6 +521,7 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId); unsafe_no_jsmanaged_fields!(WebGLVertexArrayId); unsafe_no_jsmanaged_fields!(WebGLVersion); unsafe_no_jsmanaged_fields!(WebGLSLVersion); +unsafe_no_jsmanaged_fields!(RefCell>); unsafe_no_jsmanaged_fields!(RefCell); unsafe_no_jsmanaged_fields!(WebGPU); unsafe_no_jsmanaged_fields!(WebGPUAdapter); diff --git a/components/script/dom/gpu.rs b/components/script/dom/gpu.rs index 8a3e05f2d792..4c4bd830f6eb 100644 --- a/components/script/dom/gpu.rs +++ b/components/script/dom/gpu.rs @@ -19,9 +19,10 @@ use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use js::jsapi::Heap; +use script_traits::ScriptMsg; use std::rc::Rc; use webgpu::wgpu; -use webgpu::{WebGPU, WebGPURequest, WebGPUResponse, WebGPUResponseResult}; +use webgpu::{WebGPUResponse, WebGPUResponseResult}; #[dom_struct] pub struct GPU { @@ -38,10 +39,6 @@ impl GPU { pub fn new(global: &GlobalScope) -> DomRoot { reflect_dom_object(Box::new(GPU::new_inherited()), global, GPUBinding::Wrap) } - - fn wgpu_channel(&self) -> Option { - self.global().as_window().webgpu_channel() - } } pub trait AsyncWGPUListener { @@ -114,7 +111,8 @@ impl GPUMethods for GPU { options: &GPURequestAdapterOptions, comp: InCompartment, ) -> Rc { - let promise = Promise::new_in_current_compartment(&self.global(), comp); + let global = &self.global(); + let promise = Promise::new_in_current_compartment(global, comp); let sender = response_async(&promise, self); let power_preference = match options.powerPreference { Some(GPUPowerPreference::Low_power) => wgpu::instance::PowerPreference::LowPower, @@ -123,21 +121,21 @@ impl GPUMethods for GPU { }, None => wgpu::instance::PowerPreference::Default, }; - let ids = self.global().as_window().Navigator().create_adapter_ids(); + let ids = global.as_window().Navigator().create_adapter_ids(); - match self.wgpu_channel() { - Some(channel) => { - channel - .0 - .send(WebGPURequest::RequestAdapter( - sender, - wgpu::instance::RequestAdapterOptions { power_preference }, - ids, - )) - .unwrap(); - }, - None => promise.reject_error(Error::Type("No WebGPU thread...".to_owned())), - }; + let script_to_constellation_chan = global.script_to_constellation_chan(); + if script_to_constellation_chan + .send(ScriptMsg::RequestAdapter( + sender, + wgpu::instance::RequestAdapterOptions { power_preference }, + ids, + )) + .is_err() + { + promise.reject_error(Error::Type( + "Failed to send adapter request to constellation...".to_owned(), + )); + } promise } } @@ -145,9 +143,10 @@ impl GPUMethods for GPU { impl AsyncWGPUListener for GPU { fn handle_response(&self, response: WebGPUResponse, promise: &Rc) { match response { - WebGPUResponse::RequestAdapter(name, adapter) => { + WebGPUResponse::RequestAdapter(name, adapter, channel) => { let adapter = GPUAdapter::new( &self.global(), + channel, DOMString::from(format!("{} ({:?})", name, adapter.0.backend())), Heap::default(), adapter, diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index cbb24917ebe9..80438c305acb 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -23,11 +23,13 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use std::ptr::NonNull; use std::rc::Rc; -use webgpu::{wgpu, WebGPUAdapter, WebGPURequest, WebGPUResponse}; +use webgpu::{wgpu, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse}; #[dom_struct] pub struct GPUAdapter { reflector_: Reflector, + #[ignore_malloc_size_of = "channels are hard"] + channel: WebGPU, name: DOMString, #[ignore_malloc_size_of = "mozjs"] extensions: Heap<*mut JSObject>, @@ -36,12 +38,14 @@ pub struct GPUAdapter { impl GPUAdapter { pub fn new_inherited( + channel: WebGPU, name: DOMString, extensions: Heap<*mut JSObject>, adapter: WebGPUAdapter, ) -> GPUAdapter { GPUAdapter { reflector_: Reflector::new(), + channel, name, extensions, adapter, @@ -50,12 +54,15 @@ impl GPUAdapter { pub fn new( global: &GlobalScope, + channel: WebGPU, name: DOMString, extensions: Heap<*mut JSObject>, adapter: WebGPUAdapter, ) -> DomRoot { reflect_dom_object( - Box::new(GPUAdapter::new_inherited(name, extensions, adapter)), + Box::new(GPUAdapter::new_inherited( + channel, name, extensions, adapter, + )), global, GPUAdapterBinding::Wrap, ) @@ -89,12 +96,15 @@ impl GPUAdapterMethods for GPUAdapter { let id = window .Navigator() .create_device_id(self.adapter.0.backend()); - match window.webgpu_channel() { - Some(thread) => thread - .0 - .send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id)) - .unwrap(), - None => promise.reject_error(Error::Type("No WebGPU thread...".to_owned())), + if self + .channel + .0 + .send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id)) + .is_err() + { + promise.reject_error(Error::Type( + "Failed to send RequestDevice message...".to_owned(), + )); } } else { promise.reject_error(Error::Type("No WebGPU thread...".to_owned())) @@ -109,6 +119,7 @@ impl AsyncWGPUListener for GPUAdapter { WebGPUResponse::RequestDevice(device_id, _descriptor) => { let device = GPUDevice::new( &self.global(), + self.channel.clone(), &self, Heap::default(), Heap::default(), diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index a2a3e3b62ebd..160ef6cf79c2 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -11,9 +11,8 @@ use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use dom_struct::dom_struct; -use ipc_channel::ipc::IpcSender; use std::cell::Cell; -use webgpu::{WebGPUBuffer, WebGPUDevice, WebGPURequest}; +use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest}; #[derive(MallocSizeOf)] pub enum GPUBufferState { @@ -26,7 +25,7 @@ pub enum GPUBufferState { pub struct GPUBuffer { reflector_: Reflector, #[ignore_malloc_size_of = "channels are hard"] - channel: IpcSender, + channel: WebGPU, label: DomRefCell>, size: GPUBufferSize, usage: u32, @@ -38,7 +37,7 @@ pub struct GPUBuffer { impl GPUBuffer { fn new_inherited( - channel: IpcSender, + channel: WebGPU, buffer: WebGPUBuffer, device: WebGPUDevice, state: GPUBufferState, @@ -62,7 +61,7 @@ impl GPUBuffer { #[allow(unsafe_code)] pub fn new( global: &GlobalScope, - channel: IpcSender, + channel: WebGPU, buffer: WebGPUBuffer, device: WebGPUDevice, state: GPUBufferState, @@ -90,6 +89,7 @@ impl GPUBufferMethods for GPUBuffer { /// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap fn Unmap(&self) { self.channel + .0 .send(WebGPURequest::UnmapBuffer(self.buffer)) .unwrap(); } @@ -103,6 +103,7 @@ impl GPUBufferMethods for GPUBuffer { _ => {}, }; self.channel + .0 .send(WebGPURequest::DestroyBuffer(self.buffer)) .unwrap(); *self.state.borrow_mut() = GPUBufferState::Destroyed; diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 81974735b554..ba1ea368a5b9 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -25,11 +25,13 @@ use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use js::typedarray::{ArrayBuffer, CreateWith}; use std::ptr::{self, NonNull}; use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage}; -use webgpu::{WebGPUBuffer, WebGPUDevice, WebGPURequest}; +use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest}; #[dom_struct] pub struct GPUDevice { eventtarget: EventTarget, + #[ignore_malloc_size_of = "channels are hard"] + channel: WebGPU, adapter: Dom, #[ignore_malloc_size_of = "mozjs"] extensions: Heap<*mut JSObject>, @@ -41,6 +43,7 @@ pub struct GPUDevice { impl GPUDevice { fn new_inherited( + channel: WebGPU, adapter: &GPUAdapter, extensions: Heap<*mut JSObject>, limits: Heap<*mut JSObject>, @@ -48,6 +51,7 @@ impl GPUDevice { ) -> GPUDevice { Self { eventtarget: EventTarget::new_inherited(), + channel, adapter: Dom::from_ref(adapter), extensions, limits, @@ -59,6 +63,7 @@ impl GPUDevice { #[allow(unsafe_code)] pub fn new( global: &GlobalScope, + channel: WebGPU, adapter: &GPUAdapter, extensions: Heap<*mut JSObject>, limits: Heap<*mut JSObject>, @@ -66,7 +71,7 @@ impl GPUDevice { ) -> DomRoot { reflect_dom_object( Box::new(GPUDevice::new_inherited( - adapter, extensions, limits, device, + channel, adapter, extensions, limits, device, )), global, GPUDeviceBinding::Wrap, @@ -78,7 +83,6 @@ impl GPUDevice { unsafe fn resolve_create_buffer_mapped( &self, cx: SafeJSContext, - channel: ipc_channel::ipc::IpcSender, gpu_buffer: WebGPUBuffer, array_buffer: Vec, descriptor: BufferDescriptor, @@ -95,7 +99,7 @@ impl GPUDevice { let buff = GPUBuffer::new( &self.global(), - channel, + self.channel.clone(), gpu_buffer, self.device, GPUBufferState::Mapped, @@ -165,25 +169,18 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot { let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); - let channel; let (sender, receiver) = ipc::channel().unwrap(); if let Some(window) = self.global().downcast::() { let id = window.Navigator().create_buffer_id(self.device.0.backend()); - match window.webgpu_channel() { - Some(thread) => { - channel = thread.0.clone(); - thread - .0 - .send(WebGPURequest::CreateBuffer( - sender, - self.device, - id, - wgpu_descriptor, - )) - .unwrap(); - }, - None => unimplemented!(), - } + self.channel + .0 + .send(WebGPURequest::CreateBuffer( + sender, + self.device, + id, + wgpu_descriptor, + )) + .unwrap(); } else { unimplemented!() }; @@ -192,7 +189,7 @@ impl GPUDeviceMethods for GPUDevice { GPUBuffer::new( &self.global(), - channel, + self.channel.clone(), buffer, self.device, GPUBufferState::Unmapped, @@ -209,26 +206,19 @@ impl GPUDeviceMethods for GPUDevice { descriptor: &GPUBufferDescriptor, ) -> Vec { let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); - let channel; let (sender, receiver) = ipc::channel().unwrap(); rooted!(in(*cx) let js_val = UndefinedValue()); if let Some(window) = self.global().downcast::() { let id = window.Navigator().create_buffer_id(self.device.0.backend()); - match window.webgpu_channel() { - Some(thread) => { - channel = thread.0.clone(); - thread - .0 - .send(WebGPURequest::CreateBufferMapped( - sender, - self.device, - id, - wgpu_descriptor.clone(), - )) - .unwrap() - }, - None => return vec![js_val.get()], - } + self.channel + .0 + .send(WebGPURequest::CreateBufferMapped( + sender, + self.device, + id, + wgpu_descriptor.clone(), + )) + .unwrap() } else { return vec![js_val.get()]; }; @@ -236,14 +226,7 @@ impl GPUDeviceMethods for GPUDevice { let (buffer, array_buffer) = receiver.recv().unwrap(); unsafe { - self.resolve_create_buffer_mapped( - cx, - channel, - buffer, - array_buffer, - wgpu_descriptor, - valid, - ) + self.resolve_create_buffer_mapped(cx, buffer, array_buffer, wgpu_descriptor, valid) } } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index d48f16ea6623..09b710689bde 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -135,7 +135,6 @@ 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}; use webvr_traits::WebVRMsg; @@ -267,10 +266,6 @@ pub struct Window { #[ignore_malloc_size_of = "channels are hard"] webgl_chan: Option, - #[ignore_malloc_size_of = "channels are hard"] - /// A handle for communicating messages to the WebGPU threads. - webgpu: Option, - /// A handle for communicating messages to the webvr thread, if available. #[ignore_malloc_size_of = "channels are hard"] webvr_chan: Option>, @@ -466,10 +461,6 @@ impl Window { .map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker())) } - pub fn webgpu_channel(&self) -> Option { - self.webgpu.clone() - } - pub fn webvr_thread(&self) -> Option> { self.webvr_chan.clone() } @@ -2213,7 +2204,6 @@ impl Window { navigation_start: u64, navigation_start_precise: u64, webgl_chan: Option, - webgpu: Option, webvr_chan: Option>, webxr_registry: webxr_api::Registry, microtask_queue: Rc, @@ -2292,7 +2282,6 @@ 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/script_thread.rs b/components/script/script_thread.rs index f5397d8cce59..9ce99c264412 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -164,7 +164,6 @@ 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; use webvr_traits::{WebVREvent, WebVRMsg}; @@ -630,9 +629,6 @@ pub struct ScriptThread { /// A handle to the WebGL thread webgl_chan: Option, - /// A handle to the WebGPU threads - webgpu: Option, - /// A handle to the webvr thread, if available webvr_chan: Option>, @@ -1339,7 +1335,6 @@ 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, @@ -3201,7 +3196,6 @@ 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 0635d99dda33..6b540a98c2bb 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -36,6 +36,7 @@ profile_traits = {path = "../profile_traits"} serde = "1.0" servo_atoms = {path = "../atoms"} servo_url = {path = "../url"} +smallvec = "0.6" style_traits = {path = "../style_traits", features = ["servo"]} time = "0.1.12" url = "2.0" diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 8e6b89e12f93..d2d37e5c32ae 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -65,7 +65,6 @@ 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, LayoutPoint, LayoutSize, WorldPoint, }; @@ -665,8 +664,6 @@ pub struct InitialScriptState { pub content_process_shutdown_chan: Sender<()>, /// A channel to the WebGL thread used in this pipeline. pub webgl_chan: Option, - /// A channel to the WebGPU threads. - pub webgpu: Option, /// A channel to the webvr thread, if available. pub webvr_chan: Option>, /// The XR device registry diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 1eccc7943982..8a04b59d57d6 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -30,10 +30,12 @@ use net_traits::storage_thread::StorageType; use net_traits::CoreResourceMsg; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; +use smallvec::SmallVec; use std::collections::{HashMap, VecDeque}; use std::fmt; use style_traits::viewport::ViewportConstraints; use style_traits::CSSPixel; +use webgpu::{wgpu, WebGPUResponseResult}; use webrender_api::units::{DeviceIntPoint, DeviceIntSize}; /// A particular iframe's size, associated with a browsing context. @@ -257,6 +259,12 @@ pub enum ScriptMsg { /// Notifies the constellation about media session events /// (i.e. when there is metadata for the active media session, playback state changes...). MediaSessionEvent(PipelineId, MediaSessionEvent), + /// Create a WebGPU Adapter instance + RequestAdapter( + IpcSender, + wgpu::instance::RequestAdapterOptions, + SmallVec<[wgpu::id::AdapterId; 4]>, + ), } impl fmt::Debug for ScriptMsg { @@ -309,6 +317,7 @@ impl fmt::Debug for ScriptMsg { GetScreenSize(..) => "GetScreenSize", GetScreenAvailSize(..) => "GetScreenAvailSize", MediaSessionEvent(..) => "MediaSessionEvent", + RequestAdapter(..) => "RequestAdapter", }; write!(formatter, "ScriptMsg::{}", variant) } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index ad82066c3df7..2ae1908f8bb3 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -874,8 +874,6 @@ fn create_constellation( let resource_sender = public_resource_threads.sender(); - let webgpu = webgpu::WebGPU::new(); - let initial_state = InitialConstellationState { compositor_proxy, embedder_proxy, @@ -890,7 +888,6 @@ fn create_constellation( webrender_document, webrender_api_sender, webgl_threads, - webgpu, webvr_chan, webxr_registry, glplayer_threads, diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 156beeb040b7..8ad053460bbd 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -16,7 +16,7 @@ use smallvec::SmallVec; #[derive(Debug, Deserialize, Serialize)] pub enum WebGPUResponse { - RequestAdapter(String, WebGPUAdapter), + RequestAdapter(String, WebGPUAdapter, WebGPU), RequestDevice(WebGPUDevice, wgpu::instance::DeviceDescriptor), } @@ -70,11 +70,12 @@ impl WebGPU { return None; }, }; + let sender_clone = sender.clone(); if let Err(e) = std::thread::Builder::new() .name("WGPU".to_owned()) .spawn(move || { - WGPU::new(receiver).run(); + WGPU::new(receiver, sender_clone).run(); }) { warn!("Failed to spwan WGPU thread ({})", e); @@ -92,6 +93,7 @@ impl WebGPU { struct WGPU { receiver: IpcReceiver, + sender: IpcSender, global: wgpu::hub::Global<()>, adapters: Vec, devices: Vec, @@ -100,9 +102,10 @@ struct WGPU { } impl WGPU { - fn new(receiver: IpcReceiver) -> Self { + fn new(receiver: IpcReceiver, sender: IpcSender) -> Self { WGPU { receiver, + sender, global: wgpu::hub::Global::new("wgpu-core"), adapters: Vec::new(), devices: Vec::new(), @@ -118,30 +121,41 @@ impl WGPU { while let Ok(msg) = self.receiver.recv() { match msg { WebGPURequest::RequestAdapter(sender, options, ids) => { - let adapter_id = match self.global.pick_adapter( - &options, - wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), - ) { - 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_id = if let Some(pos) = self + .adapters + .iter() + .position(|adapter| ids.contains(&adapter.0)) + { + self.adapters[pos].0 + } else { + let adapter_id = match self.global.pick_adapter( + &options, + wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), + ) { + 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; + }, + }; + adapter_id }; let adapter = WebGPUAdapter(adapter_id); self.adapters.push(adapter); let global = &self.global; let info = gfx_select!(adapter_id => global.adapter_get_info(adapter_id)); - if let Err(e) = - sender.send(Ok(WebGPUResponse::RequestAdapter(info.name, adapter))) - { + if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter( + info.name, + adapter, + WebGPU(self.sender.clone()), + ))) { warn!( "Failed to send response to WebGPURequest::RequestAdapter ({})", e