aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--components/script/dom/bindings/trace.rs4
-rw-r--r--components/script/dom/globalscope.rs6
-rw-r--r--components/script/dom/gpubindgroup.rs58
-rw-r--r--components/script/dom/gpubuffer.rs14
-rw-r--r--components/script/dom/gpudevice.rs67
-rw-r--r--components/script/dom/identityhub.rs22
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webidls/GPUBindGroup.webidl31
-rw-r--r--components/script/dom/webidls/GPUDevice.webidl4
-rw-r--r--components/webgpu/lib.rs27
11 files changed, 227 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 980fe6f20fb..872c4f62549 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6764,7 +6764,7 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.1.0"
-source = "git+https://github.com/gfx-rs/wgpu#881222a9477036e9e3504045452d88abfe5ae177"
+source = "git+https://github.com/gfx-rs/wgpu#d4a46cb60e71d6b108e9052cc581e52e44a16a44"
dependencies = [
"arrayvec 0.5.1",
"battery",
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index ffd4a4952d0..471d890c80b 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -152,7 +152,8 @@ use tendril::{StrTendril, TendrilSink};
use time::{Duration, Timespec, Tm};
use uuid::Uuid;
use webgpu::{
- WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, WebGPUPipelineLayout,
+ WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice,
+ WebGPUPipelineLayout,
};
use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
@@ -532,6 +533,7 @@ unsafe_no_jsmanaged_fields!(WebGPU);
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
unsafe_no_jsmanaged_fields!(WebGPUBuffer);
+unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(GPUBufferState);
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index f8427ffd083..aa0bfee1b79 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -98,7 +98,7 @@ use std::sync::Arc;
use time::{get_time, Timespec};
use uuid::Uuid;
use webgpu::wgpu::{
- id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
+ id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
Backend,
};
@@ -2105,6 +2105,10 @@ impl GlobalScope {
self.gpu_id_hub.borrow_mut().create_adapter_ids()
}
+ pub fn wgpu_create_bind_group_id(&self, backend: Backend) -> BindGroupId {
+ self.gpu_id_hub.borrow_mut().create_bind_group_id(backend)
+ }
+
pub fn wgpu_create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId {
self.gpu_id_hub
.borrow_mut()
diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs
new file mode 100644
index 00000000000..c14ca7a23b5
--- /dev/null
+++ b/components/script/dom/gpubindgroup.rs
@@ -0,0 +1,58 @@
+/* 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::GPUBindGroupBinding::{
+ GPUBindGroupBinding, GPUBindGroupMethods,
+};
+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 dom_struct::dom_struct;
+use std::cell::Cell;
+use webgpu::WebGPUBindGroup;
+
+#[dom_struct]
+pub struct GPUBindGroup {
+ reflector_: Reflector,
+ label: DomRefCell<Option<DOMString>>,
+ bind_group: WebGPUBindGroup,
+ valid: Cell<bool>,
+}
+
+impl GPUBindGroup {
+ fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> GPUBindGroup {
+ Self {
+ reflector_: Reflector::new(),
+ label: DomRefCell::new(None),
+ bind_group,
+ valid: Cell::new(valid),
+ }
+ }
+
+ pub fn new(
+ global: &GlobalScope,
+ bind_group: WebGPUBindGroup,
+ valid: bool,
+ ) -> DomRoot<GPUBindGroup> {
+ reflect_dom_object(
+ Box::new(GPUBindGroup::new_inherited(bind_group, valid)),
+ global,
+ GPUBindGroupBinding::Wrap,
+ )
+ }
+}
+
+impl GPUBindGroupMethods for GPUBindGroup {
+ /// 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/gpubuffer.rs b/components/script/dom/gpubuffer.rs
index 160ef6cf79c..8cc9bc52249 100644
--- a/components/script/dom/gpubuffer.rs
+++ b/components/script/dom/gpubuffer.rs
@@ -79,6 +79,20 @@ impl GPUBuffer {
}
}
+impl GPUBuffer {
+ pub fn id(&self) -> WebGPUBuffer {
+ self.buffer
+ }
+
+ pub fn size(&self) -> GPUBufferSize {
+ self.size
+ }
+
+ pub fn usage(&self) -> u32 {
+ self.usage
+ }
+}
+
impl Drop for GPUBuffer {
fn drop(&mut self) {
self.Destroy()
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs
index de3efec8117..4c576c37e8b 100644
--- a/components/script/dom/gpudevice.rs
+++ b/components/script/dom/gpudevice.rs
@@ -6,6 +6,7 @@
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits;
+use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType,
};
@@ -18,6 +19,7 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter;
+use crate::dom::gpubindgroup::GPUBindGroup;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpupipelinelayout::GPUPipelineLayout;
@@ -29,7 +31,10 @@ use js::jsval::{JSVal, ObjectValue};
use js::typedarray::{ArrayBuffer, CreateWith};
use std::collections::{HashMap, HashSet};
use std::ptr::{self, NonNull};
-use webgpu::wgpu::binding_model::{BindGroupLayoutBinding, BindingType, ShaderStage};
+use webgpu::wgpu::binding_model::{
+ BindGroupBinding, BindGroupLayoutBinding, BindingResource, BindingType, BufferBinding,
+ ShaderStage,
+};
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
@@ -463,4 +468,64 @@ impl GPUDeviceMethods for GPUDevice {
let pipeline_layout = receiver.recv().unwrap();
GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid)
}
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup
+ fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot<GPUBindGroup> {
+ let alignment: u64 = 256;
+ let mut valid = descriptor.layout.bindings().len() == descriptor.bindings.len();
+
+ valid &= descriptor.bindings.iter().all(|bind| {
+ let buffer_size = bind.resource.buffer.size();
+ let resource_size = bind.resource.size.unwrap_or(buffer_size);
+ let length = bind.resource.offset.checked_add(resource_size);
+ let usage = BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap();
+
+ length.is_some() &&
+ buffer_size >= length.unwrap() && // check buffer OOB
+ bind.resource.offset % alignment == 0 && // check alignment
+ bind.resource.offset < buffer_size && // on Vulkan offset must be less than size of buffer
+ descriptor.layout.bindings().iter().any(|layout_bind| {
+ let ty = match layout_bind.type_ {
+ GPUBindingType::Storage_buffer => BufferUsage::STORAGE,
+ // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ,
+ GPUBindingType::Uniform_buffer => BufferUsage::UNIFORM,
+ _ => unimplemented!(),
+ };
+ // binding must be present in layout
+ layout_bind.binding == bind.binding &&
+ // binding must contain one buffer of its type
+ usage.contains(ty)
+ })
+ });
+
+ let bindings = descriptor
+ .bindings
+ .iter()
+ .map(|bind| BindGroupBinding {
+ binding: bind.binding,
+ resource: BindingResource::Buffer(BufferBinding {
+ buffer: bind.resource.buffer.id().0,
+ offset: bind.resource.offset,
+ size: bind.resource.size.unwrap_or(bind.resource.buffer.size()),
+ }),
+ })
+ .collect::<Vec<_>>();
+ let (sender, receiver) = ipc::channel().unwrap();
+ let id = self
+ .global()
+ .wgpu_create_bind_group_id(self.device.0.backend());
+ self.channel
+ .0
+ .send(WebGPURequest::CreateBindGroup(
+ sender,
+ self.device,
+ id,
+ descriptor.layout.id(),
+ bindings,
+ ))
+ .expect("Failed to create WebGPU PipelineLayout");
+
+ let bind_group = receiver.recv().unwrap();
+ GPUBindGroup::new(&self.global(), bind_group, valid)
+ }
}
diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs
index d0999d1848d..311428893c0 100644
--- a/components/script/dom/identityhub.rs
+++ b/components/script/dom/identityhub.rs
@@ -5,7 +5,7 @@
use smallvec::SmallVec;
use webgpu::wgpu::{
hub::IdentityManager,
- id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
+ id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
Backend,
};
@@ -14,6 +14,7 @@ pub struct IdentityHub {
adapters: IdentityManager,
devices: IdentityManager,
buffers: IdentityManager,
+ bind_groups: IdentityManager,
bind_group_layouts: IdentityManager,
pipeline_layouts: IdentityManager,
backend: Backend,
@@ -25,6 +26,7 @@ impl IdentityHub {
adapters: IdentityManager::default(),
devices: IdentityManager::default(),
buffers: IdentityManager::default(),
+ bind_groups: IdentityManager::default(),
bind_group_layouts: IdentityManager::default(),
pipeline_layouts: IdentityManager::default(),
backend,
@@ -43,6 +45,10 @@ impl IdentityHub {
self.buffers.alloc(self.backend)
}
+ fn create_bind_group_id(&mut self) -> BindGroupId {
+ self.bind_groups.alloc(self.backend)
+ }
+
fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId {
self.bind_group_layouts.alloc(self.backend)
}
@@ -126,6 +132,20 @@ impl Identities {
self.select(backend).create_buffer_id()
}
+ pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId {
+ match backend {
+ #[cfg(any(target_os = "linux", target_os = "windows"))]
+ Backend::Vulkan => self.vk_hub.create_bind_group_id(),
+ #[cfg(target_os = "windows")]
+ Backend::Dx12 => self.dx12_hub.create_bind_group_id(),
+ #[cfg(target_os = "windows")]
+ Backend::Dx11 => self.dx11_hub.create_bind_group_id(),
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ Backend::Metal => self.metal_hub.create_bind_group_id(),
+ _ => self.dummy_hub.create_bind_group_id(),
+ }
+ }
+
pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId {
self.select(backend).create_bind_group_layout_id()
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 2550eeda007..282d3b66d60 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -318,6 +318,7 @@ pub mod gamepadlist;
pub mod globalscope;
pub mod gpu;
pub mod gpuadapter;
+pub mod gpubindgroup;
pub mod gpubindgrouplayout;
pub mod gpubuffer;
pub mod gpubufferusage;
diff --git a/components/script/dom/webidls/GPUBindGroup.webidl b/components/script/dom/webidls/GPUBindGroup.webidl
new file mode 100644
index 00000000000..537fda29a63
--- /dev/null
+++ b/components/script/dom/webidls/GPUBindGroup.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/#gpubindgrouplayout
+[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
+interface GPUBindGroup {
+};
+GPUBindGroup includes GPUObjectBase;
+
+dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
+ required GPUBindGroupLayout layout;
+ required sequence<GPUBindGroupBindings> bindings;
+};
+
+typedef /*(GPUSampler or GPUTextureView or*/ GPUBufferBindings/*)*/ GPUBindingResource;
+
+// Note: Servo codegen doesn't like the name `GPUBindGroupBinding` because it's already occupied
+// dictionary GPUBindGroupBinding {
+dictionary GPUBindGroupBindings {
+ required unsigned long binding;
+ required GPUBindingResource resource;
+};
+
+// Note: Servo codegen doesn't like the name `GPUBufferBinding` because it's already occupied
+// dictionary GPUBufferBinding {
+dictionary GPUBufferBindings {
+ required GPUBuffer buffer;
+ GPUBufferSize offset = 0;
+ GPUBufferSize size;
+};
diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl
index 85e8a3ea633..1966c9b1e92 100644
--- a/components/script/dom/webidls/GPUDevice.webidl
+++ b/components/script/dom/webidls/GPUDevice.webidl
@@ -17,9 +17,9 @@ interface GPUDevice : EventTarget {
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
- /*GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
+ GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
- GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
+ /*GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs
index 8d223a12366..e3548a158ca 100644
--- a/components/webgpu/lib.rs
+++ b/components/webgpu/lib.rs
@@ -5,8 +5,6 @@
#[macro_use]
extern crate log;
#[macro_use]
-extern crate serde;
-#[macro_use]
pub extern crate wgpu_core as wgpu;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
@@ -48,6 +46,13 @@ pub enum WebGPURequest {
wgpu::id::BufferId,
wgpu::resource::BufferDescriptor,
),
+ CreateBindGroup(
+ IpcSender<WebGPUBindGroup>,
+ WebGPUDevice,
+ wgpu::id::BindGroupId,
+ WebGPUBindGroupLayout,
+ Vec<wgpu::binding_model::BindGroupBinding>,
+ ),
CreateBindGroupLayout(
IpcSender<WebGPUBindGroupLayout>,
WebGPUDevice,
@@ -232,6 +237,23 @@ impl WGPU {
let global = &self.global;
gfx_select!(buffer.0 => global.buffer_destroy(buffer.0));
},
+ WebGPURequest::CreateBindGroup(sender, device, id, layout_id, bindings) => {
+ let global = &self.global;
+ let descriptor = wgpu_core::binding_model::BindGroupDescriptor {
+ layout: layout_id.0,
+ bindings: bindings.as_ptr(),
+ bindings_length: bindings.len(),
+ };
+ let bg_id = gfx_select!(id => global.device_create_bind_group(device.0, &descriptor, id));
+ let bind_group = WebGPUBindGroup(bg_id);
+
+ if let Err(e) = sender.send(bind_group) {
+ warn!(
+ "Failed to send response to WebGPURequest::CreateBindGroup ({})",
+ e
+ )
+ }
+ },
WebGPURequest::CreateBindGroupLayout(sender, device, id, bindings) => {
let global = &self.global;
let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor {
@@ -294,5 +316,6 @@ macro_rules! webgpu_resource {
webgpu_resource!(WebGPUAdapter, wgpu::id::AdapterId);
webgpu_resource!(WebGPUDevice, wgpu::id::DeviceId);
webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
+webgpu_resource!(WebGPUBindGroup, wgpu::id::BindGroupId);
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId);