mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #25637 - szeged:wgpu_crete_bind_group, r=jdm
Initial implementation of GPUBindGroup for WebGPU Added WebIDL bindings for `GPUBindGroup`. Implemented the `createBindGroup` function of `GPUDevice` Renamed `GPUBindGroupBinding` to `GPUBindGroupBindings` and `GPUBufferBinding` to `GPUBufferBindings` in the WebIDL, because these names are already occupied. <!-- 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 addresses a part of #24706 cc @kvark @jdm @zakorgy <!-- 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. -->
This commit is contained in:
commit
1352e7188a
11 changed files with 227 additions and 9 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
58
components/script/dom/gpubindgroup.rs
Normal file
58
components/script/dom/gpubindgroup.rs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
31
components/script/dom/webidls/GPUBindGroup.webidl
Normal file
31
components/script/dom/webidls/GPUBindGroup.webidl
Normal file
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue