From 9cf007472b364ea60445e6aaa5e91f67ef3d1894 Mon Sep 17 00:00:00 2001 From: Istvan Miklos Date: Mon, 6 Jan 2020 14:04:38 +0100 Subject: [PATCH] Initial implementation of GPUBindGroupLayout for WebGPU Added WebIDL bindings for `GPUBindGroupLayout`, `GPUBindGroupLayoutDescriptor`, `GPUBindingType`, `GPUShaderStage` and `GPUBindGroupLayoutBinding` (Note: The servo's codegen doesn't like the name, because its already occupied). Implemented the `createBindGroupLayout` function of `GPUDevice`. --- Cargo.lock | 25 ++- components/script/dom/bindings/trace.rs | 3 +- components/script/dom/gpubindgrouplayout.rs | 75 ++++++++ components/script/dom/gpudevice.rs | 180 ++++++++++++++++++ components/script/dom/gpushaderstage.rs | 11 ++ components/script/dom/identityhub.rs | 24 ++- components/script/dom/mod.rs | 2 + components/script/dom/navigator.rs | 8 +- .../dom/webidls/GPUBindGroupLayout.webidl | 34 ++++ .../script/dom/webidls/GPUDevice.webidl | 8 +- .../script/dom/webidls/GPUShaderStage.webidl | 13 ++ components/webgpu/lib.rs | 23 +++ servo-tidy.toml | 2 + 13 files changed, 397 insertions(+), 11 deletions(-) create mode 100644 components/script/dom/gpubindgrouplayout.rs create mode 100644 components/script/dom/gpushaderstage.rs create mode 100644 components/script/dom/webidls/GPUBindGroupLayout.webidl create mode 100644 components/script/dom/webidls/GPUShaderStage.webidl diff --git a/Cargo.lock b/Cargo.lock index 06faf8677f9b..d75034fc726a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3904,7 +3904,25 @@ version = "0.2.0" source = "git+https://github.com/servo/webrender#edac864107cf43732ec66a9d3288e869a70ce1de" dependencies = [ "euclid", - "peek-poke-derive", + "peek-poke-derive 0.2.1", +] + +[[package]] +name = "peek-poke" +version = "0.2.0" +source = "git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075#969bd7fe2be1a83f87916dc8b388c63cfd457075" +dependencies = [ + "peek-poke-derive 0.2.0", +] + +[[package]] +name = "peek-poke-derive" +version = "0.2.0" +source = "git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075#969bd7fe2be1a83f87916dc8b388c63cfd457075" +dependencies = [ + "proc-macro2 1.0.1", + "quote 1.0.2", + "syn 1.0.3", ] [[package]] @@ -6456,7 +6474,7 @@ dependencies = [ "derive_more 0.13.0", "euclid", "malloc_size_of_derive", - "peek-poke", + "peek-poke 0.2.0 (git+https://github.com/servo/webrender)", "serde", "serde_bytes", "serde_derive", @@ -6545,7 +6563,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.1.0" -source = "git+https://github.com/gfx-rs/wgpu#c0fa61a064c3572ee60d6c4c6a59ca0571394200" +source = "git+https://github.com/gfx-rs/wgpu#881222a9477036e9e3504045452d88abfe5ae177" dependencies = [ "arrayvec 0.5.1", "battery", @@ -6560,6 +6578,7 @@ dependencies = [ "gfx-hal", "log", "parking_lot", + "peek-poke 0.2.0 (git+https://github.com/kvark/peek-poke?rev=969bd7fe2be1a83f87916dc8b388c63cfd457075)", "rendy-descriptor", "rendy-memory", "serde", diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 36a12d023aff..bdcf99197524 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -151,7 +151,7 @@ use tendril::stream::LossyDecoder; use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec, Tm}; use uuid::Uuid; -use webgpu::{WebGPU, WebGPUAdapter, WebGPUBuffer, WebGPUDevice}; +use webgpu::{WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice}; use webrender_api::{DocumentId, ImageKey}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webxr_api::SwapChainId as WebXRSwapChainId; @@ -530,6 +530,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!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(GPUBufferState); unsafe_no_jsmanaged_fields!(WebXRSwapChainId); unsafe_no_jsmanaged_fields!(MediaList); diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs new file mode 100644 index 000000000000..7669f0e5f2d4 --- /dev/null +++ b/components/script/dom/gpubindgrouplayout.rs @@ -0,0 +1,75 @@ +/* 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::GPUBindGroupLayoutBinding::{ + self, GPUBindGroupLayoutBindings, GPUBindGroupLayoutMethods, +}; +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::{WebGPU, WebGPUBindGroupLayout}; + +#[dom_struct] +pub struct GPUBindGroupLayout { + reflector_: Reflector, + label: DomRefCell>, + bind_group_layout: WebGPUBindGroupLayout, + #[ignore_malloc_size_of = "defined in webgpu"] + bindings: Vec, + #[ignore_malloc_size_of = "defined in webgpu"] + channel: WebGPU, + valid: Cell, +} + +impl GPUBindGroupLayout { + fn new_inherited( + channel: WebGPU, + bind_group_layout: WebGPUBindGroupLayout, + bindings: Vec, + valid: bool, + ) -> GPUBindGroupLayout { + Self { + reflector_: Reflector::new(), + channel, + label: DomRefCell::new(None), + bind_group_layout, + bindings, + valid: Cell::new(valid), + } + } + pub fn new( + global: &GlobalScope, + channel: WebGPU, + bind_group_layout: WebGPUBindGroupLayout, + bindings: Vec, + valid: bool, + ) -> DomRoot { + reflect_dom_object( + Box::new(GPUBindGroupLayout::new_inherited( + channel, + bind_group_layout, + bindings, + valid, + )), + global, + GPUBindGroupLayoutBinding::Wrap, + ) + } +} + +impl GPUBindGroupLayoutMethods for GPUBindGroupLayout { + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn GetLabel(&self) -> Option { + self.label.borrow().clone() + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn SetLabel(&self, value: Option) { + *self.label.borrow_mut() = value; + } +} diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 371643b6027d..d2d2b2013d82 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -5,6 +5,10 @@ #![allow(unsafe_code)] use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ + GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType, +}; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods}; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; @@ -15,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::gpubindgrouplayout::GPUBindGroupLayout; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::window::Window; use crate::script_runtime::JSContext as SafeJSContext; @@ -23,7 +28,9 @@ use ipc_channel::ipc; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, ObjectValue, UndefinedValue}; 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::resource::{BufferDescriptor, BufferUsage}; use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest}; @@ -229,4 +236,177 @@ impl GPUDeviceMethods for GPUDevice { self.resolve_create_buffer_mapped(cx, buffer, array_buffer, wgpu_descriptor, valid) } } + + /// https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout + fn CreateBindGroupLayout( + &self, + descriptor: &GPUBindGroupLayoutDescriptor, + ) -> DomRoot { + #[derive(Clone)] + struct MaxLimits { + max_uniform_buffers_per_shader_stage: i32, + max_storage_buffers_per_shader_stage: i32, + max_sampled_textures_per_shader_stage: i32, + max_storage_textures_per_shader_stage: i32, + max_samplers_per_shader_stage: i32, + } + let mut storeBindings = HashSet::new(); + // TODO: We should have these limits on device creation + let limits = GPULimits::empty(); + + let mut validation_map = HashMap::new(); + let maxLimits = MaxLimits { + max_uniform_buffers_per_shader_stage: limits.maxUniformBuffersPerShaderStage as i32, + max_storage_buffers_per_shader_stage: limits.maxStorageBuffersPerShaderStage as i32, + max_sampled_textures_per_shader_stage: limits.maxSampledTexturesPerShaderStage as i32, + max_storage_textures_per_shader_stage: limits.maxStorageTexturesPerShaderStage as i32, + max_samplers_per_shader_stage: limits.maxSamplersPerShaderStage as i32, + }; + validation_map.insert( + webgpu::wgpu::binding_model::ShaderStage::VERTEX, + maxLimits.clone(), + ); + validation_map.insert( + webgpu::wgpu::binding_model::ShaderStage::FRAGMENT, + maxLimits.clone(), + ); + validation_map.insert( + webgpu::wgpu::binding_model::ShaderStage::COMPUTE, + maxLimits.clone(), + ); + let mut max_dynamic_uniform_buffers_per_pipeline_layout = + limits.maxDynamicUniformBuffersPerPipelineLayout as i32; + let mut max_dynamic_storage_buffers_per_pipeline_layout = + limits.maxDynamicStorageBuffersPerPipelineLayout as i32; + let mut valid = true; + + let bindings = descriptor + .bindings + .iter() + .map(|bind| { + // TODO: binding must be >= 0 + storeBindings.insert(bind.binding); + let visibility = match ShaderStage::from_bits(bind.visibility) { + Some(visibility) => visibility, + None => { + valid = false; + ShaderStage::from_bits(0).unwrap() + }, + }; + let ty = match bind.type_ { + GPUBindingType::Uniform_buffer => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_uniform_buffers_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + max_dynamic_uniform_buffers_per_pipeline_layout -= 1; + }; + BindingType::UniformBuffer + }, + GPUBindingType::Storage_buffer => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_storage_buffers_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + max_dynamic_storage_buffers_per_pipeline_layout -= 1; + }; + BindingType::StorageBuffer + }, + GPUBindingType::Readonly_storage_buffer => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_storage_buffers_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + max_dynamic_storage_buffers_per_pipeline_layout -= 1; + }; + BindingType::ReadonlyStorageBuffer + }, + GPUBindingType::Sampled_texture => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_sampled_textures_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + valid = false + }; + BindingType::SampledTexture + }, + GPUBindingType::Storage_texture => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_storage_textures_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + valid = false + }; + BindingType::StorageTexture + }, + GPUBindingType::Sampler => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_samplers_per_shader_stage -= 1; + } + if bind.hasDynamicOffset { + valid = false + }; + BindingType::Sampler + }, + }; + + BindGroupLayoutBinding { + binding: bind.binding, + visibility, + ty, + dynamic: bind.hasDynamicOffset, + multisampled: bind.multisampled, + texture_dimension: webgpu::wgpu::resource::TextureViewDimension::D2, // Use as default for now + } + }) + .collect::>(); + + // bindings are unique + valid &= storeBindings.len() == bindings.len(); + + // Ensure that values do not exceed the max limit for each ShaderStage. + valid &= validation_map.values().all(|stage| { + stage.max_uniform_buffers_per_shader_stage >= 0 && + stage.max_storage_buffers_per_shader_stage >= 0 && + stage.max_sampled_textures_per_shader_stage >= 0 && + stage.max_storage_textures_per_shader_stage >= 0 && + stage.max_samplers_per_shader_stage >= 0 + }); + + // DynamicValues does not exceed the max limit for the pipeline + valid &= max_dynamic_uniform_buffers_per_pipeline_layout >= 0 && + max_dynamic_storage_buffers_per_pipeline_layout >= 0; + + let (sender, receiver) = ipc::channel().unwrap(); + if let Some(window) = self.global().downcast::() { + let id = window + .Navigator() + .create_bind_group_layout_id(self.device.0.backend()); + self.channel + .0 + .send(WebGPURequest::CreateBindGroupLayout( + sender, + self.device, + id, + bindings.clone(), + )) + .expect("Failed to create WebGPU BindGroupLayout"); + } + let bgl = receiver.recv().unwrap(); + + let binds = descriptor + .bindings + .iter() + .map(|bind| GPUBindGroupLayoutBindings { + binding: bind.binding, + hasDynamicOffset: bind.hasDynamicOffset, + multisampled: bind.multisampled, + type_: bind.type_, + visibility: bind.visibility, + //texture_dimension: bind.texture_dimension + }) + .collect::>(); + + GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid) + } } diff --git a/components/script/dom/gpushaderstage.rs b/components/script/dom/gpushaderstage.rs new file mode 100644 index 000000000000..a9cd1d905891 --- /dev/null +++ b/components/script/dom/gpushaderstage.rs @@ -0,0 +1,11 @@ +/* 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::reflector::Reflector; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct GPUShaderStage { + reflector_: Reflector, +} diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index 64e4cad38677..91543d2ea3fd 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, BufferId, DeviceId}, + id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId}, Backend, }; @@ -14,6 +14,7 @@ pub struct IdentityHub { adapters: IdentityManager, devices: IdentityManager, buffers: IdentityManager, + bind_group_layouts: IdentityManager, backend: Backend, } @@ -23,6 +24,7 @@ impl IdentityHub { adapters: IdentityManager::default(), devices: IdentityManager::default(), buffers: IdentityManager::default(), + bind_group_layouts: IdentityManager::default(), backend, } } @@ -35,9 +37,13 @@ impl IdentityHub { self.devices.alloc(self.backend) } - pub fn create_buffer_id(&mut self) -> BufferId { + fn create_buffer_id(&mut self) -> BufferId { self.buffers.alloc(self.backend) } + + fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId { + self.bind_group_layouts.alloc(self.backend) + } } #[derive(Debug)] @@ -119,4 +125,18 @@ impl Identities { _ => self.dummy_hub.create_buffer_id(), } } + + pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId { + match backend { + #[cfg(any(target_os = "linux", target_os = "windows"))] + Backend::Vulkan => self.vk_hub.create_bind_group_layout_id(), + #[cfg(target_os = "windows")] + Backend::Dx12 => self.dx12_hub.create_bind_group_layout_id(), + #[cfg(target_os = "windows")] + Backend::Dx11 => self.dx11_hub.create_bind_group_layout_id(), + #[cfg(any(target_os = "ios", target_os = "macos"))] + Backend::Metal => self.metal_hub.create_bind_group_layout_id(), + _ => self.dummy_hub.create_bind_group_layout_id(), + } + } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 0fdf4a80b695..08f1f0812fb4 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -318,9 +318,11 @@ pub mod gamepadlist; pub mod globalscope; pub mod gpu; pub mod gpuadapter; +pub mod gpubindgrouplayout; pub mod gpubuffer; pub mod gpubufferusage; pub mod gpudevice; +pub mod gpushaderstage; pub mod hashchangeevent; pub mod headers; pub mod history; diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index 03c6b27d156c..3d04433bfcda 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -28,7 +28,7 @@ use smallvec::SmallVec; use std::cell::RefCell; use std::rc::Rc; use webgpu::wgpu::{ - id::{AdapterId, BufferId, DeviceId}, + id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId}, Backend, }; @@ -88,6 +88,12 @@ impl Navigator { 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) + } } impl NavigatorMethods for Navigator { diff --git a/components/script/dom/webidls/GPUBindGroupLayout.webidl b/components/script/dom/webidls/GPUBindGroupLayout.webidl new file mode 100644 index 000000000000..930a1dd84cc4 --- /dev/null +++ b/components/script/dom/webidls/GPUBindGroupLayout.webidl @@ -0,0 +1,34 @@ +/* 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 GPUBindGroupLayout { +}; +GPUBindGroupLayout includes GPUObjectBase; + +dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase { + required sequence bindings; +}; + +// Note: Servo codegen doesn't like the name `GPUBindGroupLayoutBinding` because it's already occupied +// dictionary GPUBindGroupLayoutBinding { +dictionary GPUBindGroupLayoutBindings { + required unsigned long binding; + required GPUShaderStageFlags visibility; + required GPUBindingType type; + //GPUTextureViewDimension textureDimension = "2d"; + //GPUTextureComponentType textureComponentType = "float"; + boolean multisampled = false; + boolean hasDynamicOffset = false; +}; + +enum GPUBindingType { + "uniform-buffer", + "storage-buffer", + "readonly-storage-buffer", + "sampler", + "sampled-texture", + "storage-texture" +}; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 965f7e1b7d57..512f9bf649f0 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -11,12 +11,12 @@ interface GPUDevice : EventTarget { GPUBuffer createBuffer(GPUBufferDescriptor descriptor); GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor); - /*Promise createBufferMappedAsync(GPUBufferDescriptor descriptor); - GPUTexture createTexture(GPUTextureDescriptor descriptor); - GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {}); + //Promise createBufferMappedAsync(GPUBufferDescriptor descriptor); + //GPUTexture createTexture(GPUTextureDescriptor descriptor); + //GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {}); GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); - GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); + /*GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); diff --git a/components/script/dom/webidls/GPUShaderStage.webidl b/components/script/dom/webidls/GPUShaderStage.webidl new file mode 100644 index 000000000000..27fcb550cc33 --- /dev/null +++ b/components/script/dom/webidls/GPUShaderStage.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/#typedefdef-gpushaderstageflags +[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] +interface GPUShaderStage { + const GPUShaderStageFlags VERTEX = 0x1; + const GPUShaderStageFlags FRAGMENT = 0x2; + const GPUShaderStageFlags COMPUTE = 0x4; +}; + +typedef unsigned long GPUShaderStageFlags; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index c177149c9c49..92d99f8a90ef 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -48,6 +48,12 @@ pub enum WebGPURequest { wgpu::id::BufferId, wgpu::resource::BufferDescriptor, ), + CreateBindGroupLayout( + IpcSender, + WebGPUDevice, + wgpu::id::BindGroupLayoutId, + Vec, + ), UnmapBuffer(WebGPUBuffer), DestroyBuffer(WebGPUBuffer), } @@ -220,6 +226,22 @@ impl WGPU { let global = &self.global; gfx_select!(buffer.0 => global.buffer_destroy(buffer.0)); }, + WebGPURequest::CreateBindGroupLayout(sender, device, id, bindings) => { + let global = &self.global; + let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor { + bindings: bindings.as_ptr(), + bindings_length: bindings.len(), + }; + let bgl_id = gfx_select!(id => global.device_create_bind_group_layout(device.0, &descriptor, id)); + let bgl = WebGPUBindGroupLayout(bgl_id); + + if let Err(e) = sender.send(bgl) { + warn!( + "Failed to send response to WebGPURequest::CreateBufferMapped ({})", + e + ) + } + }, WebGPURequest::Exit(sender) => { self.deinit(); if let Err(e) = sender.send(()) { @@ -250,3 +272,4 @@ macro_rules! webgpu_resource { webgpu_resource!(WebGPUAdapter, wgpu::id::AdapterId); webgpu_resource!(WebGPUDevice, wgpu::id::DeviceId); webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId); +webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId); diff --git a/servo-tidy.toml b/servo-tidy.toml index 4b65de58f042..eb00255d593e 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -33,6 +33,8 @@ packages = [ "gleam", "mach", "nix", + "peek-poke", + "peek-poke-derive", "wayland-sys", # https://github.com/servo/servo/pull/23288#issuecomment-494687746