aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKunal Mohan <kunalmohan99@gmail.com>2020-08-19 16:44:26 +0530
committerKunal Mohan <kunalmohan99@gmail.com>2020-08-19 16:44:26 +0530
commitf082a507da2a09d579021f8b2f0930afdec74c24 (patch)
treef1c85fce90094949e38099218389cec164ce92c0
parent8c576bb02b6424d6a7d0d02551face0b461c0e0e (diff)
downloadservo-f082a507da2a09d579021f8b2f0930afdec74c24.tar.gz
servo-f082a507da2a09d579021f8b2f0930afdec74c24.zip
Implement GPUPipelineBase for implicit pipeline layouts
-rw-r--r--components/script/dom/gpucomputepipeline.rs37
-rw-r--r--components/script/dom/gpudevice.rs54
-rw-r--r--components/script/dom/gpupipelinelayout.rs21
-rw-r--r--components/script/dom/gpurenderpipeline.rs32
-rw-r--r--components/script/dom/webidls/GPUComputePipeline.webidl7
-rw-r--r--components/script/dom/webidls/GPURenderPipeline.webidl1
-rw-r--r--components/webgpu/lib.rs49
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 {