mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Implement GPUPipelineBase for implicit pipeline layouts
This commit is contained in:
parent
8c576bb02b
commit
f082a507da
7 changed files with 176 additions and 25 deletions
|
@ -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,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
interface GPURenderPipeline {
|
||||
};
|
||||
GPURenderPipeline includes GPUObjectBase;
|
||||
GPURenderPipeline includes GPUPipelineBase;
|
||||
|
||||
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
|
||||
required GPUProgrammableStageDescriptor vertexStage;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue