Auto merge of #25580 - szeged:wgpu_worker, r=jdm

Support worker for WebGPU

To create resource ids for the WebGPU we need to access the `IdentityHub`.
In order to access the `IdentityHub` from a `Window` or a `Worker` as well, I've moved the `IdentityHub` to the `GlobalScope` from the `Navigator`.

<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #25532

cc @kvark @jdm @zakorgy
This commit is contained in:
bors-servo 2020-01-23 07:53:58 -05:00 committed by GitHub
commit 2b77a992db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 122 deletions

View file

@ -26,6 +26,7 @@ use crate::dom::eventsource::EventSource;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::file::File; use crate::dom::file::File;
use crate::dom::htmlscriptelement::ScriptId; use crate::dom::htmlscriptelement::ScriptId;
use crate::dom::identityhub::Identities;
use crate::dom::messageevent::MessageEvent; use crate::dom::messageevent::MessageEvent;
use crate::dom::messageport::MessagePort; use crate::dom::messageport::MessagePort;
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
@ -79,8 +80,9 @@ use script_traits::{
}; };
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource}; use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
use servo_url::{MutableOrigin, ServoUrl}; use servo_url::{MutableOrigin, ServoUrl};
use smallvec::SmallVec;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::Cell; use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::ffi::CString; use std::ffi::CString;
@ -91,6 +93,10 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use time::{get_time, Timespec}; use time::{get_time, Timespec};
use uuid::Uuid; use uuid::Uuid;
use webgpu::wgpu::{
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
Backend,
};
#[derive(JSTraceable)] #[derive(JSTraceable)]
pub struct AutoCloseWorker(Arc<AtomicBool>); pub struct AutoCloseWorker(Arc<AtomicBool>);
@ -206,6 +212,9 @@ pub struct GlobalScope {
/// An optional string allowing the user agent to be set for testing. /// An optional string allowing the user agent to be set for testing.
user_agent: Cow<'static, str>, user_agent: Cow<'static, str>,
#[ignore_malloc_size_of = "defined in wgpu"]
gpu_id_hub: RefCell<Identities>,
} }
/// A wrapper for glue-code between the ipc router and the event-loop. /// A wrapper for glue-code between the ipc router and the event-loop.
@ -421,6 +430,7 @@ impl GlobalScope {
consumed_rejections: Default::default(), consumed_rejections: Default::default(),
is_headless, is_headless,
user_agent, user_agent,
gpu_id_hub: RefCell::new(Identities::new()),
} }
} }
@ -1970,6 +1980,30 @@ impl GlobalScope {
// TODO: Worker and Worklet global scopes. // TODO: Worker and Worklet global scopes.
None None
} }
pub fn wgpu_create_adapter_ids(&self) -> SmallVec<[AdapterId; 4]> {
self.gpu_id_hub.borrow_mut().create_adapter_ids()
}
pub fn wgpu_create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId {
self.gpu_id_hub
.borrow_mut()
.create_bind_group_layout_id(backend)
}
pub fn wgpu_create_buffer_id(&self, backend: Backend) -> BufferId {
self.gpu_id_hub.borrow_mut().create_buffer_id(backend)
}
pub fn wgpu_create_device_id(&self, backend: Backend) -> DeviceId {
self.gpu_id_hub.borrow_mut().create_device_id(backend)
}
pub fn wgpu_create_pipeline_layout_id(&self, backend: Backend) -> PipelineLayoutId {
self.gpu_id_hub
.borrow_mut()
.create_pipeline_layout_id(backend)
}
} }
fn timestamp_in_ms(time: Timespec) -> u64 { fn timestamp_in_ms(time: Timespec) -> u64 {

View file

@ -5,7 +5,6 @@
use crate::compartments::InCompartment; use crate::compartments::InCompartment;
use crate::dom::bindings::codegen::Bindings::GPUBinding::GPURequestAdapterOptions; use crate::dom::bindings::codegen::Bindings::GPUBinding::GPURequestAdapterOptions;
use crate::dom::bindings::codegen::Bindings::GPUBinding::{self, GPUMethods, GPUPowerPreference}; use crate::dom::bindings::codegen::Bindings::GPUBinding::{self, GPUMethods, GPUPowerPreference};
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use crate::dom::bindings::error::Error; use crate::dom::bindings::error::Error;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
@ -14,7 +13,7 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter; use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::task_source::TaskSource; use crate::task_source::{TaskSource, TaskSourceName};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
@ -69,11 +68,10 @@ pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
receiver: &T, receiver: &T,
) -> IpcSender<WebGPUResponseResult> { ) -> IpcSender<WebGPUResponseResult> {
let (action_sender, action_receiver) = ipc::channel().unwrap(); let (action_sender, action_receiver) = ipc::channel().unwrap();
let (task_source, canceller) = receiver let task_source = receiver.global().dom_manipulation_task_source();
let canceller = receiver
.global() .global()
.as_window() .task_canceller(TaskSourceName::DOMManipulation);
.task_manager()
.dom_manipulation_task_source_with_canceller();
let mut trusted = Some(TrustedPromise::new(promise.clone())); let mut trusted = Some(TrustedPromise::new(promise.clone()));
let trusted_receiver = Trusted::new(receiver); let trusted_receiver = Trusted::new(receiver);
ROUTER.add_route( ROUTER.add_route(
@ -121,7 +119,7 @@ impl GPUMethods for GPU {
}, },
None => wgpu::instance::PowerPreference::Default, None => wgpu::instance::PowerPreference::Default,
}; };
let ids = global.as_window().Navigator().create_adapter_ids(); let ids = global.wgpu_create_adapter_ids();
let script_to_constellation_chan = global.script_to_constellation_chan(); let script_to_constellation_chan = global.script_to_constellation_chan();
if script_to_constellation_chan if script_to_constellation_chan

View file

@ -6,9 +6,7 @@ use crate::compartments::InCompartment;
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{ use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{
self, GPUAdapterMethods, GPUDeviceDescriptor, self, GPUAdapterMethods, GPUDeviceDescriptor,
}; };
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use crate::dom::bindings::error::Error; use crate::dom::bindings::error::Error;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
@ -17,7 +15,6 @@ use crate::dom::gpu::response_async;
use crate::dom::gpu::AsyncWGPUListener; use crate::dom::gpu::AsyncWGPUListener;
use crate::dom::gpudevice::GPUDevice; use crate::dom::gpudevice::GPUDevice;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
@ -92,21 +89,17 @@ impl GPUAdapterMethods for GPUAdapter {
max_bind_groups: descriptor.limits.maxBindGroups, max_bind_groups: descriptor.limits.maxBindGroups,
}, },
}; };
if let Some(window) = self.global().downcast::<Window>() { let id = self
let id = window .global()
.Navigator() .wgpu_create_device_id(self.adapter.0.backend());
.create_device_id(self.adapter.0.backend()); if self
if self .channel
.channel .0
.0 .send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id))
.send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id)) .is_err()
.is_err() {
{
promise.reject_error(Error::Operation);
}
} else {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation);
}; }
promise promise
} }
} }

