aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/codegen/Bindings.conf4
-rw-r--r--components/script/dom/bindings/trace.rs5
-rw-r--r--components/script/dom/gpuadapter.rs64
-rw-r--r--components/script/dom/gpudevice.rs91
-rw-r--r--components/script/dom/identityhub.rs4
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/navigator.rs6
-rw-r--r--components/script/dom/webidls/GPUAdapter.webidl22
-rw-r--r--components/script/dom/webidls/GPUDevice.webidl31
-rw-r--r--components/script/dom/webidls/GPUObjectBase.webidl13
-rw-r--r--components/webgpu/lib.rs45
11 files changed, 270 insertions, 16 deletions
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf
index 5dc9e141ed5..31a041945fd 100644
--- a/components/script/dom/bindings/codegen/Bindings.conf
+++ b/components/script/dom/bindings/codegen/Bindings.conf
@@ -138,6 +138,10 @@ DOMInterfaces = {
'GPU': {
'inCompartments': ['RequestAdapter'],
+},
+
+'GPUAdapter': {
+ 'inCompartments': ['RequestDevice'],
}
}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 65717bb81bf..1cefa9eeed8 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -146,7 +146,7 @@ use tendril::stream::LossyDecoder;
use tendril::{StrTendril, TendrilSink};
use time::{Duration, Timespec};
use uuid::Uuid;
-use webgpu::{WebGPU, WebGPUAdapter};
+use webgpu::{WebGPU, WebGPUAdapter, WebGPUDevice};
use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
use webxr_api::SwapChainId as WebXRSwapChainId;
@@ -504,9 +504,10 @@ 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!(RefCell<Identities>);
+unsafe_no_jsmanaged_fields!(WebGPU);
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
+unsafe_no_jsmanaged_fields!(WebGPUDevice);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs
index ec970439e8a..34b6fc38d45 100644
--- a/components/script/dom/gpuadapter.rs
+++ b/components/script/dom/gpuadapter.rs
@@ -2,16 +2,29 @@
* 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::compartments::InCompartment;
+use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{
+ self, GPUAdapterMethods, GPUDeviceDescriptor,
+};
+use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
+use crate::dom::bindings::error::Error;
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::reflector::DomObject;
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::dom::gpu::response_async;
+use crate::dom::gpu::AsyncWGPUListener;
+use crate::dom::gpudevice::GPUDevice;
+use crate::dom::promise::Promise;
+use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject};
use std::ptr::NonNull;
-use webgpu::WebGPUAdapter;
+use std::rc::Rc;
+use webgpu::{wgpu, WebGPUAdapter, WebGPURequest, WebGPUResponse};
#[dom_struct]
pub struct GPUAdapter {
@@ -60,4 +73,51 @@ impl GPUAdapterMethods for GPUAdapter {
fn Extensions(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
NonNull::new(self.extensions.get()).unwrap()
}
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice
+ fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InCompartment) -> Rc<Promise> {
+ let promise = Promise::new_in_current_compartment(&self.global(), comp);
+ let sender = response_async(&promise, self);
+ let desc = wgpu::DeviceDescriptor {
+ extensions: wgpu::Extensions {
+ anisotropic_filtering: descriptor.extensions.anisotropicFiltering,
+ },
+ limits: wgpu::Limits {
+ max_bind_groups: descriptor.limits.maxBindGroups,
+ },
+ };
+ if let Some(window) = self.global().downcast::<Window>() {
+ let id = window.Navigator().create_device_id();
+ 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())),
+ }
+ } else {
+ promise.reject_error(Error::Type("No WebGPU thread...".to_owned()))
+ };
+ promise
+ }
+}
+
+impl AsyncWGPUListener for GPUAdapter {
+ fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
+ match response {
+ WebGPUResponse::RequestDevice(device_id, _descriptor) => {
+ let device = GPUDevice::new(
+ &self.global(),
+ &self,
+ Heap::default(),
+ Heap::default(),
+ device_id,
+ );
+ promise.resolve_native(&device);
+ },
+ _ => promise.reject_error(Error::Type(
+ "Wrong response type from WebGPU thread...".to_owned(),
+ )),
+ }
+ }
}
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs
new file mode 100644
index 00000000000..d04ae97483a
--- /dev/null
+++ b/components/script/dom/gpudevice.rs
@@ -0,0 +1,91 @@
+/* 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::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
+use crate::dom::bindings::reflector::reflect_dom_object;
+use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::str::DOMString;
+use crate::dom::eventtarget::EventTarget;
+use crate::dom::globalscope::GlobalScope;
+use crate::dom::gpuadapter::GPUAdapter;
+use crate::script_runtime::JSContext as SafeJSContext;
+use dom_struct::dom_struct;
+use js::jsapi::{Heap, JSObject};
+use std::ptr::NonNull;
+use webgpu::WebGPUDevice;
+
+#[dom_struct]
+pub struct GPUDevice {
+ eventtarget: EventTarget,
+ adapter: Dom<GPUAdapter>,
+ #[ignore_malloc_size_of = "mozjs"]
+ extensions: Heap<*mut JSObject>,
+ #[ignore_malloc_size_of = "mozjs"]
+ limits: Heap<*mut JSObject>,
+ label: DomRefCell<Option<DOMString>>,
+ device: WebGPUDevice,
+}
+
+impl GPUDevice {
+ fn new_inherited(
+ adapter: &GPUAdapter,
+ extensions: Heap<*mut JSObject>,
+ limits: Heap<*mut JSObject>,
+ device: WebGPUDevice,
+ ) -> GPUDevice {
+ Self {
+ eventtarget: EventTarget::new_inherited(),
+ adapter: Dom::from_ref(adapter),
+ extensions,
+ limits,
+ label: DomRefCell::new(None),
+ device,
+ }
+ }
+
+ #[allow(unsafe_code)]
+ pub fn new(
+ global: &GlobalScope,
+ adapter: &GPUAdapter,
+ extensions: Heap<*mut JSObject>,
+ limits: Heap<*mut JSObject>,
+ device: WebGPUDevice,
+ ) -> DomRoot<GPUDevice> {
+ reflect_dom_object(
+ Box::new(GPUDevice::new_inherited(
+ adapter, extensions, limits, device,
+ )),
+ global,
+ GPUDeviceBinding::Wrap,
+ )
+ }
+}
+
+impl GPUDeviceMethods for GPUDevice {
+ /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-adapter
+ fn Adapter(&self) -> DomRoot<GPUAdapter> {
+ DomRoot::from_ref(&self.adapter)
+ }
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-extensions
+ fn Extensions(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
+ NonNull::new(self.extensions.get()).unwrap()
+ }
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-limits
+ fn Limits(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
+ NonNull::new(self.extensions.get()).unwrap()
+ }
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
+ fn GetLabel(&self) -> Option<DOMString> {
+ self.label.borrow().clone()
+ }
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
+ fn SetLabel(&self, value: Option<DOMString>) {
+ *self.label.borrow_mut() = value;
+ }
+}
diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs
index 489eaacc78d..6c79a3c5f46 100644
--- a/components/script/dom/identityhub.rs
+++ b/components/script/dom/identityhub.rs
@@ -44,4 +44,8 @@ impl Identities {
pub fn create_adapter_id(&mut self) -> AdapterId {
self.hub.adapters.alloc()
}
+
+ pub fn create_device_id(&mut self) -> DeviceId {
+ self.hub.devices.alloc()
+ }
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index d348633df88..bb1110389c6 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -317,6 +317,7 @@ pub mod gamepadlist;
pub mod globalscope;
pub mod gpu;
pub mod gpuadapter;
+pub mod gpudevice;
pub mod hashchangeevent;
pub mod headers;
pub mod history;
diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs
index 9121f7ef54d..c813af4ea99 100644
--- a/components/script/dom/navigator.rs
+++ b/components/script/dom/navigator.rs
@@ -26,7 +26,7 @@ use crate::dom::xr::XR;
use dom_struct::dom_struct;
use std::cell::RefCell;
use std::rc::Rc;
-use webgpu::wgpu::AdapterId;
+use webgpu::wgpu::{AdapterId, DeviceId};
#[dom_struct]
pub struct Navigator {
@@ -76,6 +76,10 @@ impl Navigator {
pub fn create_adapter_id(&self) -> AdapterId {
self.gpu_id_hub.borrow_mut().create_adapter_id()
}
+
+ pub fn create_device_id(&self) -> DeviceId {
+ self.gpu_id_hub.borrow_mut().create_device_id()
+ }
}
impl NavigatorMethods for Navigator {
diff --git a/components/script/dom/webidls/GPUAdapter.webidl b/components/script/dom/webidls/GPUAdapter.webidl
index 0c2118a5f56..cc664fabffa 100644
--- a/components/script/dom/webidls/GPUAdapter.webidl
+++ b/components/script/dom/webidls/GPUAdapter.webidl
@@ -10,5 +10,25 @@ interface GPUAdapter {
//readonly attribute GPULimits limits; Don’t expose higher limits for now.
// May reject with DOMException // TODO: DOMException("OperationError")?
- // Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
+ Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
+};
+
+dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
+ GPUExtensions extensions = {};
+ GPULimits limits = {};
+};
+
+dictionary GPUExtensions {
+ boolean anisotropicFiltering = false;
+};
+
+dictionary GPULimits {
+ unsigned long maxBindGroups = 4;
+ unsigned long maxDynamicUniformBuffersPerPipelineLayout = 8;
+ unsigned long maxDynamicStorageBuffersPerPipelineLayout = 4;
+ unsigned long maxSampledTexturesPerShaderStage = 16;
+ unsigned long maxSamplersPerShaderStage = 16;
+ unsigned long maxStorageBuffersPerShaderStage = 4;
+ unsigned long maxStorageTexturesPerShaderStage = 4;
+ unsigned long maxUniformBuffersPerShaderStage = 12;
};
diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl
new file mode 100644
index 00000000000..1cd441e6ef3
--- /dev/null
+++ b/components/script/dom/webidls/GPUDevice.webidl
@@ -0,0 +1,31 @@
+/* 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/#gpudevice
+[Exposed=(Window, DedicatedWorker)/*, Serializable */, Pref="dom.webgpu.enabled"]
+interface GPUDevice : EventTarget {
+ readonly attribute GPUAdapter adapter;
+ readonly attribute object extensions;
+ readonly attribute object limits;
+
+ /*GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
+ GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
+ Promise<GPUMappedBuffer> createBufferMappedAsync(GPUBufferDescriptor descriptor);
+ GPUTexture createTexture(GPUTextureDescriptor descriptor);
+ GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
+
+ GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
+ GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
+ GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
+
+ GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
+ GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
+ GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
+
+ GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
+ GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
+
+ GPUQueue getQueue();*/
+};
+GPUDevice includes GPUObjectBase;
diff --git a/components/script/dom/webidls/GPUObjectBase.webidl b/components/script/dom/webidls/GPUObjectBase.webidl
new file mode 100644
index 00000000000..c9a35992fb8
--- /dev/null
+++ b/components/script/dom/webidls/GPUObjectBase.webidl
@@ -0,0 +1,13 @@
+/* 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/#gpuobjectbase
+[Exposed=(Window)]
+interface mixin GPUObjectBase {
+ attribute DOMString? label;
+};
+
+dictionary GPUObjectDescriptorBase {
+ DOMString? label;
+};
diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs
index 6439fc9f5e9..83df6d77e60 100644
--- a/components/webgpu/lib.rs
+++ b/components/webgpu/lib.rs
@@ -12,12 +12,12 @@ 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::{adapter_get_info, adapter_request_device};
#[derive(Debug, Deserialize, Serialize)]
pub enum WebGPUResponse {
RequestAdapter(String, WebGPUAdapter),
- RequestDevice,
+ RequestDevice(WebGPUDevice, wgpu::DeviceDescriptor),
}
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
@@ -29,7 +29,12 @@ pub enum WebGPURequest {
wgpu::RequestAdapterOptions,
wgpu::AdapterId,
),
- RequestDevice,
+ RequestDevice(
+ IpcSender<WebGPUResponseResult>,
+ WebGPUAdapter,
+ wgpu::DeviceDescriptor,
+ wgpu::DeviceId,
+ ),
Exit(IpcSender<()>),
}
@@ -124,7 +129,18 @@ impl WGPU {
)
}
},
- WebGPURequest::RequestDevice => {},
+ WebGPURequest::RequestDevice(sender, adapter, descriptor, id) => {
+ let _output = gfx_select!(id => adapter_request_device(&self.global, adapter.0, &descriptor, id));
+ let device = WebGPUDevice(id);
+ if let Err(e) =
+ sender.send(Ok(WebGPUResponse::RequestDevice(device, descriptor)))
+ {
+ warn!(
+ "Failed to send response to WebGPURequest::RequestDevice ({})",
+ e
+ )
+ }
+ },
WebGPURequest::Exit(sender) => {
self.deinit();
if let Err(e) = sender.send(()) {
@@ -137,11 +153,20 @@ impl WGPU {
}
}
-#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
-pub struct WebGPUAdapter(pub wgpu::AdapterId);
+macro_rules! webgpu_resource {
+ ($name:ident, $id:ty) => {
+ #[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
+ pub struct $name(pub $id);
-impl MallocSizeOf for WebGPUAdapter {
- fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
- 0
- }
+ impl MallocSizeOf for $name {
+ fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
+ 0
+ }
+ }
+
+ impl Eq for $name {}
+ };
}
+
+webgpu_resource!(WebGPUAdapter, wgpu::AdapterId);
+webgpu_resource!(WebGPUDevice, wgpu::DeviceId);