From 75abccb16bc19eb375ce73f26a0234e3d2ecbb9b Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Wed, 22 Jul 2020 23:22:13 +0530 Subject: [PATCH 1/2] update wgpu, use serializable descriptors --- Cargo.lock | 4 +- components/script/dom/gpucommandencoder.rs | 103 +++---- components/script/dom/gpudevice.rs | 310 +++++++++++---------- components/webgpu/identity.rs | 4 +- components/webgpu/lib.rs | 178 ++---------- 5 files changed, 247 insertions(+), 352 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53ff04b3db7f..f7339cbfa0f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6861,7 +6861,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#73b230871ea4428ed3fb1e6e8bff81a7364fcdb2" +source = "git+https://github.com/gfx-rs/wgpu#4ed2c0a313deb48a99f15e8fe0558ad3d095ca01" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -6890,7 +6890,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#73b230871ea4428ed3fb1e6e8bff81a7364fcdb2" +source = "git+https://github.com/gfx-rs/wgpu#4ed2c0a313deb48a99f15e8fe0558ad3d095ca01" dependencies = [ "bitflags", "serde", diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 36b24b6b14e7..4f297fadb1b5 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -25,6 +25,7 @@ use crate::dom::gpucomputepassencoder::GPUComputePassEncoder; use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt}; use crate::dom::gpurenderpassencoder::GPURenderPassEncoder; use dom_struct::dom_struct; +use std::borrow::Cow; use std::cell::Cell; use std::collections::HashSet; use webgpu::wgpu::command as wgpu_com; @@ -135,55 +136,6 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { GPUCommandEncoderState::Open, ); - let colors = descriptor - .colorAttachments - .iter() - .map(|color| { - let (load_op, clear_value) = match color.loadValue { - GPUColorLoad::GPULoadOp(_) => (wgpu_com::LoadOp::Load, wgt::Color::TRANSPARENT), - GPUColorLoad::DoubleSequence(ref s) => { - let mut w = s.clone(); - if w.len() < 3 { - w.resize(3, Finite::wrap(0.0f64)); - } - w.resize(4, Finite::wrap(1.0f64)); - ( - wgpu_com::LoadOp::Clear, - wgt::Color { - r: *w[0], - g: *w[1], - b: *w[2], - a: *w[3], - }, - ) - }, - GPUColorLoad::GPUColorDict(ref d) => ( - wgpu_com::LoadOp::Clear, - wgt::Color { - r: *d.r, - g: *d.g, - b: *d.b, - a: *d.a, - }, - ), - }; - let channel = wgpu_com::PassChannel { - load_op, - store_op: match color.storeOp { - GPUStoreOp::Store => wgpu_com::StoreOp::Store, - GPUStoreOp::Clear => wgpu_com::StoreOp::Clear, - }, - clear_value, - read_only: false, - }; - wgpu_com::ColorAttachmentDescriptor { - attachment: color.attachment.id().0, - resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0), - channel, - } - }) - .collect::>(); - let depth_stencil = descriptor.depthStencilAttachment.as_ref().map(|depth| { let (depth_load_op, clear_depth) = match depth.depthLoadValue { GPULoadOpOrFloat::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0.0f32), @@ -219,7 +171,58 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { }); let desc = wgpu_com::RenderPassDescriptor { - color_attachments: colors.as_slice(), + color_attachments: Cow::Owned( + descriptor + .colorAttachments + .iter() + .map(|color| { + let (load_op, clear_value) = match color.loadValue { + GPUColorLoad::GPULoadOp(_) => { + (wgpu_com::LoadOp::Load, wgt::Color::TRANSPARENT) + }, + GPUColorLoad::DoubleSequence(ref s) => { + let mut w = s.clone(); + if w.len() < 3 { + w.resize(3, Finite::wrap(0.0f64)); + } + w.resize(4, Finite::wrap(1.0f64)); + ( + wgpu_com::LoadOp::Clear, + wgt::Color { + r: *w[0], + g: *w[1], + b: *w[2], + a: *w[3], + }, + ) + }, + GPUColorLoad::GPUColorDict(ref d) => ( + wgpu_com::LoadOp::Clear, + wgt::Color { + r: *d.r, + g: *d.g, + b: *d.b, + a: *d.a, + }, + ), + }; + let channel = wgpu_com::PassChannel { + load_op, + store_op: match color.storeOp { + GPUStoreOp::Store => wgpu_com::StoreOp::Store, + GPUStoreOp::Clear => wgpu_com::StoreOp::Clear, + }, + clear_value, + read_only: false, + }; + wgpu_com::ColorAttachmentDescriptor { + attachment: color.attachment.id().0, + resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0), + channel, + } + }) + .collect::>(), + ), depth_stencil_attachment: depth_stencil.as_ref(), }; diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index d7640b5dd372..a1d2c19c58cd 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -57,16 +57,16 @@ use crate::dom::gputexture::GPUTexture; use crate::dom::promise::Promise; use crate::realms::InRealm; use crate::script_runtime::JSContext as SafeJSContext; -use arrayvec::ArrayVec; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; +use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; use std::string::String; -use webgpu::wgpu::binding_model::BufferBinding; -use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest}; +use webgpu::wgpu::{binding_model as wgpu_bind, pipeline as wgpu_pipe}; +use webgpu::{self, wgt, WebGPU, WebGPURequest}; type ErrorScopeId = u64; @@ -401,6 +401,15 @@ impl GPUDeviceMethods for GPUDevice { } } + let desc = wgt::BindGroupLayoutDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + entries: Cow::Owned(entries.clone()), + }; + let bind_group_layout_id = self .global() .wgpu_id_hub() @@ -411,13 +420,8 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroupLayout { device_id: self.device.0, bind_group_layout_id, - entries: entries.clone(), scope_id, - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), + descriptor: desc, }) .expect("Failed to create WebGPU BindGroupLayout"); @@ -437,11 +441,16 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUPipelineLayoutDescriptor, ) -> DomRoot { - let mut bgl_ids = Vec::new(); - descriptor - .bindGroupLayouts - .iter() - .for_each(|each| bgl_ids.push(each.id().0)); + let desc = wgt::PipelineLayoutDescriptor { + bind_group_layouts: Cow::Owned( + descriptor + .bindGroupLayouts + .iter() + .map(|each| each.id().0) + .collect::>(), + ), + push_constant_ranges: Cow::Owned(vec![]), + }; let scope_id = self.use_current_scope(); @@ -455,7 +464,7 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreatePipelineLayout { device_id: self.device.0, pipeline_layout_id, - bind_group_layouts: bgl_ids, + descriptor: desc, scope_id, }) .expect("Failed to create WebGPU PipelineLayout"); @@ -469,26 +478,36 @@ impl GPUDeviceMethods for GPUDevice { let entries = descriptor .entries .iter() - .map(|bind| { - ( - bind.binding, - match bind.resource { - GPUBindingResource::GPUSampler(ref s) => WebGPUBindings::Sampler(s.id().0), - GPUBindingResource::GPUTextureView(ref t) => { - WebGPUBindings::TextureView(t.id().0) - }, - GPUBindingResource::GPUBufferBindings(ref b) => { - WebGPUBindings::Buffer(BufferBinding { - buffer_id: b.buffer.id().0, - offset: b.offset, - size: b.size.and_then(wgt::BufferSize::new), - }) - }, + .map(|bind| wgpu_bind::BindGroupEntry { + binding: bind.binding, + resource: match bind.resource { + GPUBindingResource::GPUSampler(ref s) => { + wgpu_bind::BindingResource::Sampler(s.id().0) + }, + GPUBindingResource::GPUTextureView(ref t) => { + wgpu_bind::BindingResource::TextureView(t.id().0) }, - ) + GPUBindingResource::GPUBufferBindings(ref b) => { + wgpu_bind::BindingResource::Buffer(wgpu_bind::BufferBinding { + buffer_id: b.buffer.id().0, + offset: b.offset, + size: b.size.and_then(wgt::BufferSize::new), + }) + }, + }, }) .collect::>(); + let desc = wgpu_bind::BindGroupDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|l| Cow::Owned(l.to_string())), + layout: descriptor.layout.id().0, + entries: Cow::Owned(entries), + }; + let scope_id = self.use_current_scope(); let bind_group_id = self @@ -501,14 +520,8 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroup { device_id: self.device.0, bind_group_id, - bind_group_layout_id: descriptor.layout.id().0, - entries, + descriptor: desc, scope_id, - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), }) .expect("Failed to create WebGPU BindGroup"); @@ -551,9 +564,6 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUComputePipelineDescriptor, ) -> DomRoot { - let pipeline = descriptor.parent.layout.id(); - let program = descriptor.computeStage.module.id(); - let entry_point = descriptor.computeStage.entryPoint.to_string(); let compute_pipeline_id = self .global() .wgpu_id_hub() @@ -562,15 +572,21 @@ impl GPUDeviceMethods for GPUDevice { let scope_id = self.use_current_scope(); + let desc = wgpu_pipe::ComputePipelineDescriptor { + layout: descriptor.parent.layout.id().0, + compute_stage: wgpu_pipe::ProgrammableStageDescriptor { + module: descriptor.computeStage.module.id().0, + entry_point: Cow::Owned(descriptor.computeStage.entryPoint.to_string()), + }, + }; + self.channel .0 .send(WebGPURequest::CreateComputePipeline { device_id: self.device.0, scope_id, compute_pipeline_id, - pipeline_layout_id: pipeline.0, - program_id: program.0, - entry_point, + descriptor: desc, }) .expect("Failed to create WebGPU ComputePipeline"); @@ -712,104 +728,112 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPURenderPipelineDescriptor, ) -> DomRoot { - let vertex_module = descriptor.vertexStage.module.id().0; - let vertex_entry_point = descriptor.vertexStage.entryPoint.to_string(); - let (fragment_module, fragment_entry_point) = match descriptor.fragmentStage { - Some(ref frag) => (Some(frag.module.id().0), Some(frag.entryPoint.to_string())), - None => (None, None), - }; - - let primitive_topology = match descriptor.primitiveTopology { - GPUPrimitiveTopology::Point_list => wgt::PrimitiveTopology::PointList, - GPUPrimitiveTopology::Line_list => wgt::PrimitiveTopology::LineList, - GPUPrimitiveTopology::Line_strip => wgt::PrimitiveTopology::LineStrip, - GPUPrimitiveTopology::Triangle_list => wgt::PrimitiveTopology::TriangleList, - GPUPrimitiveTopology::Triangle_strip => wgt::PrimitiveTopology::TriangleStrip, - }; - let ref rs_desc = descriptor.rasterizationState; - let rasterization_state = wgt::RasterizationStateDescriptor { - front_face: match rs_desc.frontFace { - GPUFrontFace::Ccw => wgt::FrontFace::Ccw, - GPUFrontFace::Cw => wgt::FrontFace::Cw, - }, - cull_mode: match rs_desc.cullMode { - GPUCullMode::None => wgt::CullMode::None, - GPUCullMode::Front => wgt::CullMode::Front, - GPUCullMode::Back => wgt::CullMode::Back, - }, - depth_bias: rs_desc.depthBias, - depth_bias_slope_scale: *rs_desc.depthBiasSlopeScale, - depth_bias_clamp: *rs_desc.depthBiasClamp, - }; + let ref vs_desc = descriptor.vertexState; - let color_states = descriptor - .colorStates - .iter() - .map(|state| wgt::ColorStateDescriptor { - format: convert_texture_format(state.format), - alpha_blend: convert_blend_descriptor(&state.alphaBlend), - color_blend: convert_blend_descriptor(&state.colorBlend), - write_mask: match wgt::ColorWrite::from_bits(state.writeMask) { - Some(mask) => mask, - None => wgt::ColorWrite::empty(), - }, - }) - .collect::>(); - - let depth_stencil_state = if let Some(ref dss_desc) = descriptor.depthStencilState { - Some(wgt::DepthStencilStateDescriptor { - format: convert_texture_format(dss_desc.format), - depth_write_enabled: dss_desc.depthWriteEnabled, - depth_compare: convert_compare_function(dss_desc.depthCompare), - stencil_front: wgt::StencilStateFaceDescriptor { - compare: convert_compare_function(dss_desc.stencilFront.compare), - fail_op: convert_stencil_op(dss_desc.stencilFront.failOp), - depth_fail_op: convert_stencil_op(dss_desc.stencilFront.depthFailOp), - pass_op: convert_stencil_op(dss_desc.stencilFront.passOp), + let desc = wgpu_pipe::RenderPipelineDescriptor { + layout: descriptor.parent.layout.id().0, + vertex_stage: wgpu_pipe::ProgrammableStageDescriptor { + module: descriptor.vertexStage.module.id().0, + entry_point: Cow::Owned(descriptor.vertexStage.entryPoint.to_string()), + }, + fragment_stage: descriptor.fragmentStage.as_ref().map(|stage| { + wgpu_pipe::ProgrammableStageDescriptor { + module: stage.module.id().0, + entry_point: Cow::Owned(stage.entryPoint.to_string()), + } + }), + rasterization_state: Some(wgt::RasterizationStateDescriptor { + front_face: match rs_desc.frontFace { + GPUFrontFace::Ccw => wgt::FrontFace::Ccw, + GPUFrontFace::Cw => wgt::FrontFace::Cw, }, - stencil_back: wgt::StencilStateFaceDescriptor { - compare: convert_compare_function(dss_desc.stencilBack.compare), - fail_op: convert_stencil_op(dss_desc.stencilBack.failOp), - depth_fail_op: convert_stencil_op(dss_desc.stencilBack.depthFailOp), - pass_op: convert_stencil_op(dss_desc.stencilBack.passOp), + cull_mode: match rs_desc.cullMode { + GPUCullMode::None => wgt::CullMode::None, + GPUCullMode::Front => wgt::CullMode::Front, + GPUCullMode::Back => wgt::CullMode::Back, }, - stencil_read_mask: dss_desc.stencilReadMask, - stencil_write_mask: dss_desc.stencilWriteMask, - }) - } else { - None - }; - - let ref vs_desc = descriptor.vertexState; - let vertex_state = ( - match vs_desc.indexFormat { - GPUIndexFormat::Uint16 => wgt::IndexFormat::Uint16, - GPUIndexFormat::Uint32 => wgt::IndexFormat::Uint32, + depth_bias: rs_desc.depthBias, + depth_bias_slope_scale: *rs_desc.depthBiasSlopeScale, + depth_bias_clamp: *rs_desc.depthBiasClamp, + }), + primitive_topology: match descriptor.primitiveTopology { + GPUPrimitiveTopology::Point_list => wgt::PrimitiveTopology::PointList, + GPUPrimitiveTopology::Line_list => wgt::PrimitiveTopology::LineList, + GPUPrimitiveTopology::Line_strip => wgt::PrimitiveTopology::LineStrip, + GPUPrimitiveTopology::Triangle_list => wgt::PrimitiveTopology::TriangleList, + GPUPrimitiveTopology::Triangle_strip => wgt::PrimitiveTopology::TriangleStrip, }, - vs_desc - .vertexBuffers - .iter() - .map(|buffer| { - ( - buffer.arrayStride, - match buffer.stepMode { - GPUInputStepMode::Vertex => wgt::InputStepMode::Vertex, - GPUInputStepMode::Instance => wgt::InputStepMode::Instance, + color_states: Cow::Owned( + descriptor + .colorStates + .iter() + .map(|state| wgt::ColorStateDescriptor { + format: convert_texture_format(state.format), + alpha_blend: convert_blend_descriptor(&state.alphaBlend), + color_blend: convert_blend_descriptor(&state.colorBlend), + write_mask: match wgt::ColorWrite::from_bits(state.writeMask) { + Some(mask) => mask, + None => wgt::ColorWrite::empty(), }, - buffer - .attributes - .iter() - .map(|att| wgt::VertexAttributeDescriptor { - format: convert_vertex_format(att.format), - offset: att.offset, - shader_location: att.shaderLocation, - }) - .collect::>(), - ) - }) - .collect::>(), - ); + }) + .collect::>(), + ), + depth_stencil_state: descriptor.depthStencilState.as_ref().map(|dss_desc| { + wgt::DepthStencilStateDescriptor { + format: convert_texture_format(dss_desc.format), + depth_write_enabled: dss_desc.depthWriteEnabled, + depth_compare: convert_compare_function(dss_desc.depthCompare), + stencil_front: wgt::StencilStateFaceDescriptor { + compare: convert_compare_function(dss_desc.stencilFront.compare), + fail_op: convert_stencil_op(dss_desc.stencilFront.failOp), + depth_fail_op: convert_stencil_op(dss_desc.stencilFront.depthFailOp), + pass_op: convert_stencil_op(dss_desc.stencilFront.passOp), + }, + stencil_back: wgt::StencilStateFaceDescriptor { + compare: convert_compare_function(dss_desc.stencilBack.compare), + fail_op: convert_stencil_op(dss_desc.stencilBack.failOp), + depth_fail_op: convert_stencil_op(dss_desc.stencilBack.depthFailOp), + pass_op: convert_stencil_op(dss_desc.stencilBack.passOp), + }, + stencil_read_mask: dss_desc.stencilReadMask, + stencil_write_mask: dss_desc.stencilWriteMask, + } + }), + vertex_state: wgt::VertexStateDescriptor { + index_format: match vs_desc.indexFormat { + GPUIndexFormat::Uint16 => wgt::IndexFormat::Uint16, + GPUIndexFormat::Uint32 => wgt::IndexFormat::Uint32, + }, + vertex_buffers: Cow::Owned( + vs_desc + .vertexBuffers + .iter() + .map(|buffer| wgt::VertexBufferDescriptor { + stride: buffer.arrayStride, + step_mode: match buffer.stepMode { + GPUInputStepMode::Vertex => wgt::InputStepMode::Vertex, + GPUInputStepMode::Instance => wgt::InputStepMode::Instance, + }, + attributes: Cow::Owned( + buffer + .attributes + .iter() + .map(|att| wgt::VertexAttributeDescriptor { + format: convert_vertex_format(att.format), + offset: att.offset, + shader_location: att.shaderLocation, + }) + .collect::>(), + ), + }) + .collect::>(), + ), + }, + sample_count: descriptor.sampleCount, + sample_mask: descriptor.sampleMask, + alpha_to_coverage_enabled: descriptor.alphaToCoverageEnabled, + }; let render_pipeline_id = self .global() @@ -825,19 +849,7 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, render_pipeline_id, scope_id, - pipeline_layout_id: descriptor.parent.layout.id().0, - vertex_module, - vertex_entry_point, - fragment_module, - fragment_entry_point, - primitive_topology, - rasterization_state, - color_states, - depth_stencil_state, - vertex_state, - sample_count: descriptor.sampleCount, - sample_mask: descriptor.sampleMask, - alpha_to_coverage_enabled: descriptor.alphaToCoverageEnabled, + descriptor: desc, }) .expect("Failed to create WebGPU render pipeline"); diff --git a/components/webgpu/identity.rs b/components/webgpu/identity.rs index 8a76868a2df4..3fe3d817081b 100644 --- a/components/webgpu/identity.rs +++ b/components/webgpu/identity.rs @@ -57,12 +57,12 @@ pub enum WebGPUMsg { #[derive(Debug)] pub struct IdentityRecycler { sender: IpcSender, - self_sender: IpcSender, + self_sender: IpcSender>, } pub struct IdentityRecyclerFactory { pub sender: IpcSender, - pub self_sender: IpcSender, + pub self_sender: IpcSender>, } macro_rules! impl_identity_handler { diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 747e25eb7be7..58b2c427d99f 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -31,11 +31,12 @@ use webrender_traits::{ WebrenderImageSource, }; use wgpu::{ - binding_model::{BindGroupDescriptor, BindGroupEntry, BindingResource, BufferBinding}, + binding_model::BindGroupDescriptor, command::{BufferCopyView, ComputePass, RenderPass, TextureCopyView}, device::HostMap, id, instance::RequestAdapterOptions, + pipeline::{ComputePipelineDescriptor, RenderPipelineDescriptor}, resource::{BufferMapAsyncStatus, BufferMapOperation}, }; @@ -60,7 +61,7 @@ pub enum WebGPUResponse { pub type WebGPUResponseResult = Result; #[derive(Debug, Deserialize, Serialize)] -pub enum WebGPURequest { +pub enum WebGPURequest<'a> { BufferMapAsync { sender: IpcSender, buffer_id: id::BufferId, @@ -104,16 +105,13 @@ pub enum WebGPURequest { // TODO: Consider using NonZeroU64 to reduce enum size scope_id: Option, bind_group_id: id::BindGroupId, - bind_group_layout_id: id::BindGroupLayoutId, - entries: Vec<(u32, WebGPUBindings)>, - label: Option, + descriptor: BindGroupDescriptor<'a>, }, CreateBindGroupLayout { device_id: id::DeviceId, scope_id: Option, bind_group_layout_id: id::BindGroupLayoutId, - entries: Vec, - label: Option, + descriptor: wgt::BindGroupLayoutDescriptor<'a>, }, CreateBuffer { device_id: id::DeviceId, @@ -131,37 +129,20 @@ pub enum WebGPURequest { device_id: id::DeviceId, scope_id: Option, compute_pipeline_id: id::ComputePipelineId, - pipeline_layout_id: id::PipelineLayoutId, - program_id: id::ShaderModuleId, - entry_point: String, + descriptor: ComputePipelineDescriptor<'a>, }, CreateContext(IpcSender), CreatePipelineLayout { device_id: id::DeviceId, scope_id: Option, pipeline_layout_id: id::PipelineLayoutId, - bind_group_layouts: Vec, + descriptor: wgt::PipelineLayoutDescriptor<'a, id::BindGroupLayoutId>, }, CreateRenderPipeline { device_id: id::DeviceId, scope_id: Option, render_pipeline_id: id::RenderPipelineId, - pipeline_layout_id: id::PipelineLayoutId, - vertex_module: id::ShaderModuleId, - vertex_entry_point: String, - fragment_module: Option, - fragment_entry_point: Option, - primitive_topology: wgt::PrimitiveTopology, - rasterization_state: wgt::RasterizationStateDescriptor, - color_states: ArrayVec<[wgt::ColorStateDescriptor; wgpu::device::MAX_COLOR_TARGETS]>, - depth_stencil_state: Option, - vertex_state: ( - wgt::IndexFormat, - Vec<(u64, wgt::InputStepMode, Vec)>, - ), - sample_count: u32, - sample_mask: u32, - alpha_to_coverage_enabled: bool, + descriptor: RenderPipelineDescriptor<'a>, }, CreateSampler { device_id: id::DeviceId, @@ -255,13 +236,6 @@ pub enum WebGPURequest { }, } -#[derive(Debug, Deserialize, Serialize)] -pub enum WebGPUBindings { - Buffer(BufferBinding), - Sampler(id::SamplerId), - TextureView(id::TextureViewId), -} - struct BufferMapInfo<'a, T> { buffer_id: id::BufferId, sender: IpcSender, @@ -271,7 +245,7 @@ struct BufferMapInfo<'a, T> { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct WebGPU(pub IpcSender); +pub struct WebGPU(pub IpcSender>); impl WebGPU { pub fn new( @@ -335,8 +309,8 @@ impl WebGPU { } struct WGPU<'a> { - receiver: IpcReceiver, - sender: IpcSender, + receiver: IpcReceiver>, + sender: IpcSender>, script_sender: IpcSender, global: wgpu::hub::Global, adapters: Vec, @@ -346,7 +320,7 @@ struct WGPU<'a> { // Buffers with pending mapping buffer_maps: HashMap>>, // Presentation Buffers with pending mapping - present_buffer_maps: HashMap>>, + present_buffer_maps: HashMap>>>, webrender_api: webrender_api::RenderApi, webrender_document: webrender_api::DocumentId, external_images: Arc>, @@ -356,8 +330,8 @@ struct WGPU<'a> { impl<'a> WGPU<'a> { fn new( - receiver: IpcReceiver, - sender: IpcSender, + receiver: IpcReceiver>, + sender: IpcSender>, script_sender: IpcSender, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, @@ -420,7 +394,8 @@ impl<'a> WGPU<'a> { BufferMapAsyncStatus::Success => { let global = &info.global; let data_pt = gfx_select!(info.buffer_id => - global.buffer_get_mapped_range(info.buffer_id, 0, None)); + global.buffer_get_mapped_range(info.buffer_id, 0, None)) + .unwrap(); let data = slice::from_raw_parts(data_pt, info.size); if let Err(e) = info.sender.send(Ok(WebGPUResponse::BufferMapAsync( @@ -442,7 +417,7 @@ impl<'a> WGPU<'a> { ), }; let global = &self.global; - gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); + let _ = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); }, WebGPURequest::BufferMapComplete(buffer_id) => { self.buffer_maps.remove(&buffer_id); @@ -518,32 +493,9 @@ impl<'a> WGPU<'a> { device_id, scope_id, bind_group_id, - bind_group_layout_id, - mut entries, - label, + descriptor, } => { let global = &self.global; - let bindings = entries - .drain(..) - .map(|(bind, res)| { - let resource = match res { - WebGPUBindings::Sampler(s) => BindingResource::Sampler(s), - WebGPUBindings::TextureView(t) => { - BindingResource::TextureView(t) - }, - WebGPUBindings::Buffer(b) => BindingResource::Buffer(b), - }; - BindGroupEntry { - binding: bind, - resource, - } - }) - .collect::>(); - let descriptor = BindGroupDescriptor { - label: label.as_deref(), - layout: bind_group_layout_id, - entries: bindings.as_slice(), - }; let result = gfx_select!(bind_group_id => global.device_create_bind_group(device_id, &descriptor, bind_group_id)); if let Some(s_id) = scope_id { @@ -554,14 +506,9 @@ impl<'a> WGPU<'a> { device_id, scope_id, bind_group_layout_id, - entries, - label, + descriptor, } => { let global = &self.global; - let descriptor = wgt::BindGroupLayoutDescriptor { - entries: entries.as_slice(), - label: label.as_deref(), - }; let result = gfx_select!(bind_group_layout_id => global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); if let Some(s_id) = scope_id { @@ -607,18 +554,9 @@ impl<'a> WGPU<'a> { device_id, scope_id, compute_pipeline_id, - pipeline_layout_id, - program_id, - entry_point, + descriptor, } => { let global = &self.global; - let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor { - layout: pipeline_layout_id, - compute_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: program_id, - entry_point: entry_point.as_str(), - }, - }; let result = gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); if let Some(s_id) = scope_id { @@ -639,13 +577,9 @@ impl<'a> WGPU<'a> { device_id, scope_id, pipeline_layout_id, - bind_group_layouts, + descriptor, } => { let global = &self.global; - let descriptor = wgt::PipelineLayoutDescriptor { - bind_group_layouts: bind_group_layouts.as_slice(), - push_constant_ranges: &[], - }; let result = gfx_select!(pipeline_layout_id => global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)); if let Some(s_id) = scope_id { @@ -657,65 +591,9 @@ impl<'a> WGPU<'a> { device_id, scope_id, render_pipeline_id, - pipeline_layout_id, - vertex_module, - vertex_entry_point, - fragment_module, - fragment_entry_point, - primitive_topology, - rasterization_state, - color_states, - depth_stencil_state, - vertex_state, - sample_count, - sample_mask, - alpha_to_coverage_enabled, + descriptor, } => { let global = &self.global; - let frag_ep; - let fragment_stage = match fragment_module { - Some(frag) => { - frag_ep = fragment_entry_point.unwrap().clone(); - let frag_module = - wgpu_core::pipeline::ProgrammableStageDescriptor { - module: frag, - entry_point: frag_ep.as_str(), - }; - Some(frag_module) - }, - None => None, - }; - let vert_buffers = vertex_state - .1 - .iter() - .map(|&(stride, step_mode, ref attributes)| { - wgt::VertexBufferDescriptor { - stride, - step_mode, - attributes: attributes.as_slice(), - } - }) - .collect::>(); - let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor { - layout: pipeline_layout_id, - vertex_stage: wgpu_core::pipeline::ProgrammableStageDescriptor { - module: vertex_module, - entry_point: vertex_entry_point.as_str(), - }, - fragment_stage, - primitive_topology, - rasterization_state: Some(rasterization_state), - color_states: color_states.as_slice(), - depth_stencil_state, - vertex_state: wgt::VertexStateDescriptor { - index_format: vertex_state.0, - vertex_buffers: vert_buffers.as_slice(), - }, - sample_count, - sample_mask, - alpha_to_coverage_enabled, - }; - let result = gfx_select!(render_pipeline_id => global.device_create_render_pipeline(device_id, &descriptor, render_pipeline_id)); if let Some(s_id) = scope_id { @@ -1117,7 +995,7 @@ impl<'a> WGPU<'a> { self.present_buffer_maps.get(&buffer_id).unwrap().clone(), ), }; - gfx_select!(buffer_id => global.buffer_map_async(buffer_id, 0..buffer_size, map_op)); + let _ = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, 0..buffer_size, map_op)); }, WebGPURequest::UnmapBuffer { buffer_id, @@ -1132,11 +1010,12 @@ impl<'a> WGPU<'a> { buffer_id, offset, wgt::BufferSize::new(size) - )); + )) + .unwrap(); unsafe { slice::from_raw_parts_mut(map_ptr, size as usize) } .copy_from_slice(&array_buffer); } - gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); + let _ = gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); }, WebGPURequest::UpdateWebRenderData { buffer_id, @@ -1145,7 +1024,8 @@ impl<'a> WGPU<'a> { } => { let global = &self.global; let data_pt = gfx_select!(buffer_id => - global.buffer_get_mapped_range(buffer_id, 0, None)); + global.buffer_get_mapped_range(buffer_id, 0, None)) + .unwrap(); let data = unsafe { slice::from_raw_parts(data_pt, buffer_size) }.to_vec(); if let Some(present_data) = self.wgpu_image_map.lock().unwrap().get_mut(&external_id) @@ -1167,7 +1047,7 @@ impl<'a> WGPU<'a> { } else { warn!("Data not found for ExternalImageId({:?})", external_id); } - gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); + let _ = gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); self.present_buffer_maps.remove(&buffer_id); }, WebGPURequest::WriteBuffer { From aff22db33ff237e0fd677671851e3919007f20ef Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Wed, 22 Jul 2020 17:52:49 +0530 Subject: [PATCH 2/2] Implement GPURenderBundleEncoder and GPURenderBundle --- Cargo.lock | 8 +- components/script/dom/bindings/trace.rs | 8 +- components/script/dom/gpuadapter.rs | 3 + components/script/dom/gpubindgroup.rs | 8 +- components/script/dom/gpubindgrouplayout.rs | 12 +- components/script/dom/gpubuffer.rs | 6 +- components/script/dom/gpucanvascontext.rs | 8 +- components/script/dom/gpucommandbuffer.rs | 5 +- components/script/dom/gpucommandencoder.rs | 26 ++- .../script/dom/gpucomputepassencoder.rs | 19 +- components/script/dom/gpucomputepipeline.rs | 12 +- components/script/dom/gpudevice.rs | 124 +++++++--- components/script/dom/gpupipelinelayout.rs | 12 +- components/script/dom/gpurenderbundle.rs | 75 ++++++ .../script/dom/gpurenderbundleencoder.rs | 213 ++++++++++++++++++ components/script/dom/gpurenderpassencoder.rs | 45 +++- components/script/dom/gpurenderpipeline.rs | 15 +- components/script/dom/gpusampler.rs | 17 +- components/script/dom/gpushadermodule.rs | 12 +- components/script/dom/gpuswapchain.rs | 14 +- components/script/dom/gputexture.rs | 12 +- components/script/dom/gputextureview.rs | 11 +- components/script/dom/identityhub.rs | 14 +- components/script/dom/mod.rs | 2 + .../script/dom/webidls/GPUDevice.webidl | 4 +- .../script/dom/webidls/GPURenderBundle.webidl | 12 + .../dom/webidls/GPURenderBundleEncoder.webidl | 18 ++ .../dom/webidls/GPURenderPassEncoder.webidl | 9 +- .../dom/webidls/GPURenderPipeline.webidl | 2 + components/script/script_thread.rs | 1 + components/webgpu/identity.rs | 4 +- components/webgpu/lib.rs | 60 +++-- 32 files changed, 676 insertions(+), 115 deletions(-) create mode 100644 components/script/dom/gpurenderbundle.rs create mode 100644 components/script/dom/gpurenderbundleencoder.rs create mode 100644 components/script/dom/webidls/GPURenderBundle.webidl create mode 100644 components/script/dom/webidls/GPURenderBundleEncoder.webidl diff --git a/Cargo.lock b/Cargo.lock index f7339cbfa0f9..dbc96983a4e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3642,13 +3642,14 @@ checksum = "0419348c027fa7be448d2ae7ea0e4e04c2334c31dc4e74ab29f00a2a7ca69204" [[package]] name = "naga" version = "0.1.0" -source = "git+https://github.com/gfx-rs/naga?rev=a9228d2aed38c71388489a95817238ff98198fa3#a9228d2aed38c71388489a95817238ff98198fa3" +source = "git+https://github.com/gfx-rs/naga?rev=94802078c3bc5d138f497419ea3e7a869f10916d#94802078c3bc5d138f497419ea3e7a869f10916d" dependencies = [ "bitflags", "fxhash", "log", "num-traits", "spirv_headers", + "thiserror", ] [[package]] @@ -6861,7 +6862,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#4ed2c0a313deb48a99f15e8fe0558ad3d095ca01" +source = "git+https://github.com/gfx-rs/wgpu#8a2ee26fffcdf02fc5e7f0a29771f4720522f7d8" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -6881,7 +6882,6 @@ dependencies = [ "ron", "serde", "smallvec 1.4.1", - "spirv_headers", "thiserror", "tracing", "wgpu-types", @@ -6890,7 +6890,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#4ed2c0a313deb48a99f15e8fe0558ad3d095ca01" +source = "git+https://github.com/gfx-rs/wgpu#8a2ee26fffcdf02fc5e7f0a29771f4720522f7d8" dependencies = [ "bitflags", "serde", diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index a752b129a124..a5496a7cc170 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -168,12 +168,12 @@ use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{ - wgpu::command::{ComputePass, RenderPass}, + wgpu::command::{ComputePass, RenderBundleEncoder, RenderPass}, wgt::BindGroupLayoutEntry, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice, - WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule, - WebGPUTexture, WebGPUTextureView, + WebGPUPipelineLayout, WebGPUQueue, WebGPURenderBundle, WebGPURenderPipeline, WebGPUSampler, + WebGPUShaderModule, WebGPUTexture, WebGPUTextureView, }; use webrender_api::{DocumentId, ExternalImageId, ImageKey}; use webxr_api::{Finger, Hand, Ray, View}; @@ -618,6 +618,7 @@ unsafe_no_jsmanaged_fields!(WebGPUBindGroup); unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(WebGPUComputePipeline); unsafe_no_jsmanaged_fields!(WebGPURenderPipeline); +unsafe_no_jsmanaged_fields!(WebGPURenderBundle); unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout); unsafe_no_jsmanaged_fields!(WebGPUQueue); unsafe_no_jsmanaged_fields!(WebGPUShaderModule); @@ -630,6 +631,7 @@ unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder); unsafe_no_jsmanaged_fields!(WebGPUDevice); unsafe_no_jsmanaged_fields!(BindGroupLayoutEntry); unsafe_no_jsmanaged_fields!(Option); +unsafe_no_jsmanaged_fields!(Option); unsafe_no_jsmanaged_fields!(Option); unsafe_no_jsmanaged_fields!(GPUBufferState); unsafe_no_jsmanaged_fields!(GPUCommandEncoderState); diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index afab6b89d096..9392f1414fa3 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -103,6 +103,7 @@ impl GPUAdapterMethods for GPUAdapter { descriptor: desc, device_id: id, pipeline_id, + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), }) .is_err() { @@ -119,6 +120,7 @@ impl AsyncWGPUListener for GPUAdapter { device_id, queue_id, _descriptor, + label, } => { let device = GPUDevice::new( &self.global(), @@ -128,6 +130,7 @@ impl AsyncWGPUListener for GPUAdapter { Heap::default(), device_id, queue_id, + label, ); self.global().add_gpu_device(&device); promise.resolve_native(&device); diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs index 458a437eed4b..394cf41e9152 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -26,10 +26,11 @@ impl GPUBindGroup { bind_group: WebGPUBindGroup, device: WebGPUDevice, layout: &GPUBindGroupLayout, + label: Option, ) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), bind_group, device, layout: Dom::from_ref(layout), @@ -41,9 +42,12 @@ impl GPUBindGroup { bind_group: WebGPUBindGroup, device: WebGPUDevice, layout: &GPUBindGroupLayout, + label: Option, ) -> DomRoot { reflect_dom_object( - Box::new(GPUBindGroup::new_inherited(bind_group, device, layout)), + Box::new(GPUBindGroup::new_inherited( + bind_group, device, layout, label, + )), global, ) } diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index 622981ebb4d4..ce794269359b 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -19,17 +19,21 @@ pub struct GPUBindGroupLayout { } impl GPUBindGroupLayout { - fn new_inherited(bind_group_layout: WebGPUBindGroupLayout) -> Self { + fn new_inherited(bind_group_layout: WebGPUBindGroupLayout, label: Option) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), bind_group_layout, } } - pub fn new(global: &GlobalScope, bind_group_layout: WebGPUBindGroupLayout) -> DomRoot { + pub fn new( + global: &GlobalScope, + bind_group_layout: WebGPUBindGroupLayout, + label: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout)), + Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout, label)), global, ) } diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index c7629852d924..1a9c9d14f2f2 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -76,11 +76,12 @@ impl GPUBuffer { state: GPUBufferState, size: GPUSize64, map_info: DomRefCell>, + label: Option, ) -> Self { Self { reflector_: Reflector::new(), channel, - label: DomRefCell::new(None), + label: DomRefCell::new(label), state: Cell::new(state), device, buffer, @@ -99,10 +100,11 @@ impl GPUBuffer { state: GPUBufferState, size: GPUSize64, map_info: DomRefCell>, + label: Option, ) -> DomRoot { reflect_dom_object( Box::new(GPUBuffer::new_inherited( - channel, buffer, device, state, size, map_info, + channel, buffer, device, state, size, map_info, label, )), global, ) diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs index ca059fdec979..511f78634efe 100644 --- a/components/script/dom/gpucanvascontext.rs +++ b/components/script/dom/gpucanvascontext.rs @@ -201,7 +201,13 @@ impl GPUCanvasContextMethods for GPUCanvasContext { self.webrender_image.set(Some(receiver.recv().unwrap())); - let swap_chain = GPUSwapChain::new(&self.global(), self.channel.clone(), &self, &*texture); + let swap_chain = GPUSwapChain::new( + &self.global(), + self.channel.clone(), + &self, + &*texture, + descriptor.parent.label.as_ref().cloned(), + ); *self.swap_chain.borrow_mut() = Some(Dom::from_ref(&*swap_chain)); swap_chain } diff --git a/components/script/dom/gpucommandbuffer.rs b/components/script/dom/gpucommandbuffer.rs index 7c7f03629d9b..6e1eb8446f0b 100644 --- a/components/script/dom/gpucommandbuffer.rs +++ b/components/script/dom/gpucommandbuffer.rs @@ -37,11 +37,12 @@ impl GPUCommandBuffer { channel: WebGPU, command_buffer: WebGPUCommandBuffer, buffers: HashSet>, + label: Option, ) -> Self { Self { channel, reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), command_buffer, buffers: DomRefCell::new(buffers.into_iter().map(|b| Dom::from_ref(&*b)).collect()), } @@ -52,12 +53,14 @@ impl GPUCommandBuffer { channel: WebGPU, command_buffer: WebGPUCommandBuffer, buffers: HashSet>, + label: Option, ) -> DomRoot { reflect_dom_object( Box::new(GPUCommandBuffer::new_inherited( channel, command_buffer, buffers, + label, )), global, ) diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 4f297fadb1b5..8d8311eeae18 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -59,11 +59,12 @@ impl GPUCommandEncoder { device: WebGPUDevice, encoder: webgpu::WebGPUCommandEncoder, valid: bool, + label: Option, ) -> Self { Self { channel, reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), device, encoder, buffers: DomRefCell::new(HashSet::new()), @@ -78,10 +79,11 @@ impl GPUCommandEncoder { device: WebGPUDevice, encoder: webgpu::WebGPUCommandEncoder, valid: bool, + label: Option, ) -> DomRoot { reflect_dom_object( Box::new(GPUCommandEncoder::new_inherited( - channel, device, encoder, valid, + channel, device, encoder, valid, label, )), global, ) @@ -117,13 +119,18 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-begincomputepass fn BeginComputePass( &self, - _descriptor: &GPUComputePassDescriptor, + descriptor: &GPUComputePassDescriptor, ) -> DomRoot { self.set_state( GPUCommandEncoderState::EncodingComputePass, GPUCommandEncoderState::Open, ); - GPUComputePassEncoder::new(&self.global(), self.channel.clone(), &self) + GPUComputePassEncoder::new( + &self.global(), + self.channel.clone(), + &self, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-beginrenderpass @@ -228,7 +235,13 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { let render_pass = wgpu_com::RenderPass::new(self.encoder.0, desc); - GPURenderPassEncoder::new(&self.global(), self.channel.clone(), render_pass, &self) + GPURenderPassEncoder::new( + &self.global(), + self.channel.clone(), + render_pass, + &self, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertobuffer @@ -352,7 +365,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { } /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish - fn Finish(&self, _descriptor: &GPUCommandBufferDescriptor) -> DomRoot { + fn Finish(&self, descriptor: &GPUCommandBufferDescriptor) -> DomRoot { self.channel .0 .send(WebGPURequest::CommandEncoderFinish { @@ -369,6 +382,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { self.channel.clone(), buffer, self.buffers.borrow_mut().drain().collect(), + descriptor.parent.label.as_ref().cloned(), ) } } diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs index 2f4535d835ec..1cfcdf7a25c5 100644 --- a/components/script/dom/gpucomputepassencoder.rs +++ b/components/script/dom/gpucomputepassencoder.rs @@ -30,19 +30,28 @@ pub struct GPUComputePassEncoder { } impl GPUComputePassEncoder { - fn new_inherited(channel: WebGPU, parent: &GPUCommandEncoder) -> Self { + fn new_inherited( + channel: WebGPU, + parent: &GPUCommandEncoder, + label: Option, + ) -> Self { Self { channel, reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), compute_pass: DomRefCell::new(Some(ComputePass::new(parent.id().0))), command_encoder: Dom::from_ref(parent), } } - pub fn new(global: &GlobalScope, channel: WebGPU, parent: &GPUCommandEncoder) -> DomRoot { + pub fn new( + global: &GlobalScope, + channel: WebGPU, + parent: &GPUCommandEncoder, + label: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUComputePassEncoder::new_inherited(channel, parent)), + Box::new(GPUComputePassEncoder::new_inherited(channel, parent, label)), global, ) } @@ -86,7 +95,7 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { command_encoder_id: self.command_encoder.id().0, compute_pass, }) - .unwrap(); + .expect("Failed to send RunComputePass"); self.command_encoder.set_state( GPUCommandEncoderState::Open, diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs index a5b7fbc495d5..598c6a7caee2 100644 --- a/components/script/dom/gpucomputepipeline.rs +++ b/components/script/dom/gpucomputepipeline.rs @@ -20,17 +20,21 @@ pub struct GPUComputePipeline { } impl GPUComputePipeline { - fn new_inherited(compute_pipeline: WebGPUComputePipeline) -> Self { + fn new_inherited(compute_pipeline: WebGPUComputePipeline, label: Option) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), compute_pipeline, } } - pub fn new(global: &GlobalScope, compute_pipeline: WebGPUComputePipeline) -> DomRoot { + pub fn new( + global: &GlobalScope, + compute_pipeline: WebGPUComputePipeline, + label: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUComputePipeline::new_inherited(compute_pipeline)), + Box::new(GPUComputePipeline::new_inherited(compute_pipeline, label)), global, ) } diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index a1d2c19c58cd..1cd9c7653ed4 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -17,6 +17,7 @@ use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{ GPUCommandEncoderDescriptor, GPUDeviceMethods, }; use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor; +use crate::dom::bindings::codegen::Bindings::GPURenderBundleEncoderBinding::GPURenderBundleEncoderDescriptor; use crate::dom::bindings::codegen::Bindings::GPURenderPipelineBinding::{ GPUBlendDescriptor, GPUBlendFactor, GPUBlendOperation, GPUCullMode, GPUFrontFace, GPUIndexFormat, GPUInputStepMode, GPUPrimitiveTopology, GPURenderPipelineDescriptor, @@ -50,6 +51,7 @@ use crate::dom::gpucommandencoder::GPUCommandEncoder; use crate::dom::gpucomputepipeline::GPUComputePipeline; use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpuqueue::GPUQueue; +use crate::dom::gpurenderbundleencoder::GPURenderBundleEncoder; use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; @@ -64,8 +66,9 @@ use std::cell::RefCell; use std::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; -use std::string::String; -use webgpu::wgpu::{binding_model as wgpu_bind, pipeline as wgpu_pipe}; +use webgpu::wgpu::{ + binding_model as wgpu_bind, command::RenderBundleEncoder, pipeline as wgpu_pipe, +}; use webgpu::{self, wgt, WebGPU, WebGPURequest}; type ErrorScopeId = u64; @@ -116,6 +119,7 @@ impl GPUDevice { limits: Heap<*mut JSObject>, device: webgpu::WebGPUDevice, queue: &GPUQueue, + label: Option, ) -> Self { Self { eventtarget: EventTarget::new_inherited(), @@ -123,7 +127,7 @@ impl GPUDevice { adapter: Dom::from_ref(adapter), extensions, limits, - label: DomRefCell::new(None), + label: DomRefCell::new(label.map(|l| USVString::from(l))), device, default_queue: Dom::from_ref(queue), scope_context: DomRefCell::new(ScopeContext { @@ -144,11 +148,12 @@ impl GPUDevice { limits: Heap<*mut JSObject>, device: webgpu::WebGPUDevice, queue: webgpu::WebGPUQueue, + label: Option, ) -> DomRoot { let queue = GPUQueue::new(global, channel.clone(), queue); reflect_dom_object( Box::new(GPUDevice::new_inherited( - channel, adapter, extensions, limits, device, &queue, + channel, adapter, extensions, limits, device, &queue, label, )), global, ) @@ -247,11 +252,7 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot { let wgpu_descriptor = wgt::BufferDescriptor { - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), size: descriptor.size, usage: match wgt::BufferUsage::from_bits(descriptor.usage) { Some(u) => u, @@ -299,6 +300,7 @@ impl GPUDeviceMethods for GPUDevice { state, descriptor.size, map_info, + descriptor.parent.label.as_ref().cloned(), ) } @@ -427,7 +429,11 @@ impl GPUDeviceMethods for GPUDevice { let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); - let layout = GPUBindGroupLayout::new(&self.global(), bgl); + let layout = GPUBindGroupLayout::new( + &self.global(), + bgl, + descriptor.parent.label.as_ref().cloned(), + ); self.bind_group_layouts .borrow_mut() @@ -470,7 +476,11 @@ impl GPUDeviceMethods for GPUDevice { .expect("Failed to create WebGPU PipelineLayout"); let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id); - GPUPipelineLayout::new(&self.global(), pipeline_layout) + GPUPipelineLayout::new( + &self.global(), + pipeline_layout, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup @@ -527,7 +537,13 @@ impl GPUDeviceMethods for GPUDevice { let bind_group = webgpu::WebGPUBindGroup(bind_group_id); - GPUBindGroup::new(&self.global(), bind_group, self.device, &*descriptor.layout) + GPUBindGroup::new( + &self.global(), + bind_group, + self.device, + &*descriptor.layout, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule @@ -556,7 +572,11 @@ impl GPUDeviceMethods for GPUDevice { .expect("Failed to create WebGPU ShaderModule"); let shader_module = webgpu::WebGPUShaderModule(program_id); - GPUShaderModule::new(&self.global(), shader_module) + GPUShaderModule::new( + &self.global(), + shader_module, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline @@ -591,7 +611,11 @@ impl GPUDeviceMethods for GPUDevice { .expect("Failed to create WebGPU ComputePipeline"); let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); - GPUComputePipeline::new(&self.global(), compute_pipeline) + GPUComputePipeline::new( + &self.global(), + compute_pipeline, + descriptor.parent.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder @@ -609,11 +633,7 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateCommandEncoder { device_id: self.device.0, command_encoder_id, - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), }) .expect("Failed to create WebGPU command encoder"); @@ -625,6 +645,7 @@ impl GPUDeviceMethods for GPUDevice { self.device, encoder, true, + descriptor.parent.label.as_ref().cloned(), ) } @@ -632,11 +653,7 @@ impl GPUDeviceMethods for GPUDevice { fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> DomRoot { let size = convert_texture_size_to_dict(&descriptor.size); let desc = wgt::TextureDescriptor { - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), size: convert_texture_size_to_wgt(&size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, @@ -680,6 +697,7 @@ impl GPUDeviceMethods for GPUDevice { descriptor.dimension, descriptor.format, descriptor.usage, + descriptor.parent.label.as_ref().cloned(), ) } @@ -692,11 +710,7 @@ impl GPUDeviceMethods for GPUDevice { .create_sampler_id(self.device.0.backend()); let compare_enable = descriptor.compare.is_some(); let desc = wgt::SamplerDescriptor { - label: descriptor - .parent - .label - .as_ref() - .map(|s| String::from(s.as_ref())), + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), address_mode_u: convert_address_mode(descriptor.addressModeU), address_mode_v: convert_address_mode(descriptor.addressModeV), address_mode_w: convert_address_mode(descriptor.addressModeW), @@ -720,7 +734,13 @@ impl GPUDeviceMethods for GPUDevice { let sampler = webgpu::WebGPUSampler(sampler_id); - GPUSampler::new(&self.global(), self.device, compare_enable, sampler) + GPUSampler::new( + &self.global(), + self.device, + compare_enable, + sampler, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline @@ -753,6 +773,7 @@ impl GPUDeviceMethods for GPUDevice { GPUCullMode::Front => wgt::CullMode::Front, GPUCullMode::Back => wgt::CullMode::Back, }, + clamp_depth: rs_desc.clampDepth, depth_bias: rs_desc.depthBias, depth_bias_slope_scale: *rs_desc.depthBiasSlopeScale, depth_bias_clamp: *rs_desc.depthBiasClamp, @@ -855,7 +876,48 @@ impl GPUDeviceMethods for GPUDevice { let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); - GPURenderPipeline::new(&self.global(), render_pipeline, self.device) + GPURenderPipeline::new( + &self.global(), + render_pipeline, + self.device, + descriptor.parent.parent.label.as_ref().cloned(), + ) + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderbundleencoder + fn CreateRenderBundleEncoder( + &self, + descriptor: &GPURenderBundleEncoderDescriptor, + ) -> DomRoot { + let desc = wgt::RenderBundleEncoderDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + color_formats: Cow::Owned( + descriptor + .colorFormats + .iter() + .map(|f| convert_texture_format(*f)) + .collect::>(), + ), + depth_stencil_format: descriptor + .depthStencilFormat + .map(|f| convert_texture_format(f)), + sample_count: descriptor.sampleCount, + }; + + // Handle error gracefully + let render_bundle_encoder = RenderBundleEncoder::new(&desc, self.device.0, None).unwrap(); + + GPURenderBundleEncoder::new( + &self.global(), + render_bundle_encoder, + self.device, + self.channel.clone(), + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index d08098196009..7547adce8433 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -19,17 +19,21 @@ pub struct GPUPipelineLayout { } impl GPUPipelineLayout { - fn new_inherited(pipeline_layout: WebGPUPipelineLayout) -> Self { + fn new_inherited(pipeline_layout: WebGPUPipelineLayout, label: Option) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), pipeline_layout, } } - pub fn new(global: &GlobalScope, pipeline_layout: WebGPUPipelineLayout) -> DomRoot { + pub fn new( + global: &GlobalScope, + pipeline_layout: WebGPUPipelineLayout, + label: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUPipelineLayout::new_inherited(pipeline_layout)), + Box::new(GPUPipelineLayout::new_inherited(pipeline_layout, label)), global, ) } diff --git a/components/script/dom/gpurenderbundle.rs b/components/script/dom/gpurenderbundle.rs new file mode 100644 index 000000000000..5c020f8f697a --- /dev/null +++ b/components/script/dom/gpurenderbundle.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::GPURenderBundleBinding::GPURenderBundleMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::USVString; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; +use webgpu::{WebGPU, WebGPUDevice, WebGPURenderBundle}; + +#[dom_struct] +pub struct GPURenderBundle { + reflector_: Reflector, + #[ignore_malloc_size_of = "channels are hard"] + channel: WebGPU, + device: WebGPUDevice, + render_bundle: WebGPURenderBundle, + label: DomRefCell>, +} + +impl GPURenderBundle { + fn new_inherited( + render_bundle: WebGPURenderBundle, + device: WebGPUDevice, + channel: WebGPU, + label: Option, + ) -> Self { + Self { + reflector_: Reflector::new(), + render_bundle, + device, + channel, + label: DomRefCell::new(label), + } + } + + pub fn new( + global: &GlobalScope, + render_bundle: WebGPURenderBundle, + device: WebGPUDevice, + channel: WebGPU, + label: Option, + ) -> DomRoot { + reflect_dom_object( + Box::new(GPURenderBundle::new_inherited( + render_bundle, + device, + channel, + label, + )), + global, + ) + } +} + +impl GPURenderBundle { + pub fn id(&self) -> WebGPURenderBundle { + self.render_bundle + } +} + +impl GPURenderBundleMethods for GPURenderBundle { + /// 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/gpurenderbundleencoder.rs b/components/script/dom/gpurenderbundleencoder.rs new file mode 100644 index 000000000000..5759b09b299c --- /dev/null +++ b/components/script/dom/gpurenderbundleencoder.rs @@ -0,0 +1,213 @@ +/* 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::GPURenderBundleBinding::GPURenderBundleDescriptor; +use crate::dom::bindings::codegen::Bindings::GPURenderBundleEncoderBinding::GPURenderBundleEncoderMethods; +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::gpubindgroup::GPUBindGroup; +use crate::dom::gpubuffer::GPUBuffer; +use crate::dom::gpurenderbundle::GPURenderBundle; +use crate::dom::gpurenderpipeline::GPURenderPipeline; +use dom_struct::dom_struct; +use webgpu::{ + wgpu::command::{bundle_ffi as wgpu_bundle, RenderBundleEncoder}, + wgt, WebGPU, WebGPUDevice, WebGPURenderBundle, WebGPURequest, +}; + +#[dom_struct] +pub struct GPURenderBundleEncoder { + reflector_: Reflector, + #[ignore_malloc_size_of = "channels are hard"] + channel: WebGPU, + device: WebGPUDevice, + #[ignore_malloc_size_of = "defined in wgpu-core"] + render_bundle_encoder: DomRefCell>, + label: DomRefCell>, +} + +impl GPURenderBundleEncoder { + fn new_inherited( + render_bundle_encoder: RenderBundleEncoder, + device: WebGPUDevice, + channel: WebGPU, + label: Option, + ) -> Self { + Self { + reflector_: Reflector::new(), + render_bundle_encoder: DomRefCell::new(Some(render_bundle_encoder)), + device, + channel, + label: DomRefCell::new(label), + } + } + + pub fn new( + global: &GlobalScope, + render_bundle_encoder: RenderBundleEncoder, + device: WebGPUDevice, + channel: WebGPU, + label: Option, + ) -> DomRoot { + reflect_dom_object( + Box::new(GPURenderBundleEncoder::new_inherited( + render_bundle_encoder, + device, + channel, + label, + )), + global, + ) + } +} + +impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder { + /// 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; + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup + #[allow(unsafe_code)] + fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, dynamic_offsets: Vec) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + unsafe { + wgpu_bundle::wgpu_render_bundle_set_bind_group( + encoder, + index, + bind_group.id().0, + dynamic_offsets.as_ptr(), + dynamic_offsets.len(), + ) + }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setpipeline + fn SetPipeline(&self, pipeline: &GPURenderPipeline) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_set_pipeline(encoder, pipeline.id().0); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setindexbuffer + fn SetIndexBuffer(&self, buffer: &GPUBuffer, offset: u64, size: u64) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_set_index_buffer( + encoder, + buffer.id().0, + offset, + wgt::BufferSize::new(size), + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setvertexbuffer + fn SetVertexBuffer(&self, slot: u32, buffer: &GPUBuffer, offset: u64, size: u64) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_set_vertex_buffer( + encoder, + slot, + buffer.id().0, + offset, + wgt::BufferSize::new(size), + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-draw + fn Draw(&self, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_draw( + encoder, + vertex_count, + instance_count, + first_vertex, + first_instance, + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindexed + fn DrawIndexed( + &self, + index_count: u32, + instance_count: u32, + first_index: u32, + base_vertex: i32, + first_instance: u32, + ) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_draw_indexed( + encoder, + index_count, + instance_count, + first_index, + base_vertex, + first_instance, + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindirect + fn DrawIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_bundle_draw_indirect( + encoder, + indirect_buffer.id().0, + indirect_offset, + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindexedindirect + fn DrawIndexedIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) { + if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() { + wgpu_bundle::wgpu_render_pass_bundle_indexed_indirect( + encoder, + indirect_buffer.id().0, + indirect_offset, + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderbundleencoder-finish + fn Finish(&self, descriptor: &GPURenderBundleDescriptor) -> DomRoot { + let desc = wgt::RenderBundleDescriptor { + label: descriptor.parent.label.as_ref().map(|s| s.to_string()), + }; + let encoder = self.render_bundle_encoder.borrow_mut().take().unwrap(); + let render_bundle_id = self + .global() + .wgpu_id_hub() + .lock() + .create_render_bundle_id(self.device.0.backend()); + + self.channel + .0 + .send(WebGPURequest::RenderBundleEncoderFinish { + render_bundle_encoder: encoder, + descriptor: desc, + render_bundle_id, + }) + .expect("Failed to send RenderBundleEncoderFinish"); + + let render_bundle = WebGPURenderBundle(render_bundle_id); + GPURenderBundle::new( + &self.global(), + render_bundle, + self.device, + self.channel.clone(), + descriptor.parent.label.as_ref().cloned(), + ) + } +} diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs index ba8cf0a65d2d..a3c620e7ee2b 100644 --- a/components/script/dom/gpurenderpassencoder.rs +++ b/components/script/dom/gpurenderpassencoder.rs @@ -13,6 +13,7 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::gpubindgroup::GPUBindGroup; use crate::dom::gpubuffer::GPUBuffer; use crate::dom::gpucommandencoder::{GPUCommandEncoder, GPUCommandEncoderState}; +use crate::dom::gpurenderbundle::GPURenderBundle; use crate::dom::gpurenderpipeline::GPURenderPipeline; use dom_struct::dom_struct; use webgpu::{ @@ -32,11 +33,16 @@ pub struct GPURenderPassEncoder { } impl GPURenderPassEncoder { - fn new_inherited(channel: WebGPU, render_pass: RenderPass, parent: &GPUCommandEncoder) -> Self { + fn new_inherited( + channel: WebGPU, + render_pass: RenderPass, + parent: &GPUCommandEncoder, + label: Option, + ) -> Self { Self { channel, reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), render_pass: DomRefCell::new(Some(render_pass)), command_encoder: Dom::from_ref(parent), } @@ -47,12 +53,14 @@ impl GPURenderPassEncoder { channel: WebGPU, render_pass: RenderPass, parent: &GPUCommandEncoder, + label: Option, ) -> DomRoot { reflect_dom_object( Box::new(GPURenderPassEncoder::new_inherited( channel, render_pass, parent, + label, )), global, ) @@ -125,11 +133,17 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder { b: *d.b, a: *d.a, }, - GPUColor::DoubleSequence(s) => wgt::Color { - r: *s[0], - g: *s[1], - b: *s[2], - a: *s[3], + GPUColor::DoubleSequence(mut s) => { + if s.len() < 3 { + s.resize(3, Finite::wrap(0.0f64)); + } + s.resize(4, Finite::wrap(1.0f64)); + wgt::Color { + r: *s[0], + g: *s[1], + b: *s[2], + a: *s[3], + } }, }; if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() { @@ -153,7 +167,7 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder { command_encoder_id: self.command_encoder.id().0, render_pass, }) - .unwrap(); + .expect("Failed to send RunRenderPass"); self.command_encoder.set_state( GPUCommandEncoderState::Open, @@ -249,4 +263,19 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder { ); } } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-executebundles + #[allow(unsafe_code)] + fn ExecuteBundles(&self, bundles: Vec>) { + let bundle_ids = bundles.iter().map(|b| b.id().0).collect::>(); + if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_execute_bundles( + render_pass, + bundle_ids.as_ptr(), + bundle_ids.len(), + ) + }; + } + } } diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs index 88e55848b917..bb618a248a92 100644 --- a/components/script/dom/gpurenderpipeline.rs +++ b/components/script/dom/gpurenderpipeline.rs @@ -21,10 +21,14 @@ pub struct GPURenderPipeline { } impl GPURenderPipeline { - fn new_inherited(render_pipeline: WebGPURenderPipeline, device: WebGPUDevice) -> Self { + fn new_inherited( + render_pipeline: WebGPURenderPipeline, + device: WebGPUDevice, + label: Option, + ) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), render_pipeline, device, } @@ -34,9 +38,14 @@ impl GPURenderPipeline { global: &GlobalScope, render_pipeline: WebGPURenderPipeline, device: WebGPUDevice, + label: Option, ) -> DomRoot { reflect_dom_object( - Box::new(GPURenderPipeline::new_inherited(render_pipeline, device)), + Box::new(GPURenderPipeline::new_inherited( + render_pipeline, + device, + label, + )), global, ) } diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs index cba3ec3b018c..23395ee058cb 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -21,10 +21,15 @@ pub struct GPUSampler { } impl GPUSampler { - fn new_inherited(device: WebGPUDevice, compare_enable: bool, sampler: WebGPUSampler) -> Self { + fn new_inherited( + device: WebGPUDevice, + compare_enable: bool, + sampler: WebGPUSampler, + label: Option, + ) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), device, sampler, compare_enable, @@ -36,9 +41,15 @@ impl GPUSampler { device: WebGPUDevice, compare_enable: bool, sampler: WebGPUSampler, + label: Option, ) -> DomRoot { reflect_dom_object( - Box::new(GPUSampler::new_inherited(device, compare_enable, sampler)), + Box::new(GPUSampler::new_inherited( + device, + compare_enable, + sampler, + label, + )), global, ) } diff --git a/components/script/dom/gpushadermodule.rs b/components/script/dom/gpushadermodule.rs index 3c752e7fe4ab..c4f20124ea8f 100644 --- a/components/script/dom/gpushadermodule.rs +++ b/components/script/dom/gpushadermodule.rs @@ -19,17 +19,21 @@ pub struct GPUShaderModule { } impl GPUShaderModule { - fn new_inherited(shader_module: WebGPUShaderModule) -> Self { + fn new_inherited(shader_module: WebGPUShaderModule, label: Option) -> Self { Self { reflector_: Reflector::new(), - label: DomRefCell::new(None), + label: DomRefCell::new(label), shader_module, } } - pub fn new(global: &GlobalScope, shader_module: WebGPUShaderModule) -> DomRoot { + pub fn new( + global: &GlobalScope, + shader_module: WebGPUShaderModule, + label: Option, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUShaderModule::new_inherited(shader_module)), + Box::new(GPUShaderModule::new_inherited(shader_module, label)), global, ) } diff --git a/components/script/dom/gpuswapchain.rs b/components/script/dom/gpuswapchain.rs index 5e50e7e57abb..1d50a00f40a8 100644 --- a/components/script/dom/gpuswapchain.rs +++ b/components/script/dom/gpuswapchain.rs @@ -24,13 +24,18 @@ pub struct GPUSwapChain { } impl GPUSwapChain { - fn new_inherited(channel: WebGPU, context: &GPUCanvasContext, texture: &GPUTexture) -> Self { + fn new_inherited( + channel: WebGPU, + context: &GPUCanvasContext, + texture: &GPUTexture, + label: Option, + ) -> Self { Self { reflector_: Reflector::new(), channel, context: Dom::from_ref(context), texture: Dom::from_ref(texture), - label: DomRefCell::new(None), + label: DomRefCell::new(label), } } @@ -39,9 +44,12 @@ impl GPUSwapChain { channel: WebGPU, context: &GPUCanvasContext, texture: &GPUTexture, + label: Option, ) -> DomRoot { reflect_dom_object( - Box::new(GPUSwapChain::new_inherited(channel, context, texture)), + Box::new(GPUSwapChain::new_inherited( + channel, context, texture, label, + )), global, ) } diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 4977207942e6..4a6256ee3690 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -47,11 +47,12 @@ impl GPUTexture { dimension: GPUTextureDimension, format: GPUTextureFormat, texture_usage: u32, + label: Option, ) -> Self { Self { reflector_: Reflector::new(), texture, - label: DomRefCell::new(None), + label: DomRefCell::new(label), device, channel, texture_size, @@ -74,6 +75,7 @@ impl GPUTexture { dimension: GPUTextureDimension, format: GPUTextureFormat, texture_usage: u32, + label: Option, ) -> DomRoot { reflect_dom_object( Box::new(GPUTexture::new_inherited( @@ -86,6 +88,7 @@ impl GPUTexture { dimension, format, texture_usage, + label, )), global, ) @@ -179,7 +182,12 @@ impl GPUTextureMethods for GPUTexture { let texture_view = WebGPUTextureView(texture_view_id); - GPUTextureView::new(&self.global(), texture_view, &self) + GPUTextureView::new( + &self.global(), + texture_view, + &self, + descriptor.parent.label.as_ref().cloned(), + ) } /// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index 208352f3ff7f..af346d922506 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -21,11 +21,15 @@ pub struct GPUTextureView { } impl GPUTextureView { - fn new_inherited(texture_view: WebGPUTextureView, texture: &GPUTexture) -> GPUTextureView { + fn new_inherited( + texture_view: WebGPUTextureView, + texture: &GPUTexture, + label: Option, + ) -> GPUTextureView { Self { reflector_: Reflector::new(), texture: Dom::from_ref(texture), - label: DomRefCell::new(None), + label: DomRefCell::new(label), texture_view, } } @@ -34,9 +38,10 @@ impl GPUTextureView { global: &GlobalScope, texture_view: WebGPUTextureView, texture: &GPUTexture, + label: Option, ) -> DomRoot { reflect_dom_object( - Box::new(GPUTextureView::new_inherited(texture_view, texture)), + Box::new(GPUTextureView::new_inherited(texture_view, texture, label)), global, ) } diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index 3862702561e9..515e9f7e1b13 100644 --- a/components/script/dom/identityhub.rs +++ b/components/script/dom/identityhub.rs @@ -7,8 +7,8 @@ use webgpu::wgpu::{ hub::IdentityManager, id::{ AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId, - DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, TextureId, - TextureViewId, + DeviceId, PipelineLayoutId, RenderBundleId, RenderPipelineId, SamplerId, ShaderModuleId, + TextureId, TextureViewId, }, }; use webgpu::wgt::Backend; @@ -28,6 +28,7 @@ pub struct IdentityHub { texture_views: IdentityManager, samplers: IdentityManager, render_pipelines: IdentityManager, + render_bundles: IdentityManager, } impl IdentityHub { @@ -46,6 +47,7 @@ impl IdentityHub { texture_views: IdentityManager::default(), samplers: IdentityManager::default(), render_pipelines: IdentityManager::default(), + render_bundles: IdentityManager::default(), } } } @@ -215,4 +217,12 @@ impl Identities { pub fn kill_texture_view_id(&mut self, id: TextureViewId) { self.select(id.backend()).texture_views.free(id); } + + pub fn create_render_bundle_id(&mut self, backend: Backend) -> RenderBundleId { + self.select(backend).render_bundles.alloc(backend) + } + + pub fn kill_render_bundle_id(&mut self, id: RenderBundleId) { + self.select(id.backend()).render_bundles.free(id); + } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 698cff979c9a..30681be0ff2c 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -338,6 +338,8 @@ pub mod gpumapmode; pub mod gpuoutofmemoryerror; pub mod gpupipelinelayout; pub mod gpuqueue; +pub mod gpurenderbundle; +pub mod gpurenderbundleencoder; pub mod gpurenderpassencoder; pub mod gpurenderpipeline; pub mod gpusampler; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 24ee59b54a94..4303b2622015 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ // https://gpuweb.github.io/gpuweb/#gpudevice -[Exposed=(Window, DedicatedWorker)/*, Serializable */, Pref="dom.webgpu.enabled"] +[Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"] interface GPUDevice : EventTarget { [SameObject] readonly attribute GPUAdapter adapter; readonly attribute object extensions; @@ -24,7 +24,7 @@ interface GPUDevice : EventTarget { GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {}); - // GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor); + GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor); }; GPUDevice includes GPUObjectBase; diff --git a/components/script/dom/webidls/GPURenderBundle.webidl b/components/script/dom/webidls/GPURenderBundle.webidl new file mode 100644 index 000000000000..52a8e5b0bc8d --- /dev/null +++ b/components/script/dom/webidls/GPURenderBundle.webidl @@ -0,0 +1,12 @@ +/* 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/#gpurenderbundle +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPURenderBundle { +}; +GPURenderBundle includes GPUObjectBase; + +dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase { +}; diff --git a/components/script/dom/webidls/GPURenderBundleEncoder.webidl b/components/script/dom/webidls/GPURenderBundleEncoder.webidl new file mode 100644 index 000000000000..50676b431b9b --- /dev/null +++ b/components/script/dom/webidls/GPURenderBundleEncoder.webidl @@ -0,0 +1,18 @@ +/* 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/#gpurenderbundleencoder +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPURenderBundleEncoder { + GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {}); +}; +GPURenderBundleEncoder includes GPUObjectBase; +GPURenderBundleEncoder includes GPUProgrammablePassEncoder; +GPURenderBundleEncoder includes GPURenderEncoderBase; + +dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase { + required sequence colorFormats; + GPUTextureFormat depthStencilFormat; + GPUSize32 sampleCount = 1; +}; diff --git a/components/script/dom/webidls/GPURenderPassEncoder.webidl b/components/script/dom/webidls/GPURenderPassEncoder.webidl index 2aa6e7c55817..6261cf894538 100644 --- a/components/script/dom/webidls/GPURenderPassEncoder.webidl +++ b/components/script/dom/webidls/GPURenderPassEncoder.webidl @@ -16,9 +16,14 @@ interface GPURenderPassEncoder { void setStencilReference(GPUStencilValue reference); //void beginOcclusionQuery(GPUSize32 queryIndex); - //void endOcclusionQuery(GPUSize32 queryIndex); + //void endOcclusionQuery(); - //void executeBundles(sequence bundles); + //void beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex); + //void endPipelineStatisticsQuery(); + + //void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); + + void executeBundles(sequence bundles); void endPass(); }; GPURenderPassEncoder includes GPUObjectBase; diff --git a/components/script/dom/webidls/GPURenderPipeline.webidl b/components/script/dom/webidls/GPURenderPipeline.webidl index 951a480601a7..a25890112fc8 100644 --- a/components/script/dom/webidls/GPURenderPipeline.webidl +++ b/components/script/dom/webidls/GPURenderPipeline.webidl @@ -38,6 +38,8 @@ typedef [EnforceRange] long GPUDepthBias; dictionary GPURasterizationStateDescriptor { GPUFrontFace frontFace = "ccw"; GPUCullMode cullMode = "none"; + // Enable depth clamping (requires "depth-clamping" extension) + boolean clampDepth = false; GPUDepthBias depthBias = 0; float depthBiasSlopeScale = 0; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index b5ea3f619a6e..1b7c137e9a29 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -2057,6 +2057,7 @@ impl ScriptThread { WebGPUMsg::FreeCommandBuffer(id) => self.gpu_id_hub.lock().kill_command_buffer_id(id), WebGPUMsg::FreeSampler(id) => self.gpu_id_hub.lock().kill_sampler_id(id), WebGPUMsg::FreeShaderModule(id) => self.gpu_id_hub.lock().kill_shader_module_id(id), + WebGPUMsg::FreeRenderBundle(id) => self.gpu_id_hub.lock().kill_render_bundle_id(id), WebGPUMsg::FreeRenderPipeline(id) => self.gpu_id_hub.lock().kill_render_pipeline_id(id), WebGPUMsg::FreeTexture(id) => self.gpu_id_hub.lock().kill_texture_id(id), WebGPUMsg::FreeTextureView(id) => self.gpu_id_hub.lock().kill_texture_view_id(id), diff --git a/components/webgpu/identity.rs b/components/webgpu/identity.rs index 3fe3d817081b..8a76868a2df4 100644 --- a/components/webgpu/identity.rs +++ b/components/webgpu/identity.rs @@ -57,12 +57,12 @@ pub enum WebGPUMsg { #[derive(Debug)] pub struct IdentityRecycler { sender: IpcSender, - self_sender: IpcSender>, + self_sender: IpcSender, } pub struct IdentityRecyclerFactory { pub sender: IpcSender, - pub self_sender: IpcSender>, + pub self_sender: IpcSender, } macro_rules! impl_identity_handler { diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 58b2c427d99f..663940861599 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -19,6 +19,7 @@ use msg::constellation_msg::PipelineId; use serde::{Deserialize, Serialize}; use servo_config::pref; use smallvec::SmallVec; +use std::borrow::Cow; use std::collections::HashMap; use std::ffi::CString; use std::ptr; @@ -32,7 +33,7 @@ use webrender_traits::{ }; use wgpu::{ binding_model::BindGroupDescriptor, - command::{BufferCopyView, ComputePass, RenderPass, TextureCopyView}, + command::{BufferCopyView, ComputePass, RenderBundleEncoder, RenderPass, TextureCopyView}, device::HostMap, id, instance::RequestAdapterOptions, @@ -54,6 +55,7 @@ pub enum WebGPUResponse { device_id: WebGPUDevice, queue_id: WebGPUQueue, _descriptor: wgt::DeviceDescriptor, + label: Option, }, BufferMapAsync(IpcSharedMemory), } @@ -61,7 +63,7 @@ pub enum WebGPUResponse { pub type WebGPUResponseResult = Result; #[derive(Debug, Deserialize, Serialize)] -pub enum WebGPURequest<'a> { +pub enum WebGPURequest { BufferMapAsync { sender: IpcSender, buffer_id: id::BufferId, @@ -105,13 +107,13 @@ pub enum WebGPURequest<'a> { // TODO: Consider using NonZeroU64 to reduce enum size scope_id: Option, bind_group_id: id::BindGroupId, - descriptor: BindGroupDescriptor<'a>, + descriptor: BindGroupDescriptor<'static>, }, CreateBindGroupLayout { device_id: id::DeviceId, scope_id: Option, bind_group_layout_id: id::BindGroupLayoutId, - descriptor: wgt::BindGroupLayoutDescriptor<'a>, + descriptor: wgt::BindGroupLayoutDescriptor<'static>, }, CreateBuffer { device_id: id::DeviceId, @@ -129,20 +131,20 @@ pub enum WebGPURequest<'a> { device_id: id::DeviceId, scope_id: Option, compute_pipeline_id: id::ComputePipelineId, - descriptor: ComputePipelineDescriptor<'a>, + descriptor: ComputePipelineDescriptor<'static>, }, CreateContext(IpcSender), CreatePipelineLayout { device_id: id::DeviceId, scope_id: Option, pipeline_layout_id: id::PipelineLayoutId, - descriptor: wgt::PipelineLayoutDescriptor<'a, id::BindGroupLayoutId>, + descriptor: wgt::PipelineLayoutDescriptor<'static, id::BindGroupLayoutId>, }, CreateRenderPipeline { device_id: id::DeviceId, scope_id: Option, render_pipeline_id: id::RenderPipelineId, - descriptor: RenderPipelineDescriptor<'a>, + descriptor: RenderPipelineDescriptor<'static>, }, CreateSampler { device_id: id::DeviceId, @@ -180,6 +182,11 @@ pub enum WebGPURequest<'a> { DestroyTexture(id::TextureId), Exit(IpcSender<()>), FreeDevice(id::DeviceId), + RenderBundleEncoderFinish { + render_bundle_encoder: RenderBundleEncoder, + descriptor: wgt::RenderBundleDescriptor>, + render_bundle_id: id::RenderBundleId, + }, RequestAdapter { sender: IpcSender, options: RequestAdapterOptions, @@ -191,6 +198,7 @@ pub enum WebGPURequest<'a> { descriptor: wgt::DeviceDescriptor, device_id: id::DeviceId, pipeline_id: PipelineId, + label: Option, }, RunComputePass { command_encoder_id: id::CommandEncoderId, @@ -245,7 +253,7 @@ struct BufferMapInfo<'a, T> { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct WebGPU(pub IpcSender>); +pub struct WebGPU(pub IpcSender); impl WebGPU { pub fn new( @@ -309,8 +317,8 @@ impl WebGPU { } struct WGPU<'a> { - receiver: IpcReceiver>, - sender: IpcSender>, + receiver: IpcReceiver, + sender: IpcSender, script_sender: IpcSender, global: wgpu::hub::Global, adapters: Vec, @@ -320,7 +328,7 @@ struct WGPU<'a> { // Buffers with pending mapping buffer_maps: HashMap>>, // Presentation Buffers with pending mapping - present_buffer_maps: HashMap>>>, + present_buffer_maps: HashMap>>, webrender_api: webrender_api::RenderApi, webrender_document: webrender_api::DocumentId, external_images: Arc>, @@ -330,8 +338,8 @@ struct WGPU<'a> { impl<'a> WGPU<'a> { fn new( - receiver: IpcReceiver>, - sender: IpcSender>, + receiver: IpcReceiver, + sender: IpcSender, script_sender: IpcSender, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, @@ -626,7 +634,8 @@ impl<'a> WGPU<'a> { program, } => { let global = &self.global; - let source = wgpu_core::pipeline::ShaderModuleSource::SpirV(&program); + let source = + wgpu_core::pipeline::ShaderModuleSource::SpirV(Cow::Owned(program)); let _ = gfx_select!(program_id => global.device_create_shader_module(device_id, source, program_id)); }, @@ -766,6 +775,26 @@ impl<'a> WGPU<'a> { warn!("Unable to send CleanDevice({:?}) ({:?})", device_id, e); } }, + WebGPURequest::RenderBundleEncoderFinish { + render_bundle_encoder, + descriptor, + render_bundle_id, + } => { + let global = &self.global; + let st; + let label = match descriptor.label { + Some(ref s) => { + st = CString::new(s.as_bytes()).unwrap(); + st.as_ptr() + }, + None => ptr::null(), + }; + let _ = gfx_select!(render_bundle_id => global.render_bundle_encoder_finish( + render_bundle_encoder, + &descriptor.map_label(|_| label), + render_bundle_id + )); + }, WebGPURequest::RequestAdapter { sender, options, @@ -809,6 +838,7 @@ impl<'a> WGPU<'a> { descriptor, device_id, pipeline_id, + label, } => { let global = &self.global; let result = gfx_select!(device_id => global.adapter_request_device( @@ -828,6 +858,7 @@ impl<'a> WGPU<'a> { device_id: device, queue_id: queue, _descriptor: descriptor, + label, })) { warn!( "Failed to send response to WebGPURequest::RequestDevice ({})", @@ -1136,6 +1167,7 @@ webgpu_resource!(WebGPUComputePipeline, id::ComputePipelineId); webgpu_resource!(WebGPUDevice, id::DeviceId); webgpu_resource!(WebGPUPipelineLayout, id::PipelineLayoutId); webgpu_resource!(WebGPUQueue, id::QueueId); +webgpu_resource!(WebGPURenderBundle, id::RenderBundleId); webgpu_resource!(WebGPURenderPipeline, id::RenderPipelineId); webgpu_resource!(WebGPUSampler, id::SamplerId); webgpu_resource!(WebGPUShaderModule, id::ShaderModuleId);