View file

@ -12,8 +12,6 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods}; use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor; use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
@ -23,12 +21,11 @@ use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpupipelinelayout::GPUPipelineLayout;
use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc; use ipc_channel::ipc;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use js::jsval::{JSVal, ObjectValue};
use js::typedarray::{ArrayBuffer, CreateWith}; use js::typedarray::{ArrayBuffer, CreateWith};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
@ -179,20 +176,16 @@ impl GPUDeviceMethods for GPUDevice {
fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> { fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> {
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor);
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
if let Some(window) = self.global().downcast::<Window>() { let id = self.global().wgpu_create_buffer_id(self.device.0.backend());
let id = window.Navigator().create_buffer_id(self.device.0.backend()); self.channel
self.channel .0
.0 .send(WebGPURequest::CreateBuffer(
.send(WebGPURequest::CreateBuffer( sender,
sender, self.device,
self.device, id,
id, wgpu_descriptor,
wgpu_descriptor, ))
)) .expect("Failed to create WebGPU buffer");
.expect("Failed to create WebGPU buffer");
} else {
unimplemented!()
};
let buffer = receiver.recv().unwrap(); let buffer = receiver.recv().unwrap();
@ -216,21 +209,16 @@ impl GPUDeviceMethods for GPUDevice {
) -> Vec<JSVal> { ) -> Vec<JSVal> {
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor);
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
rooted!(in(*cx) let js_val = UndefinedValue()); let id = self.global().wgpu_create_buffer_id(self.device.0.backend());
if let Some(window) = self.global().downcast::<Window>() { self.channel
let id = window.Navigator().create_buffer_id(self.device.0.backend()); .0
self.channel .send(WebGPURequest::CreateBufferMapped(
.0 sender,
.send(WebGPURequest::CreateBufferMapped( self.device,
sender, id,
self.device, wgpu_descriptor.clone(),
id, ))
wgpu_descriptor.clone(), .expect("Failed to create WebGPU buffer");
))
.expect("Failed to create WebGPU buffer");
} else {
return vec![js_val.get()];
};
let (buffer, array_buffer) = receiver.recv().unwrap(); let (buffer, array_buffer) = receiver.recv().unwrap();
@ -381,20 +369,19 @@ impl GPUDeviceMethods for GPUDevice {
max_dynamic_storage_buffers_per_pipeline_layout >= 0; max_dynamic_storage_buffers_per_pipeline_layout >= 0;
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
if let Some(window) = self.global().downcast::<Window>() { let id = self
let id = window .global()
.Navigator() .wgpu_create_bind_group_layout_id(self.device.0.backend());
.create_bind_group_layout_id(self.device.0.backend()); self.channel
self.channel .0
.0 .send(WebGPURequest::CreateBindGroupLayout(
.send(WebGPURequest::CreateBindGroupLayout( sender,
sender, self.device,
self.device, id,
id, bindings.clone(),
bindings.clone(), ))
)) .expect("Failed to create WebGPU BindGroupLayout");
.expect("Failed to create WebGPU BindGroupLayout");
}
let bgl = receiver.recv().unwrap(); let bgl = receiver.recv().unwrap();
let binds = descriptor let binds = descriptor
@ -460,20 +447,19 @@ impl GPUDeviceMethods for GPUDevice {
max_dynamic_storage_buffers_per_pipeline_layout >= 0; max_dynamic_storage_buffers_per_pipeline_layout >= 0;
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
if let Some(window) = self.global().downcast::<Window>() { let id = self
let id = window .global()
.Navigator() .wgpu_create_pipeline_layout_id(self.device.0.backend());
.create_pipeline_layout_id(self.device.0.backend()); self.channel
self.channel .0
.0 .send(WebGPURequest::CreatePipelineLayout(
.send(WebGPURequest::CreatePipelineLayout( sender,
sender, self.device,
self.device, id,
id, bgl_ids,
bgl_ids, ))
)) .expect("Failed to create WebGPU PipelineLayout");
.expect("Failed to create WebGPU PipelineLayout");
}
let pipeline_layout = receiver.recv().unwrap(); let pipeline_layout = receiver.recv().unwrap();
GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid) GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid)
} }

