mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Initial implementation of GPUPipelineLayout for WebGPU
Added WebIDL bindings for `GPUPipelineLayout`. Implemented the createPipelineLayout function of `GPUDevice`.
This commit is contained in:
parent
0dccfd148a
commit
d33a4d29a0
10 changed files with 223 additions and 6 deletions
|
@ -151,7 +151,9 @@ use tendril::stream::LossyDecoder;
|
|||
use tendril::{StrTendril, TendrilSink};
|
||||
use time::{Duration, Timespec, Tm};
|
||||
use uuid::Uuid;
|
||||
use webgpu::{WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice};
|
||||
use webgpu::{
|
||||
WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, WebGPUPipelineLayout,
|
||||
};
|
||||
use webrender_api::{DocumentId, ImageKey};
|
||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
@ -531,6 +533,7 @@ unsafe_no_jsmanaged_fields!(WebGPUAdapter);
|
|||
unsafe_no_jsmanaged_fields!(WebGPUDevice);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUBuffer);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
|
||||
unsafe_no_jsmanaged_fields!(GPUBufferState);
|
||||
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
||||
unsafe_no_jsmanaged_fields!(MediaList);
|
||||
|
|
|
@ -42,6 +42,7 @@ impl GPUBindGroupLayout {
|
|||
valid: Cell::new(valid),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
channel: WebGPU,
|
||||
|
@ -62,6 +63,20 @@ impl GPUBindGroupLayout {
|
|||
}
|
||||
}
|
||||
|
||||
impl GPUBindGroupLayout {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.valid.get()
|
||||
}
|
||||
|
||||
pub fn id(&self) -> WebGPUBindGroupLayout {
|
||||
self.bind_group_layout
|
||||
}
|
||||
|
||||
pub fn bindings(&self) -> &[GPUBindGroupLayoutBindings] {
|
||||
&self.bindings
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUBindGroupLayoutMethods for GPUBindGroupLayout {
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
fn GetLabel(&self) -> Option<DOMString> {
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
|
|||
};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
|
@ -21,6 +22,7 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::gpuadapter::GPUAdapter;
|
||||
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
|
||||
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
|
||||
use crate::dom::gpupipelinelayout::GPUPipelineLayout;
|
||||
use crate::dom::window::Window;
|
||||
use crate::script_runtime::JSContext as SafeJSContext;
|
||||
use dom_struct::dom_struct;
|
||||
|
@ -410,4 +412,69 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
|
||||
GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout
|
||||
fn CreatePipelineLayout(
|
||||
&self,
|
||||
descriptor: &GPUPipelineLayoutDescriptor,
|
||||
) -> DomRoot<GPUPipelineLayout> {
|
||||
// TODO: We should have these limits on device creation
|
||||
let limits = GPULimits::empty();
|
||||
let mut bind_group_layouts = Vec::new();
|
||||
let mut bgl_ids = Vec::new();
|
||||
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;
|
||||
descriptor.bindGroupLayouts.iter().for_each(|each| {
|
||||
if each.is_valid() {
|
||||
let id = each.id();
|
||||
bind_group_layouts.push(id);
|
||||
bgl_ids.push(id.0);
|
||||
}
|
||||
each.bindings().iter().for_each(|bind| {
|
||||
match bind.type_ {
|
||||
GPUBindingType::Uniform_buffer => {
|
||||
if bind.hasDynamicOffset {
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout -= 1;
|
||||
};
|
||||
},
|
||||
GPUBindingType::Storage_buffer => {
|
||||
if bind.hasDynamicOffset {
|
||||
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
|
||||
};
|
||||
},
|
||||
GPUBindingType::Readonly_storage_buffer => {
|
||||
if bind.hasDynamicOffset {
|
||||
max_dynamic_storage_buffers_per_pipeline_layout -= 1;
|
||||
};
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
let valid = descriptor.bindGroupLayouts.len() <= limits.maxBindGroups as usize &&
|
||||
descriptor.bindGroupLayouts.len() == bind_group_layouts.len() &&
|
||||
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::<Window>() {
|
||||
let id = window
|
||||
.Navigator()
|
||||
.create_pipeline_layout_id(self.device.0.backend());
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::CreatePipelineLayout(
|
||||
sender,
|
||||
self.device,
|
||||
id,
|
||||
bgl_ids,
|
||||
))
|
||||
.expect("Failed to create WebGPU PipelineLayout");
|
||||
}
|
||||
let pipeline_layout = receiver.recv().unwrap();
|
||||
GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid)
|
||||
}
|
||||
}
|
||||
|
|
69
components/script/dom/gpupipelinelayout.rs
Normal file
69
components/script/dom/gpupipelinelayout.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* 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::GPUPipelineLayoutBinding::{
|
||||
self, GPUPipelineLayoutMethods,
|
||||
};
|
||||
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::{WebGPUBindGroupLayout, WebGPUPipelineLayout};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUPipelineLayout {
|
||||
reflector_: Reflector,
|
||||
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
pipeline_layout: WebGPUPipelineLayout,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUPipelineLayout {
|
||||
fn new_inherited(
|
||||
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
|
||||
pipeline_layout: WebGPUPipelineLayout,
|
||||
valid: bool,
|
||||
) -> GPUPipelineLayout {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
bind_group_layouts,
|
||||
label: DomRefCell::new(None),
|
||||
pipeline_layout,
|
||||
valid: Cell::new(valid),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
|
||||
pipeline_layout: WebGPUPipelineLayout,
|
||||
valid: bool,
|
||||
) -> DomRoot<GPUPipelineLayout> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUPipelineLayout::new_inherited(
|
||||
bind_group_layouts,
|
||||
pipeline_layout,
|
||||
valid,
|
||||
)),
|
||||
global,
|
||||
GPUPipelineLayoutBinding::Wrap,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUPipelineLayoutMethods for GPUPipelineLayout {
|
||||
/// 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;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
use smallvec::SmallVec;
|
||||
use webgpu::wgpu::{
|
||||
hub::IdentityManager,
|
||||
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId},
|
||||
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
|
||||
Backend,
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@ pub struct IdentityHub {
|
|||
devices: IdentityManager,
|
||||
buffers: IdentityManager,
|
||||
bind_group_layouts: IdentityManager,
|
||||
pipeline_layouts: IdentityManager,
|
||||
backend: Backend,
|
||||
}
|
||||
|
||||
|
@ -25,6 +26,7 @@ impl IdentityHub {
|
|||
devices: IdentityManager::default(),
|
||||
buffers: IdentityManager::default(),
|
||||
bind_group_layouts: IdentityManager::default(),
|
||||
pipeline_layouts: IdentityManager::default(),
|
||||
backend,
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +46,10 @@ impl IdentityHub {
|
|||
fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId {
|
||||
self.bind_group_layouts.alloc(self.backend)
|
||||
}
|
||||
|
||||
fn create_pipeline_layout_id(&mut self) -> PipelineLayoutId {
|
||||
self.pipeline_layouts.alloc(self.backend)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -139,4 +145,18 @@ impl Identities {
|
|||
_ => self.dummy_hub.create_bind_group_layout_id(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId {
|
||||
match backend {
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
Backend::Vulkan => self.vk_hub.create_pipeline_layout_id(),
|
||||
#[cfg(target_os = "windows")]
|
||||
Backend::Dx12 => self.dx12_hub.create_pipeline_layout_id(),
|
||||
#[cfg(target_os = "windows")]
|
||||
Backend::Dx11 => self.dx11_hub.create_pipeline_layout_id(),
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
Backend::Metal => self.metal_hub.create_pipeline_layout_id(),
|
||||
_ => self.dummy_hub.create_pipeline_layout_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,6 +322,7 @@ pub mod gpubindgrouplayout;
|
|||
pub mod gpubuffer;
|
||||
pub mod gpubufferusage;
|
||||
pub mod gpudevice;
|
||||
pub mod gpupipelinelayout;
|
||||
pub mod gpushaderstage;
|
||||
pub mod hashchangeevent;
|
||||
pub mod headers;
|
||||
|
|
|
@ -28,7 +28,7 @@ use smallvec::SmallVec;
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use webgpu::wgpu::{
|
||||
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId},
|
||||
id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
|
||||
Backend,
|
||||
};
|
||||
|
||||
|
@ -94,6 +94,12 @@ impl Navigator {
|
|||
.borrow_mut()
|
||||
.create_bind_group_layout_id(backend)
|
||||
}
|
||||
|
||||
pub fn create_pipeline_layout_id(&self, backend: Backend) -> PipelineLayoutId {
|
||||
self.gpu_id_hub
|
||||
.borrow_mut()
|
||||
.create_pipeline_layout_id(backend)
|
||||
}
|
||||
}
|
||||
|
||||
impl NavigatorMethods for Navigator {
|
||||
|
|
|
@ -16,8 +16,8 @@ interface GPUDevice : EventTarget {
|
|||
//GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
|
||||
|
||||
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
|
||||
/*GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
|
||||
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
|
||||
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
|
||||
/*GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
|
||||
|
||||
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
|
||||
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
|
||||
|
|
13
components/script/dom/webidls/GPUPipelineLayout.webidl
Normal file
13
components/script/dom/webidls/GPUPipelineLayout.webidl
Normal file
|
@ -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/#pipeline-layout
|
||||
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
|
||||
interface GPUPipelineLayout {
|
||||
};
|
||||
GPUPipelineLayout includes GPUObjectBase;
|
||||
|
||||
dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase {
|
||||
required sequence<GPUBindGroupLayout> bindGroupLayouts;
|
||||
};
|
|
@ -54,6 +54,12 @@ pub enum WebGPURequest {
|
|||
wgpu::id::BindGroupLayoutId,
|
||||
Vec<wgpu::binding_model::BindGroupLayoutBinding>,
|
||||
),
|
||||
CreatePipelineLayout(
|
||||
IpcSender<WebGPUPipelineLayout>,
|
||||
WebGPUDevice,
|
||||
wgpu::id::PipelineLayoutId,
|
||||
Vec<wgpu::id::BindGroupLayoutId>,
|
||||
),
|
||||
UnmapBuffer(WebGPUBuffer),
|
||||
DestroyBuffer(WebGPUBuffer),
|
||||
}
|
||||
|
@ -237,7 +243,23 @@ impl WGPU {
|
|||
|
||||
if let Err(e) = sender.send(bgl) {
|
||||
warn!(
|
||||
"Failed to send response to WebGPURequest::CreateBufferMapped ({})",
|
||||
"Failed to send response to WebGPURequest::CreateBindGroupLayout ({})",
|
||||
e
|
||||
)
|
||||
}
|
||||
},
|
||||
WebGPURequest::CreatePipelineLayout(sender, device, id, bind_group_layouts) => {
|
||||
let global = &self.global;
|
||||
let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_ptr(),
|
||||
bind_group_layouts_length: bind_group_layouts.len(),
|
||||
};
|
||||
let pl_id = gfx_select!(id => global.device_create_pipeline_layout(device.0, &descriptor, id));
|
||||
let pipeline_layout = WebGPUPipelineLayout(pl_id);
|
||||
|
||||
if let Err(e) = sender.send(pipeline_layout) {
|
||||
warn!(
|
||||
"Failed to send response to WebGPURequest::CreatePipelineLayout ({})",
|
||||
e
|
||||
)
|
||||
}
|
||||
|
@ -273,3 +295,4 @@ webgpu_resource!(WebGPUAdapter, wgpu::id::AdapterId);
|
|||
webgpu_resource!(WebGPUDevice, wgpu::id::DeviceId);
|
||||
webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
|
||||
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
|
||||
webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue