diff options
author | Kunal Mohan <kunalmohan99@gmail.com> | 2020-08-19 16:44:26 +0530 |
---|---|---|
committer | Kunal Mohan <kunalmohan99@gmail.com> | 2020-08-19 16:44:26 +0530 |
commit | f082a507da2a09d579021f8b2f0930afdec74c24 (patch) | |
tree | f1c85fce90094949e38099218389cec164ce92c0 | |
parent | 8c576bb02b6424d6a7d0d02551face0b461c0e0e (diff) | |
download | servo-f082a507da2a09d579021f8b2f0930afdec74c24.tar.gz servo-f082a507da2a09d579021f8b2f0930afdec74c24.zip |
Implement GPUPipelineBase for implicit pipeline layouts
-rw-r--r-- | components/script/dom/gpucomputepipeline.rs | 37 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 54 | ||||
-rw-r--r-- | components/script/dom/gpupipelinelayout.rs | 21 | ||||
-rw-r--r-- | components/script/dom/gpurenderpipeline.rs | 32 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUComputePipeline.webidl | 7 | ||||
-rw-r--r-- | components/script/dom/webidls/GPURenderPipeline.webidl | 1 | ||||
-rw-r--r-- | components/webgpu/lib.rs | 49 |
7 files changed, 176 insertions, 25 deletions
diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs index 598c6a7caee..85d35997eed 100644 --- a/components/script/dom/gpucomputepipeline.rs +++ b/components/script/dom/gpucomputepipeline.rs @@ -3,28 +3,37 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineMethods; -use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::reflector::Reflector; +use crate::dom::bindings::error::{Error, Fallible}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use dom_struct::dom_struct; -use webgpu::WebGPUComputePipeline; +use std::string::String; +use webgpu::{WebGPUBindGroupLayout, WebGPUComputePipeline}; #[dom_struct] pub struct GPUComputePipeline { reflector_: Reflector, label: DomRefCell<Option<USVString>>, compute_pipeline: WebGPUComputePipeline, + bind_group_layouts: Vec<WebGPUBindGroupLayout>, } impl GPUComputePipeline { - fn new_inherited(compute_pipeline: WebGPUComputePipeline, label: Option<USVString>) -> Self { + fn new_inherited( + compute_pipeline: WebGPUComputePipeline, + label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, + ) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(label), compute_pipeline, + bind_group_layouts: bgls, } } @@ -32,9 +41,14 @@ impl GPUComputePipeline { global: &GlobalScope, compute_pipeline: WebGPUComputePipeline, label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, ) -> DomRoot<Self> { reflect_dom_object( - Box::new(GPUComputePipeline::new_inherited(compute_pipeline, label)), + Box::new(GPUComputePipeline::new_inherited( + compute_pipeline, + label, + bgls, + )), global, ) } @@ -56,4 +70,17 @@ impl GPUComputePipelineMethods for GPUComputePipeline { fn SetLabel(&self, value: Option<USVString>) { *self.label.borrow_mut() = value; } + + /// https://gpuweb.github.io/gpuweb/#dom-gpupipelinebase-getbindgrouplayout + fn GetBindGroupLayout(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> { + if index > self.bind_group_layouts.len() as u32 || index > GPULimits::empty().maxBindGroups + { + return Err(Error::Range(String::from("Index out of bounds"))); + } + return Ok(GPUBindGroupLayout::new( + &self.global(), + self.bind_group_layouts[index as usize], + None, + )); + } } diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 0cc2ac593e0..4ce23aa5728 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -7,6 +7,7 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit; use crate::dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; +use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{ GPUBindGroupDescriptor, GPUBindingResource, }; @@ -74,7 +75,9 @@ use std::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; use webgpu::wgpu::{ - binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res, + binding_model as wgpu_bind, command as wgpu_com, + id::{BindGroupLayoutId, PipelineLayoutId}, + pipeline as wgpu_pipe, resource as wgpu_res, }; use webgpu::{self, identity::WebGPUOpResult, wgt, ErrorScopeId, WebGPU, WebGPURequest}; @@ -279,6 +282,38 @@ impl GPUDevice { }) }) } + + fn get_pipeline_layout_data( + &self, + layout: &Option<DomRoot<GPUPipelineLayout>>, + ) -> ( + Option<PipelineLayoutId>, + Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>, + Vec<webgpu::WebGPUBindGroupLayout>, + ) { + if let Some(ref layout) = layout { + (Some(layout.id().0), None, layout.bind_group_layouts()) + } else { + let layout_id = self + .global() + .wgpu_id_hub() + .lock() + .create_pipeline_layout_id(self.device.0.backend()); + let max_bind_grps = GPULimits::empty().maxBindGroups; + let mut bgls = Vec::with_capacity(max_bind_grps as usize); + let mut bgl_ids = Vec::with_capacity(max_bind_grps as usize); + for _ in 0..max_bind_grps { + let bgl = self + .global() + .wgpu_id_hub() + .lock() + .create_bind_group_layout_id(self.device.0.backend()); + bgls.push(webgpu::WebGPUBindGroupLayout(bgl)); + bgl_ids.push(bgl); + } + (None, Some((layout_id, bgl_ids)), bgls) + } + } } impl GPUDeviceMethods for GPUDevice { @@ -552,11 +587,17 @@ impl GPUDeviceMethods for GPUDevice { )) .expect("Failed to create WebGPU PipelineLayout"); + let bgls = descriptor + .bindGroupLayouts + .iter() + .map(|each| each.id()) + .collect::<Vec<_>>(); let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id); GPUPipelineLayout::new( &self.global(), pipeline_layout, descriptor.parent.label.as_ref().cloned(), + bgls, ) } @@ -671,10 +712,11 @@ impl GPUDeviceMethods for GPUDevice { .create_compute_pipeline_id(self.device.0.backend()); let scope_id = self.use_current_scope(); + let (layout, implicit_ids, bgls) = self.get_pipeline_layout_data(&descriptor.parent.layout); let desc = wgpu_pipe::ComputePipelineDescriptor { label: convert_label(&descriptor.parent.parent), - layout: Some(descriptor.parent.layout.id().0), + layout, compute_stage: wgpu_pipe::ProgrammableStageDescriptor { module: descriptor.computeStage.module.id().0, entry_point: Cow::Owned(descriptor.computeStage.entryPoint.to_string()), @@ -689,6 +731,7 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, compute_pipeline_id, descriptor: desc, + implicit_ids, }, )) .expect("Failed to create WebGPU ComputePipeline"); @@ -698,6 +741,7 @@ impl GPUDeviceMethods for GPUDevice { &self.global(), compute_pipeline, descriptor.parent.parent.label.as_ref().cloned(), + bgls, ) } @@ -872,11 +916,12 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(), ); + let (layout, implicit_ids, bgls) = self.get_pipeline_layout_data(&descriptor.parent.layout); let desc = if valid { Some(wgpu_pipe::RenderPipelineDescriptor { label: convert_label(&descriptor.parent.parent), - layout: Some(descriptor.parent.layout.id().0), + layout, vertex_stage: wgpu_pipe::ProgrammableStageDescriptor { module: descriptor.vertexStage.module.id().0, entry_point: Cow::Owned(descriptor.vertexStage.entryPoint.to_string()), @@ -991,6 +1036,7 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, render_pipeline_id, descriptor: desc, + implicit_ids, }, )) .expect("Failed to create WebGPU render pipeline"); @@ -1000,8 +1046,8 @@ impl GPUDeviceMethods for GPUDevice { GPURenderPipeline::new( &self.global(), render_pipeline, - self.device, descriptor.parent.parent.label.as_ref().cloned(), + bgls, ) } diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index 7547adce843..563d0ca9220 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -9,21 +9,27 @@ use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; use dom_struct::dom_struct; -use webgpu::WebGPUPipelineLayout; +use webgpu::{WebGPUBindGroupLayout, WebGPUPipelineLayout}; #[dom_struct] pub struct GPUPipelineLayout { reflector_: Reflector, label: DomRefCell<Option<USVString>>, pipeline_layout: WebGPUPipelineLayout, + bind_group_layouts: Vec<WebGPUBindGroupLayout>, } impl GPUPipelineLayout { - fn new_inherited(pipeline_layout: WebGPUPipelineLayout, label: Option<USVString>) -> Self { + fn new_inherited( + pipeline_layout: WebGPUPipelineLayout, + label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, + ) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(label), pipeline_layout, + bind_group_layouts: bgls, } } @@ -31,9 +37,14 @@ impl GPUPipelineLayout { global: &GlobalScope, pipeline_layout: WebGPUPipelineLayout, label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, ) -> DomRoot<Self> { reflect_dom_object( - Box::new(GPUPipelineLayout::new_inherited(pipeline_layout, label)), + Box::new(GPUPipelineLayout::new_inherited( + pipeline_layout, + label, + bgls, + )), global, ) } @@ -43,6 +54,10 @@ impl GPUPipelineLayout { pub fn id(&self) -> WebGPUPipelineLayout { self.pipeline_layout } + + pub fn bind_group_layouts(&self) -> Vec<WebGPUBindGroupLayout> { + self.bind_group_layouts.clone() + } } impl GPUPipelineLayoutMethods for GPUPipelineLayout { diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs index bb618a248a9..b59ea0e8501 100644 --- a/components/script/dom/gpurenderpipeline.rs +++ b/components/script/dom/gpurenderpipeline.rs @@ -3,48 +3,51 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; use crate::dom::bindings::codegen::Bindings::GPURenderPipelineBinding::GPURenderPipelineMethods; -use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::reflector::Reflector; +use crate::dom::bindings::error::{Error, Fallible}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use dom_struct::dom_struct; -use webgpu::{WebGPUDevice, WebGPURenderPipeline}; +use std::string::String; +use webgpu::{WebGPUBindGroupLayout, WebGPURenderPipeline}; #[dom_struct] pub struct GPURenderPipeline { reflector_: Reflector, label: DomRefCell<Option<USVString>>, render_pipeline: WebGPURenderPipeline, - device: WebGPUDevice, + bind_group_layouts: Vec<WebGPUBindGroupLayout>, } impl GPURenderPipeline { fn new_inherited( render_pipeline: WebGPURenderPipeline, - device: WebGPUDevice, label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, ) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(label), render_pipeline, - device, + bind_group_layouts: bgls, } } pub fn new( global: &GlobalScope, render_pipeline: WebGPURenderPipeline, - device: WebGPUDevice, label: Option<USVString>, + bgls: Vec<WebGPUBindGroupLayout>, ) -> DomRoot<Self> { reflect_dom_object( Box::new(GPURenderPipeline::new_inherited( render_pipeline, - device, label, + bgls, )), global, ) @@ -67,4 +70,17 @@ impl GPURenderPipelineMethods for GPURenderPipeline { fn SetLabel(&self, value: Option<USVString>) { *self.label.borrow_mut() = value; } + + /// https://gpuweb.github.io/gpuweb/#dom-gpupipelinebase-getbindgrouplayout + fn GetBindGroupLayout(&self, index: u32) -> Fallible<DomRoot<GPUBindGroupLayout>> { + if index > self.bind_group_layouts.len() as u32 || index > GPULimits::empty().maxBindGroups + { + return Err(Error::Range(String::from("Index out of bounds"))); + } + return Ok(GPUBindGroupLayout::new( + &self.global(), + self.bind_group_layouts[index as usize], + None, + )); + } } diff --git a/components/script/dom/webidls/GPUComputePipeline.webidl b/components/script/dom/webidls/GPUComputePipeline.webidl index 671c36ad351..a7599a13803 100644 --- a/components/script/dom/webidls/GPUComputePipeline.webidl +++ b/components/script/dom/webidls/GPUComputePipeline.webidl @@ -7,9 +7,10 @@ interface GPUComputePipeline { }; GPUComputePipeline includes GPUObjectBase; +GPUComputePipeline includes GPUPipelineBase; dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { - required GPUPipelineLayout layout; + GPUPipelineLayout layout; }; dictionary GPUProgrammableStageDescriptor { @@ -20,3 +21,7 @@ dictionary GPUProgrammableStageDescriptor { dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase { required GPUProgrammableStageDescriptor computeStage; }; + +interface mixin GPUPipelineBase { + [Throws] GPUBindGroupLayout getBindGroupLayout(unsigned long index); +}; diff --git a/components/script/dom/webidls/GPURenderPipeline.webidl b/components/script/dom/webidls/GPURenderPipeline.webidl index a25890112fc..7def381780a 100644 --- a/components/script/dom/webidls/GPURenderPipeline.webidl +++ b/components/script/dom/webidls/GPURenderPipeline.webidl @@ -7,6 +7,7 @@ interface GPURenderPipeline { }; GPURenderPipeline includes GPUObjectBase; +GPURenderPipeline includes GPUPipelineBase; dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase { required GPUProgrammableStageDescriptor vertexStage; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 3c970a87760..a7169834586 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -36,7 +36,7 @@ use wgpu::{ BufferCopyView, ComputePass, RenderBundleDescriptor, RenderBundleEncoder, RenderPass, TextureCopyView, }, - device::HostMap, + device::{HostMap, ImplicitPipelineIds}, id, instance::RequestAdapterOptions, pipeline::{ComputePipelineDescriptor, RenderPipelineDescriptor}, @@ -141,6 +141,7 @@ pub enum WebGPURequest { device_id: id::DeviceId, compute_pipeline_id: id::ComputePipelineId, descriptor: ComputePipelineDescriptor<'static>, + implicit_ids: Option<(id::PipelineLayoutId, Vec<id::BindGroupLayoutId>)>, }, CreateContext(IpcSender<webrender_api::ExternalImageId>), CreatePipelineLayout { @@ -152,6 +153,7 @@ pub enum WebGPURequest { device_id: id::DeviceId, render_pipeline_id: id::RenderPipelineId, descriptor: Option<RenderPipelineDescriptor<'static>>, + implicit_ids: Option<(id::PipelineLayoutId, Vec<id::BindGroupLayoutId>)>, }, CreateSampler { device_id: id::DeviceId, @@ -611,13 +613,34 @@ impl<'a> WGPU<'a> { device_id, compute_pipeline_id, descriptor, + implicit_ids, } => { let global = &self.global; - let result = gfx_select!(compute_pipeline_id => - global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id, None)); + let bgls = implicit_ids + .as_ref() + .map_or(Vec::with_capacity(0), |(_, bgls)| bgls.clone()); + let implicit = + implicit_ids + .as_ref() + .map(|(layout, _)| ImplicitPipelineIds { + root_id: *layout, + group_ids: bgls.as_slice(), + }); + let result = gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline( + device_id, + &descriptor, + compute_pipeline_id, + implicit + )); if result.is_err() { let _ = gfx_select!(compute_pipeline_id => global.compute_pipeline_error(compute_pipeline_id)); + if let Some((layout, bgls)) = implicit_ids { + let _ = gfx_select!(layout => global.pipeline_layout_error(layout)); + bgls.iter().for_each(|&bgl| { + let _ = gfx_select!(bgl => global.bind_group_layout_error(bgl)); + }); + } } self.send_result(device_id, scope_id, result); }, @@ -648,14 +671,32 @@ impl<'a> WGPU<'a> { device_id, render_pipeline_id, descriptor, + implicit_ids, } => { let global = &self.global; + let bgls = implicit_ids + .as_ref() + .map_or(Vec::with_capacity(0), |(_, bgls)| bgls.clone()); + let implicit = + implicit_ids + .as_ref() + .map(|(layout, _)| ImplicitPipelineIds { + root_id: *layout, + group_ids: bgls.as_slice(), + }); if let Some(desc) = descriptor { let result = gfx_select!(render_pipeline_id => - global.device_create_render_pipeline(device_id, &desc, render_pipeline_id, None)); + global.device_create_render_pipeline(device_id, &desc, render_pipeline_id, implicit)); if result.is_err() { let _ = gfx_select!(render_pipeline_id => global.render_pipeline_error(render_pipeline_id)); + if let Some((layout, bgls)) = implicit_ids { + let _ = + gfx_select!(layout => global.pipeline_layout_error(layout)); + bgls.iter().for_each(|&bgl| { + let _ = gfx_select!(bgl => global.bind_group_layout_error(bgl)); + }); + } } self.send_result(device_id, scope_id, result); } else { |