View file

@ -12,7 +12,6 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::bluetooth::Bluetooth; use crate::dom::bluetooth::Bluetooth;
use crate::dom::gamepadlist::GamepadList; use crate::dom::gamepadlist::GamepadList;
use crate::dom::gpu::GPU; use crate::dom::gpu::GPU;
use crate::dom::identityhub::Identities;
use crate::dom::mediadevices::MediaDevices; use crate::dom::mediadevices::MediaDevices;
use crate::dom::mediasession::MediaSession; use crate::dom::mediasession::MediaSession;
use crate::dom::mimetypearray::MimeTypeArray; use crate::dom::mimetypearray::MimeTypeArray;
@ -24,13 +23,7 @@ use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::dom::xr::XR; use crate::dom::xr::XR;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use smallvec::SmallVec;
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use webgpu::wgpu::{
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
Backend,
};
#[dom_struct] #[dom_struct]
pub struct Navigator { pub struct Navigator {
@ -45,8 +38,6 @@ pub struct Navigator {
permissions: MutNullableDom<Permissions>, permissions: MutNullableDom<Permissions>,
mediasession: MutNullableDom<MediaSession>, mediasession: MutNullableDom<MediaSession>,
gpu: MutNullableDom<GPU>, gpu: MutNullableDom<GPU>,
#[ignore_malloc_size_of = "Defined in wgpu"]
gpu_id_hub: RefCell<Identities>,
} }
impl Navigator { impl Navigator {
@ -63,7 +54,6 @@ impl Navigator {
permissions: Default::default(), permissions: Default::default(),
mediasession: Default::default(), mediasession: Default::default(),
gpu: Default::default(), gpu: Default::default(),
gpu_id_hub: RefCell::new(Identities::new()),
} }
} }
@ -76,32 +66,6 @@ impl Navigator {
} }
} }
impl Navigator {
pub fn create_adapter_ids(&self) -> SmallVec<[AdapterId; 4]> {
self.gpu_id_hub.borrow_mut().create_adapter_ids()
}
pub fn create_device_id(&self, backend: Backend) -> DeviceId {
self.gpu_id_hub.borrow_mut().create_device_id(backend)
}
pub fn create_buffer_id(&self, backend: Backend) -> BufferId {
self.gpu_id_hub.borrow_mut().create_buffer_id(backend)
}
pub fn create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId {
self.gpu_id_hub
.borrow_mut()
.create_bind_group_layout_id(backend)
}
pub fn create_pipeline_layout_id(&self, backend: Backend) -> PipelineLayoutId {
self.gpu_id_hub
.borrow_mut()
.create_pipeline_layout_id(backend)
}
}
impl NavigatorMethods for Navigator { impl NavigatorMethods for Navigator {
// https://html.spec.whatwg.org/multipage/#dom-navigator-product // https://html.spec.whatwg.org/multipage/#dom-navigator-product
fn Product(&self) -> DOMString { fn Product(&self) -> DOMString {