diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 487bd7fe7ee2..6fcd1bc23b62 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -6,6 +6,10 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUSize64; use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::{ GPUCommandBufferDescriptor, GPUCommandEncoderMethods, GPUComputePassDescriptor, + GPURenderPassDescriptor, GPUStencilLoadValue, GPUStoreOp, +}; +use crate::dom::bindings::codegen::UnionTypes::{ + GPULoadOpOrDoubleSequenceOrGPUColorDict as GPUColorLoad, GPULoadOpOrFloat, }; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; @@ -15,17 +19,20 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::gpubuffer::GPUBuffer; use crate::dom::gpucommandbuffer::GPUCommandBuffer; use crate::dom::gpucomputepassencoder::GPUComputePassEncoder; +use crate::dom::gpurenderpassencoder::GPURenderPassEncoder; use dom_struct::dom_struct; use std::cell::Cell; use std::collections::HashSet; -use webgpu::wgt::BufferUsage; -use webgpu::{self, WebGPU, WebGPURequest}; +use webgpu::wgpu::command::{ + RawPass, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, + RenderPassDescriptor, +}; +use webgpu::{self, wgt, WebGPU, WebGPUDevice, WebGPURequest}; const BUFFER_COPY_ALIGN_MASK: u64 = 3; // https://gpuweb.github.io/gpuweb/#enumdef-encoder-state #[derive(MallocSizeOf, PartialEq)] -#[allow(dead_code)] pub enum GPUCommandEncoderState { Open, EncodingRenderPass, @@ -42,19 +49,22 @@ pub struct GPUCommandEncoder { encoder: webgpu::WebGPUCommandEncoder, buffers: DomRefCell>>, state: DomRefCell, + device: WebGPUDevice, valid: Cell, } impl GPUCommandEncoder { pub fn new_inherited( channel: WebGPU, + device: WebGPUDevice, encoder: webgpu::WebGPUCommandEncoder, valid: bool, - ) -> GPUCommandEncoder { - GPUCommandEncoder { + ) -> Self { + Self { channel, reflector_: Reflector::new(), label: DomRefCell::new(None), + device, encoder, buffers: DomRefCell::new(HashSet::new()), state: DomRefCell::new(GPUCommandEncoderState::Open), @@ -65,11 +75,14 @@ impl GPUCommandEncoder { pub fn new( global: &GlobalScope, channel: WebGPU, + device: WebGPUDevice, encoder: webgpu::WebGPUCommandEncoder, valid: bool, - ) -> DomRoot { + ) -> DomRoot { reflect_dom_object( - Box::new(GPUCommandEncoder::new_inherited(channel, encoder, valid)), + Box::new(GPUCommandEncoder::new_inherited( + channel, device, encoder, valid, + )), global, ) } @@ -113,6 +126,92 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { GPUComputePassEncoder::new(&self.global(), self.channel.clone(), &self) } + #[allow(unsafe_code)] + /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-beginrenderpass + fn BeginRenderPass( + &self, + descriptor: &GPURenderPassDescriptor, + ) -> DomRoot { + self.set_state( + GPUCommandEncoderState::EncodingRenderPass, + GPUCommandEncoderState::Open, + ); + + let colors = descriptor + .colorAttachments + .iter() + .map(|color| { + let (load_op, clear_color) = match color.loadValue { + GPUColorLoad::GPULoadOp(_) => (wgt::LoadOp::Load, wgt::Color::TRANSPARENT), + GPUColorLoad::DoubleSequence(ref s) => ( + wgt::LoadOp::Clear, + wgt::Color { + r: *s[0], + g: *s[1], + b: *s[2], + a: *s[3], + }, + ), + GPUColorLoad::GPUColorDict(ref d) => ( + wgt::LoadOp::Clear, + wgt::Color { + r: *d.r, + g: *d.g, + b: *d.b, + a: *d.a, + }, + ), + }; + RenderPassColorAttachmentDescriptor { + attachment: color.attachment.id().0, + resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0), + load_op, + store_op: match color.storeOp { + GPUStoreOp::Store => wgt::StoreOp::Store, + GPUStoreOp::Clear => wgt::StoreOp::Clear, + }, + clear_color, + } + }) + .collect::>(); + + let depth_stencil = descriptor.depthStencilAttachment.as_ref().map(|depth| { + let (depth_load_op, clear_depth) = match depth.depthLoadValue { + GPULoadOpOrFloat::GPULoadOp(_) => (wgt::LoadOp::Load, 0.0f32), + GPULoadOpOrFloat::Float(f) => (wgt::LoadOp::Clear, *f), + }; + let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue { + GPUStencilLoadValue::GPULoadOp(_) => (wgt::LoadOp::Load, 0u32), + GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (wgt::LoadOp::Clear, l), + }; + RenderPassDepthStencilAttachmentDescriptor { + attachment: depth.attachment.id().0, + depth_load_op, + depth_store_op: match depth.depthStoreOp { + GPUStoreOp::Store => wgt::StoreOp::Store, + GPUStoreOp::Clear => wgt::StoreOp::Clear, + }, + clear_depth, + stencil_load_op, + stencil_store_op: match depth.stencilStoreOp { + GPUStoreOp::Store => wgt::StoreOp::Store, + GPUStoreOp::Clear => wgt::StoreOp::Clear, + }, + clear_stencil, + } + }); + + let desc = RenderPassDescriptor { + color_attachments: colors.as_ptr(), + color_attachments_length: colors.len(), + depth_stencil_attachment: depth_stencil.as_ref(), + }; + + let raw_pass = unsafe { RawPass::new_render(self.id().0, &desc) }; + + GPURenderPassEncoder::new(&self.global(), self.channel.clone(), raw_pass, &self) + } + /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertobuffer fn CopyBufferToBuffer( &self, @@ -130,12 +229,12 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { Some(_) => true, None => false, }; - valid &= match BufferUsage::from_bits(source.usage()) { - Some(usage) => usage.contains(BufferUsage::COPY_SRC), + valid &= match wgt::BufferUsage::from_bits(source.usage()) { + Some(usage) => usage.contains(wgt::BufferUsage::COPY_SRC), None => false, }; - valid &= match BufferUsage::from_bits(destination.usage()) { - Some(usage) => usage.contains(BufferUsage::COPY_DST), + valid &= match wgt::BufferUsage::from_bits(destination.usage()) { + Some(usage) => usage.contains(wgt::BufferUsage::COPY_DST), None => false, }; valid &= (*self.state.borrow() == GPUCommandEncoderState::Open) && diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs index 76c9ec8eea4a..f202cc37038d 100644 --- a/components/script/dom/gpucomputepassencoder.rs +++ b/components/script/dom/gpucomputepassencoder.rs @@ -2,6 +2,8 @@ * 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/. */ +#![allow(unsafe_code)] + use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUComputePassEncoderBinding::GPUComputePassEncoderMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; @@ -12,7 +14,6 @@ use crate::dom::gpubindgroup::GPUBindGroup; use crate::dom::gpucommandencoder::{GPUCommandEncoder, GPUCommandEncoderState}; use crate::dom::gpucomputepipeline::GPUComputePipeline; use dom_struct::dom_struct; -use std::cell::RefCell; use webgpu::{ wgpu::command::{ compute_ffi::{ @@ -31,27 +32,22 @@ pub struct GPUComputePassEncoder { channel: WebGPU, label: DomRefCell>, #[ignore_malloc_size_of = "defined in wgpu-core"] - raw_pass: RefCell>, + raw_pass: DomRefCell>, command_encoder: Dom, } impl GPUComputePassEncoder { - #[allow(unsafe_code)] - fn new_inherited(channel: WebGPU, parent: &GPUCommandEncoder) -> GPUComputePassEncoder { - GPUComputePassEncoder { + fn new_inherited(channel: WebGPU, parent: &GPUCommandEncoder) -> Self { + Self { channel, reflector_: Reflector::new(), label: DomRefCell::new(None), - raw_pass: RefCell::new(Some(unsafe { RawPass::new_compute(parent.id().0) })), + raw_pass: DomRefCell::new(Some(unsafe { RawPass::new_compute(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) -> DomRoot { reflect_dom_object( Box::new(GPUComputePassEncoder::new_inherited(channel, parent)), global, @@ -70,7 +66,6 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { *self.label.borrow_mut() = value; } - #[allow(unsafe_code)] /// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatch fn Dispatch(&self, x: u32, y: u32, z: u32) { if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { @@ -78,7 +73,6 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { } } - #[allow(unsafe_code)] /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass fn EndPass(&self) { if let Some(raw_pass) = self.raw_pass.borrow_mut().take() { @@ -99,7 +93,6 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { } } - #[allow(unsafe_code)] /// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, dynamic_offsets: Vec) { if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { @@ -115,7 +108,6 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { } } - #[allow(unsafe_code)] /// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-setpipeline fn SetPipeline(&self, pipeline: &GPUComputePipeline) { if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index ba9f22b5fecd..6a4301124b9b 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -98,7 +98,6 @@ impl GPUDevice { } } - #[allow(unsafe_code)] pub fn new( global: &GlobalScope, channel: WebGPU, @@ -647,7 +646,13 @@ impl GPUDeviceMethods for GPUDevice { let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id); - GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true) + GPUCommandEncoder::new( + &self.global(), + self.channel.clone(), + self.device, + encoder, + true, + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs new file mode 100644 index 000000000000..47ac8c6db222 --- /dev/null +++ b/components/script/dom/gpurenderpassencoder.rs @@ -0,0 +1,275 @@ +/* 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/. */ + +#![allow(unsafe_code)] + +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::GPUColor; +use crate::dom::bindings::codegen::Bindings::GPURenderPassEncoderBinding::GPURenderPassEncoderMethods; +use crate::dom::bindings::num::Finite; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::dom::gpubindgroup::GPUBindGroup; +use crate::dom::gpubuffer::GPUBuffer; +use crate::dom::gpucommandencoder::{GPUCommandEncoder, GPUCommandEncoderState}; +use crate::dom::gpurenderpipeline::GPURenderPipeline; +use dom_struct::dom_struct; +use webgpu::{ + wgpu::command::{render_ffi as wgpu_render, RawPass}, + wgt, WebGPU, WebGPURequest, +}; + +#[dom_struct] +pub struct GPURenderPassEncoder { + reflector_: Reflector, + #[ignore_malloc_size_of = "defined in webgpu"] + channel: WebGPU, + label: DomRefCell>, + #[ignore_malloc_size_of = "defined in wgpu-core"] + raw_pass: DomRefCell>, + command_encoder: Dom, +} + +impl GPURenderPassEncoder { + fn new_inherited(channel: WebGPU, raw_pass: RawPass, parent: &GPUCommandEncoder) -> Self { + Self { + channel, + reflector_: Reflector::new(), + label: DomRefCell::new(None), + raw_pass: DomRefCell::new(Some(raw_pass)), + command_encoder: Dom::from_ref(parent), + } + } + + pub fn new( + global: &GlobalScope, + channel: WebGPU, + raw_pass: RawPass, + parent: &GPUCommandEncoder, + ) -> DomRoot { + reflect_dom_object( + Box::new(GPURenderPassEncoder::new_inherited( + channel, raw_pass, parent, + )), + global, + ) + } +} + +impl GPURenderPassEncoderMethods for GPURenderPassEncoder { + /// 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 + fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, dynamic_offsets: Vec) { + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_set_bind_group( + raw_pass, + index, + bind_group.id().0, + dynamic_offsets.as_ptr(), + dynamic_offsets.len(), + ) + }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setviewport + fn SetViewport( + &self, + x: Finite, + y: Finite, + width: Finite, + height: Finite, + min_depth: Finite, + max_depth: Finite, + ) { + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_set_viewport( + raw_pass, *x, *y, *width, *height, *min_depth, *max_depth, + ) + }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setscissorrect + fn SetScissorRect(&self, x: u32, y: u32, width: u32, height: u32) { + if width <= 0 || height <= 0 { + return warn!("Cannot set scissor rect- width and height must greater than 0"); + } + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_set_scissor_rect(raw_pass, x, y, width, height) + }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setblendcolor + fn SetBlendColor(&self, color: GPUColor) { + let colors = match color { + GPUColor::GPUColorDict(d) => wgt::Color { + r: *d.r, + g: *d.g, + b: *d.b, + a: *d.a, + }, + GPUColor::DoubleSequence(s) => wgt::Color { + r: *s[0], + g: *s[1], + b: *s[2], + a: *s[3], + }, + }; + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { wgpu_render::wgpu_render_pass_set_blend_color(raw_pass, &colors) }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setstencilreference + fn SetStencilReference(&self, reference: u32) { + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { wgpu_render::wgpu_render_pass_set_stencil_reference(raw_pass, reference) }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass + fn EndPass(&self) { + if let Some(raw_pass) = self.raw_pass.borrow_mut().take() { + let (pass_data, command_encoder_id) = unsafe { raw_pass.finish_render() }; + + self.channel + .0 + .send(WebGPURequest::RunRenderPass { + command_encoder_id, + pass_data, + }) + .unwrap(); + + self.command_encoder.set_state( + GPUCommandEncoderState::Open, + GPUCommandEncoderState::EncodingRenderPass, + ); + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setpipeline + fn SetPipeline(&self, pipeline: &GPURenderPipeline) { + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { wgpu_render::wgpu_render_pass_set_pipeline(raw_pass, pipeline.id().0) }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setindexbuffer + fn SetIndexBuffer(&self, buffer: &GPUBuffer, offset: u64, size: u64) { + let s; + if size == 0 { + s = buffer.size() - offset; + } else { + s = size; + } + + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_set_index_buffer(raw_pass, buffer.id().0, offset, s) + }; + } + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setvertexbuffer + fn SetVertexBuffer(&self, slot: u32, buffer: &GPUBuffer, offset: u64, size: u64) { + let s; + if size == 0 { + s = buffer.size() - offset; + } else { + s = size; + } + + if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_set_vertex_buffer( + raw_pass, + slot, + buffer.id().0, + offset, + s, + ) + }; + } + } + + /// 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(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_draw( + raw_pass, + 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(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_draw_indexed( + raw_pass, + 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(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_draw_indirect( + raw_pass, + 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(raw_pass) = self.raw_pass.borrow_mut().as_mut() { + unsafe { + wgpu_render::wgpu_render_pass_draw_indexed_indirect( + raw_pass, + indirect_buffer.id().0, + indirect_offset, + ) + }; + } + } +} diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs index c7e56fb253ab..68d07820103b 100644 --- a/components/script/dom/gpurenderpipeline.rs +++ b/components/script/dom/gpurenderpipeline.rs @@ -54,6 +54,12 @@ impl GPURenderPipeline { } } +impl GPURenderPipeline { + pub fn id(&self) -> WebGPURenderPipeline { + self.render_pipeline + } +} + impl GPURenderPipelineMethods for GPURenderPipeline { /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label fn GetLabel(&self) -> Option { diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index 7a6f60e3bfb8..f3bb4209708d 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -22,11 +22,7 @@ pub struct GPUTextureView { } impl GPUTextureView { - fn new_inherited( - texture_view: WebGPUTextureView, - device: WebGPUDevice, - valid: bool, - ) -> GPUTextureView { + fn new_inherited(texture_view: WebGPUTextureView, device: WebGPUDevice, valid: bool) -> Self { Self { reflector_: Reflector::new(), device, @@ -41,7 +37,7 @@ impl GPUTextureView { texture_view: WebGPUTextureView, device: WebGPUDevice, valid: bool, - ) -> DomRoot { + ) -> DomRoot { reflect_dom_object( Box::new(GPUTextureView::new_inherited(texture_view, device, valid)), global, @@ -49,6 +45,12 @@ impl GPUTextureView { } } +impl GPUTextureView { + pub fn id(&self) -> WebGPUTextureView { + self.texture_view + } +} + impl GPUTextureViewMethods for GPUTextureView { /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label fn GetLabel(&self) -> Option { diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 8c96b3cd9cbf..0aa0bd3123ae 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -333,6 +333,7 @@ pub mod gpucomputepipeline; pub mod gpudevice; pub mod gpupipelinelayout; pub mod gpuqueue; +pub mod gpurenderpassencoder; pub mod gpurenderpipeline; pub mod gpusampler; pub mod gpushadermodule; diff --git a/components/script/dom/webidls/GPUCommandEncoder.webidl b/components/script/dom/webidls/GPUCommandEncoder.webidl index f6801e46e966..6892c5393af2 100644 --- a/components/script/dom/webidls/GPUCommandEncoder.webidl +++ b/components/script/dom/webidls/GPUCommandEncoder.webidl @@ -5,7 +5,7 @@ // https://gpuweb.github.io/gpuweb/#gpucommandencoder [Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] interface GPUCommandEncoder { - // GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); + GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {}); void copyBufferToBuffer( @@ -43,3 +43,48 @@ dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase { dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase { }; + +dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase { + required sequence colorAttachments; + GPURenderPassDepthStencilAttachmentDescriptor depthStencilAttachment; + //GPUQuerySet occlusionQuerySet; +}; + +dictionary GPURenderPassColorAttachmentDescriptor { + required GPUTextureView attachment; + GPUTextureView resolveTarget; + + required (GPULoadOp or GPUColor) loadValue; + GPUStoreOp storeOp = "store"; +}; + +dictionary GPURenderPassDepthStencilAttachmentDescriptor { + required GPUTextureView attachment; + + required (GPULoadOp or float) depthLoadValue; + required GPUStoreOp depthStoreOp; + boolean depthReadOnly = false; + + required GPUStencilLoadValue stencilLoadValue; + required GPUStoreOp stencilStoreOp; + boolean stencilReadOnly = false; +}; + +typedef (GPULoadOp or GPUStencilValue) GPUStencilLoadValue; + +enum GPULoadOp { + "load" +}; + +enum GPUStoreOp { + "store", + "clear" +}; + +dictionary GPUColorDict { + required double r; + required double g; + required double b; + required double a; +}; +typedef (sequence or GPUColorDict) GPUColor; diff --git a/components/script/dom/webidls/GPURenderEncoderBase.webidl b/components/script/dom/webidls/GPURenderEncoderBase.webidl new file mode 100644 index 000000000000..f0c4532b4464 --- /dev/null +++ b/components/script/dom/webidls/GPURenderEncoderBase.webidl @@ -0,0 +1,24 @@ +/* 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/#gpurenderencoderbase +[Exposed=(Window, DedicatedWorker)] +interface mixin GPURenderEncoderBase { + void setPipeline(GPURenderPipeline pipeline); + + void setIndexBuffer(GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); + void setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); + + void draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1, + optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0); + void drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1, + optional GPUSize32 firstIndex = 0, + optional GPUSignedOffset32 baseVertex = 0, + optional GPUSize32 firstInstance = 0); + + void drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); + void drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); +}; + +typedef [EnforceRange] long GPUSignedOffset32; diff --git a/components/script/dom/webidls/GPURenderPassEncoder.webidl b/components/script/dom/webidls/GPURenderPassEncoder.webidl new file mode 100644 index 000000000000..2aa6e7c55817 --- /dev/null +++ b/components/script/dom/webidls/GPURenderPassEncoder.webidl @@ -0,0 +1,26 @@ +/* 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/#gpurenderpassencoder +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPURenderPassEncoder { + void setViewport(float x, float y, + float width, float height, + float minDepth, float maxDepth); + + void setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y, + GPUIntegerCoordinate width, GPUIntegerCoordinate height); + + void setBlendColor(GPUColor color); + void setStencilReference(GPUStencilValue reference); + + //void beginOcclusionQuery(GPUSize32 queryIndex); + //void endOcclusionQuery(GPUSize32 queryIndex); + + //void executeBundles(sequence bundles); + void endPass(); +}; +GPURenderPassEncoder includes GPUObjectBase; +GPURenderPassEncoder includes GPUProgrammablePassEncoder; +GPURenderPassEncoder includes GPURenderEncoderBase; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 884bf0ddfa5f..442e2201e188 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -155,6 +155,10 @@ pub enum WebGPURequest { command_encoder_id: id::CommandEncoderId, pass_data: Vec, }, + RunRenderPass { + command_encoder_id: id::CommandEncoderId, + pass_data: Vec, + }, Submit { queue_id: id::QueueId, command_buffers: Vec, @@ -586,6 +590,16 @@ impl WGPU { &pass_data )); }, + WebGPURequest::RunRenderPass { + command_encoder_id, + pass_data, + } => { + let global = &self.global; + gfx_select!(command_encoder_id => global.command_encoder_run_render_pass( + command_encoder_id, + &pass_data + )); + }, WebGPURequest::Submit { queue_id, command_buffers,