diff options
author | bors-servo <servo-ops@mozilla.com> | 2020-05-30 14:22:47 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-30 14:22:47 -0400 |
commit | e0f3e9b9808a2660d6b601a6b571227a4ad93469 (patch) | |
tree | 947c187042e53e05f41adef666bfecbe6f12103b /components/script/dom | |
parent | 5dae012db80deb2ebb1c5589bbddf3e35f730842 (diff) | |
parent | 130de8b8e645867c5c834655d8b94defea599681 (diff) | |
download | servo-e0f3e9b9808a2660d6b601a6b571227a4ad93469.tar.gz servo-e0f3e9b9808a2660d6b601a6b571227a4ad93469.zip |
Auto merge of #26714 - kunalmohan:gpu-render-pipeline, r=jdm
Implement GPURenderPipeline
<!-- Please describe your changes on the following line: -->
We need to wait for #26699 to merge before this.
A significant amount of validation still needs to be added. I plan on doing that in a follow-up PR.
r?@kvark
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 7 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/gpucolorwrite.rs | 11 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 276 | ||||
-rw-r--r-- | components/script/dom/gpupipelinelayout.rs | 4 | ||||
-rw-r--r-- | components/script/dom/gpurenderpipeline.rs | 67 | ||||
-rw-r--r-- | components/script/dom/identityhub.rs | 12 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUColorWrite.webidl | 15 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUDevice.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/GPURenderPipeline.webidl | 188 |
11 files changed, 563 insertions, 24 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 597e5611f74..de97e2c9ea9 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1134,7 +1134,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if type.isDictionary(): # There are no nullable dictionaries - assert not type.nullable() + assert not type.nullable() or (isMember and isMember != "Dictionary") typeName = "%s::%s" % (CGDictionary.makeModuleName(type.inner), CGDictionary.makeDictionaryName(type.inner)) @@ -6645,7 +6645,10 @@ class CGDictionary(CGThing): @staticmethod def makeDictionaryName(dictionary): - return dictionary.identifier.name + if isinstance(dictionary, IDLWrapperType): + return CGDictionary.makeDictionaryName(dictionary.inner) + else: + return dictionary.identifier.name def makeClassName(self, dictionary): return self.makeDictionaryName(dictionary) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 29160e61186..907abb890ee 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -160,7 +160,7 @@ use uuid::Uuid; use webgpu::{ wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice, - WebGPUPipelineLayout, WebGPUQueue, WebGPUSampler, WebGPUShaderModule, + WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule, }; use webrender_api::{DocumentId, ImageKey}; use webxr_api::SwapChainId as WebXRSwapChainId; @@ -556,6 +556,7 @@ unsafe_no_jsmanaged_fields!(WebGPUBuffer); unsafe_no_jsmanaged_fields!(WebGPUBindGroup); unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(WebGPUComputePipeline); +unsafe_no_jsmanaged_fields!(WebGPURenderPipeline); unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout); unsafe_no_jsmanaged_fields!(WebGPUQueue); unsafe_no_jsmanaged_fields!(WebGPUShaderModule); diff --git a/components/script/dom/gpucolorwrite.rs b/components/script/dom/gpucolorwrite.rs new file mode 100644 index 00000000000..c34799d9982 --- /dev/null +++ b/components/script/dom/gpucolorwrite.rs @@ -0,0 +1,11 @@ +/* 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::reflector::Reflector; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct GPUColorWrite { + reflector_: Reflector, +} diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 9c5df68f7a2..9afbeb4483e 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -16,6 +16,11 @@ use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{ GPUCommandEncoderDescriptor, GPUDeviceMethods, }; use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor; +use crate::dom::bindings::codegen::Bindings::GPURenderPipelineBinding::{ + GPUBlendDescriptor, GPUBlendFactor, GPUBlendOperation, GPUCullMode, GPUFrontFace, + GPUIndexFormat, GPUInputStepMode, GPUPrimitiveTopology, GPURenderPipelineDescriptor, + GPUStencilOperation, GPUVertexFormat, +}; use crate::dom::bindings::codegen::Bindings::GPUSamplerBinding::{ GPUAddressMode, GPUCompareFunction, GPUFilterMode, GPUSamplerDescriptor, }; @@ -35,9 +40,11 @@ use crate::dom::gpucommandencoder::GPUCommandEncoder; use crate::dom::gpucomputepipeline::GPUComputePipeline; use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpuqueue::GPUQueue; +use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; use crate::script_runtime::JSContext as SafeJSContext; +use arrayvec::ArrayVec; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, ObjectValue}; @@ -47,7 +54,7 @@ use std::ptr::{self, NonNull}; use webgpu::wgpu::binding_model::{ BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, }; -use webgpu::{self, wgt, WebGPU, WebGPURequest}; +use webgpu::{self, wgpu, wgt, WebGPU, WebGPURequest}; #[dom_struct] pub struct GPUDevice { @@ -605,6 +612,7 @@ impl GPUDeviceMethods for GPUDevice { let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); GPUComputePipeline::new(&self.global(), compute_pipeline) } + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder fn CreateCommandEncoder( &self, @@ -627,6 +635,7 @@ impl GPUDeviceMethods for GPUDevice { GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true) } + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> { let sampler_id = self @@ -637,25 +646,16 @@ impl GPUDeviceMethods for GPUDevice { let compare_enable = descriptor.compare.is_some(); let desc = wgt::SamplerDescriptor { label: Default::default(), - address_mode_u: assign_address_mode(descriptor.addressModeU), - address_mode_v: assign_address_mode(descriptor.addressModeV), - address_mode_w: assign_address_mode(descriptor.addressModeW), - mag_filter: assign_filter_mode(descriptor.magFilter), - min_filter: assign_filter_mode(descriptor.minFilter), - mipmap_filter: assign_filter_mode(descriptor.mipmapFilter), + address_mode_u: convert_address_mode(descriptor.addressModeU), + address_mode_v: convert_address_mode(descriptor.addressModeV), + address_mode_w: convert_address_mode(descriptor.addressModeW), + mag_filter: convert_filter_mode(descriptor.magFilter), + min_filter: convert_filter_mode(descriptor.minFilter), + mipmap_filter: convert_filter_mode(descriptor.mipmapFilter), lod_min_clamp: *descriptor.lodMinClamp, lod_max_clamp: *descriptor.lodMaxClamp, compare: if let Some(c) = descriptor.compare { - match c { - GPUCompareFunction::Never => wgt::CompareFunction::Never, - GPUCompareFunction::Less => wgt::CompareFunction::Less, - GPUCompareFunction::Equal => wgt::CompareFunction::Equal, - GPUCompareFunction::Less_equal => wgt::CompareFunction::LessEqual, - GPUCompareFunction::Greater => wgt::CompareFunction::Greater, - GPUCompareFunction::Not_equal => wgt::CompareFunction::NotEqual, - GPUCompareFunction::Greater_equal => wgt::CompareFunction::GreaterEqual, - GPUCompareFunction::Always => wgt::CompareFunction::Always, - } + convert_compare_function(c) } else { wgt::CompareFunction::Undefined }, @@ -680,9 +680,154 @@ impl GPUDeviceMethods for GPUDevice { true, ) } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline + fn CreateRenderPipeline( + &self, + descriptor: &GPURenderPipelineDescriptor, + ) -> DomRoot<GPURenderPipeline> { + let mut valid = descriptor.parent.layout.is_valid(); + valid &= descriptor.colorStates.len() <= wgpu::device::MAX_COLOR_TARGETS; + if descriptor.alphaToCoverageEnabled { + valid &= descriptor.sampleCount > 1; + } + + 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 color_states = descriptor + .colorStates + .iter() + .map(|state| wgt::ColorStateDescriptor { + format: wgt::TextureFormat::Rgba8UnormSrgb, //TODO: Update this after implementing Texture + 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 => { + valid = false; + wgt::ColorWrite::empty() + }, + }, + }) + .collect::<ArrayVec<_>>(); + + let depth_stencil_state = if let Some(ref dss_desc) = descriptor.depthStencilState { + Some(wgt::DepthStencilStateDescriptor { + format: wgt::TextureFormat::Rgba8UnormSrgb, //TODO: Update this + 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, + }) + } 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, + }, + vs_desc + .vertexBuffers + .iter() + .map(|buffer| { + ( + buffer.arrayStride, + match buffer.stepMode { + GPUInputStepMode::Vertex => wgt::InputStepMode::Vertex, + GPUInputStepMode::Instance => wgt::InputStepMode::Instance, + }, + buffer + .attributes + .iter() + .map(|att| wgt::VertexAttributeDescriptor { + format: convert_vertex_format(att.format), + offset: att.offset, + shader_location: att.shaderLocation, + }) + .collect::<Vec<_>>(), + ) + }) + .collect::<Vec<_>>(), + ); + + let render_pipeline_id = self + .global() + .wgpu_id_hub() + .lock() + .create_render_pipeline_id(self.device.0.backend()); + + self.channel + .0 + .send(WebGPURequest::CreateRenderPipeline { + device_id: self.device.0, + render_pipeline_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, + }) + .expect("Failed to create WebGPU render pipeline"); + + let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); + + GPURenderPipeline::new(&self.global(), render_pipeline, self.device, valid) + } } -fn assign_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { +fn convert_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { match address_mode { GPUAddressMode::Clamp_to_edge => wgt::AddressMode::ClampToEdge, GPUAddressMode::Repeat => wgt::AddressMode::Repeat, @@ -690,9 +835,102 @@ fn assign_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { } } -fn assign_filter_mode(filter_mode: GPUFilterMode) -> wgt::FilterMode { +fn convert_filter_mode(filter_mode: GPUFilterMode) -> wgt::FilterMode { match filter_mode { GPUFilterMode::Nearest => wgt::FilterMode::Nearest, GPUFilterMode::Linear => wgt::FilterMode::Linear, } } + +fn convert_compare_function(compare: GPUCompareFunction) -> wgt::CompareFunction { + match compare { + GPUCompareFunction::Never => wgt::CompareFunction::Never, + GPUCompareFunction::Less => wgt::CompareFunction::Less, + GPUCompareFunction::Equal => wgt::CompareFunction::Equal, + GPUCompareFunction::Less_equal => wgt::CompareFunction::LessEqual, + GPUCompareFunction::Greater => wgt::CompareFunction::Greater, + GPUCompareFunction::Not_equal => wgt::CompareFunction::NotEqual, + GPUCompareFunction::Greater_equal => wgt::CompareFunction::GreaterEqual, + GPUCompareFunction::Always => wgt::CompareFunction::Always, + } +} + +fn convert_blend_descriptor(desc: &GPUBlendDescriptor) -> wgt::BlendDescriptor { + wgt::BlendDescriptor { + src_factor: convert_blend_factor(desc.srcFactor), + dst_factor: convert_blend_factor(desc.dstFactor), + operation: match desc.operation { + GPUBlendOperation::Add => wgt::BlendOperation::Add, + GPUBlendOperation::Subtract => wgt::BlendOperation::Subtract, + GPUBlendOperation::Reverse_subtract => wgt::BlendOperation::ReverseSubtract, + GPUBlendOperation::Min => wgt::BlendOperation::Min, + GPUBlendOperation::Max => wgt::BlendOperation::Max, + }, + } +} + +fn convert_blend_factor(factor: GPUBlendFactor) -> wgt::BlendFactor { + match factor { + GPUBlendFactor::Zero => wgt::BlendFactor::Zero, + GPUBlendFactor::One => wgt::BlendFactor::One, + GPUBlendFactor::Src_color => wgt::BlendFactor::SrcColor, + GPUBlendFactor::One_minus_src_color => wgt::BlendFactor::OneMinusSrcColor, + GPUBlendFactor::Src_alpha => wgt::BlendFactor::SrcAlpha, + GPUBlendFactor::One_minus_src_alpha => wgt::BlendFactor::OneMinusSrcAlpha, + GPUBlendFactor::Dst_color => wgt::BlendFactor::DstColor, + GPUBlendFactor::One_minus_dst_color => wgt::BlendFactor::OneMinusDstColor, + GPUBlendFactor::Dst_alpha => wgt::BlendFactor::DstAlpha, + GPUBlendFactor::One_minus_dst_alpha => wgt::BlendFactor::OneMinusDstAlpha, + GPUBlendFactor::Src_alpha_saturated => wgt::BlendFactor::SrcAlphaSaturated, + GPUBlendFactor::Blend_color => wgt::BlendFactor::BlendColor, + GPUBlendFactor::One_minus_blend_color => wgt::BlendFactor::OneMinusBlendColor, + } +} + +fn convert_stencil_op(operation: GPUStencilOperation) -> wgt::StencilOperation { + match operation { + GPUStencilOperation::Keep => wgt::StencilOperation::Keep, + GPUStencilOperation::Zero => wgt::StencilOperation::Zero, + GPUStencilOperation::Replace => wgt::StencilOperation::Replace, + GPUStencilOperation::Invert => wgt::StencilOperation::Invert, + GPUStencilOperation::Increment_clamp => wgt::StencilOperation::IncrementClamp, + GPUStencilOperation::Decrement_clamp => wgt::StencilOperation::DecrementClamp, + GPUStencilOperation::Increment_wrap => wgt::StencilOperation::IncrementWrap, + GPUStencilOperation::Decrement_wrap => wgt::StencilOperation::DecrementWrap, + } +} + +fn convert_vertex_format(format: GPUVertexFormat) -> wgt::VertexFormat { + match format { + GPUVertexFormat::Uchar2 => wgt::VertexFormat::Uchar2, + GPUVertexFormat::Uchar4 => wgt::VertexFormat::Uchar4, + GPUVertexFormat::Char2 => wgt::VertexFormat::Char2, + GPUVertexFormat::Char4 => wgt::VertexFormat::Char4, + GPUVertexFormat::Uchar2norm => wgt::VertexFormat::Uchar2Norm, + GPUVertexFormat::Uchar4norm => wgt::VertexFormat::Uchar4Norm, + GPUVertexFormat::Char2norm => wgt::VertexFormat::Char2Norm, + GPUVertexFormat::Char4norm => wgt::VertexFormat::Char4Norm, + GPUVertexFormat::Ushort2 => wgt::VertexFormat::Ushort2, + GPUVertexFormat::Ushort4 => wgt::VertexFormat::Ushort4, + GPUVertexFormat::Short2 => wgt::VertexFormat::Short2, + GPUVertexFormat::Short4 => wgt::VertexFormat::Short4, + GPUVertexFormat::Ushort2norm => wgt::VertexFormat::Ushort2Norm, + GPUVertexFormat::Ushort4norm => wgt::VertexFormat::Ushort4Norm, + GPUVertexFormat::Short2norm => wgt::VertexFormat::Short2Norm, + GPUVertexFormat::Short4norm => wgt::VertexFormat::Short4Norm, + GPUVertexFormat::Half2 => wgt::VertexFormat::Half2, + GPUVertexFormat::Half4 => wgt::VertexFormat::Half4, + GPUVertexFormat::Float => wgt::VertexFormat::Float, + GPUVertexFormat::Float2 => wgt::VertexFormat::Float2, + GPUVertexFormat::Float3 => wgt::VertexFormat::Float3, + GPUVertexFormat::Float4 => wgt::VertexFormat::Float4, + GPUVertexFormat::Uint => wgt::VertexFormat::Uint, + GPUVertexFormat::Uint2 => wgt::VertexFormat::Uint2, + GPUVertexFormat::Uint3 => wgt::VertexFormat::Uint3, + GPUVertexFormat::Uint4 => wgt::VertexFormat::Uint4, + GPUVertexFormat::Int => wgt::VertexFormat::Int, + GPUVertexFormat::Int2 => wgt::VertexFormat::Int2, + GPUVertexFormat::Int3 => wgt::VertexFormat::Int3, + GPUVertexFormat::Int4 => wgt::VertexFormat::Int4, + } +} diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index a3f816deb0d..d1c3d0d2bef 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -57,6 +57,10 @@ impl GPUPipelineLayout { pub fn id(&self) -> WebGPUPipelineLayout { self.pipeline_layout } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } } impl GPUPipelineLayoutMethods for GPUPipelineLayout { diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs new file mode 100644 index 00000000000..c7e56fb253a --- /dev/null +++ b/components/script/dom/gpurenderpipeline.rs @@ -0,0 +1,67 @@ +/* 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::GPURenderPipelineBinding::GPURenderPipelineMethods; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::reflector::Reflector; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; +use std::cell::Cell; +use webgpu::{WebGPUDevice, WebGPURenderPipeline}; + +#[dom_struct] +pub struct GPURenderPipeline { + reflector_: Reflector, + label: DomRefCell<Option<DOMString>>, + render_pipeline: WebGPURenderPipeline, + device: WebGPUDevice, + valid: Cell<bool>, +} + +impl GPURenderPipeline { + fn new_inherited( + render_pipeline: WebGPURenderPipeline, + device: WebGPUDevice, + valid: bool, + ) -> GPURenderPipeline { + Self { + reflector_: Reflector::new(), + label: DomRefCell::new(None), + render_pipeline, + valid: Cell::new(valid), + device, + } + } + + pub fn new( + global: &GlobalScope, + render_pipeline: WebGPURenderPipeline, + device: WebGPUDevice, + valid: bool, + ) -> DomRoot<GPURenderPipeline> { + reflect_dom_object( + Box::new(GPURenderPipeline::new_inherited( + render_pipeline, + device, + valid, + )), + global, + ) + } +} + +impl GPURenderPipelineMethods for GPURenderPipeline { + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn GetLabel(&self) -> Option<DOMString> { + self.label.borrow().clone() + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn SetLabel(&self, value: Option<DOMString>) { + *self.label.borrow_mut() = value; + } +} diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index 8ba21e36969..2e7a8cc8a96 100644 --- a/components/script/dom/identityhub.rs +++ b/components/script/dom/identityhub.rs @@ -7,7 +7,7 @@ use webgpu::wgpu::{ hub::IdentityManager, id::{ AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandEncoderId, ComputePipelineId, - DeviceId, PipelineLayoutId, SamplerId, ShaderModuleId, + DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, }, }; use webgpu::wgt::Backend; @@ -24,6 +24,7 @@ pub struct IdentityHub { shader_modules: IdentityManager, command_encoders: IdentityManager, samplers: IdentityManager, + render_pipelines: IdentityManager, } impl IdentityHub { @@ -39,6 +40,7 @@ impl IdentityHub { shader_modules: IdentityManager::default(), command_encoders: IdentityManager::default(), samplers: IdentityManager::default(), + render_pipelines: IdentityManager::default(), } } } @@ -184,4 +186,12 @@ impl Identities { pub fn kill_sampler_id(&mut self, id: SamplerId) { self.select(id.backend()).samplers.free(id); } + + pub fn create_render_pipeline_id(&mut self, backend: Backend) -> RenderPipelineId { + self.select(backend).render_pipelines.alloc(backend) + } + + pub fn kill_render_pipeline_id(&mut self, id: RenderPipelineId) { + self.select(id.backend()).render_pipelines.free(id); + } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index f76bdc498ad..9c259a3dea5 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -325,6 +325,7 @@ pub mod gpubindgroup; pub mod gpubindgrouplayout; pub mod gpubuffer; pub mod gpubufferusage; +pub mod gpucolorwrite; pub mod gpucommandbuffer; pub mod gpucommandencoder; pub mod gpucomputepassencoder; @@ -332,6 +333,7 @@ pub mod gpucomputepipeline; pub mod gpudevice; pub mod gpupipelinelayout; pub mod gpuqueue; +pub mod gpurenderpipeline; pub mod gpusampler; pub mod gpushadermodule; pub mod gpushaderstage; diff --git a/components/script/dom/webidls/GPUColorWrite.webidl b/components/script/dom/webidls/GPUColorWrite.webidl new file mode 100644 index 00000000000..e4a74fe5f6a --- /dev/null +++ b/components/script/dom/webidls/GPUColorWrite.webidl @@ -0,0 +1,15 @@ +/* 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/#gpucolorwrite +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPUColorWrite { + const GPUColorWriteFlags RED = 0x1; + const GPUColorWriteFlags GREEN = 0x2; + const GPUColorWriteFlags BLUE = 0x4; + const GPUColorWriteFlags ALPHA = 0x8; + const GPUColorWriteFlags ALL = 0xF; +}; + +typedef [EnforceRange] unsigned long GPUColorWriteFlags; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 13f7ab37caa..3db27fdae7f 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -22,7 +22,7 @@ interface GPUDevice : EventTarget { GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); - // GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); + GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {}); // GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor); diff --git a/components/script/dom/webidls/GPURenderPipeline.webidl b/components/script/dom/webidls/GPURenderPipeline.webidl new file mode 100644 index 00000000000..768a4c70c4d --- /dev/null +++ b/components/script/dom/webidls/GPURenderPipeline.webidl @@ -0,0 +1,188 @@ +/* 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/#gpurenderpipeline +[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] +interface GPURenderPipeline { +}; +GPURenderPipeline includes GPUObjectBase; + +dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase { + required GPUProgrammableStageDescriptor vertexStage; + GPUProgrammableStageDescriptor fragmentStage; + + required GPUPrimitiveTopology primitiveTopology; + GPURasterizationStateDescriptor rasterizationState = {}; + required sequence<GPUColorStateDescriptor> colorStates; + GPUDepthStencilStateDescriptor depthStencilState; + GPUVertexStateDescriptor vertexState = {}; + + GPUSize32 sampleCount = 1; + GPUSampleMask sampleMask = 0xFFFFFFFF; + boolean alphaToCoverageEnabled = false; +}; + +typedef [EnforceRange] unsigned long GPUSampleMask; + +enum GPUPrimitiveTopology { + "point-list", + "line-list", + "line-strip", + "triangle-list", + "triangle-strip" +}; + +typedef [EnforceRange] long GPUDepthBias; + +dictionary GPURasterizationStateDescriptor { + GPUFrontFace frontFace = "ccw"; + GPUCullMode cullMode = "none"; + + GPUDepthBias depthBias = 0; + float depthBiasSlopeScale = 0; + float depthBiasClamp = 0; +}; + +enum GPUFrontFace { + "ccw", + "cw" +}; + +enum GPUCullMode { + "none", + "front", + "back" +}; + +dictionary GPUColorStateDescriptor { + //required GPUTextureFormat format; + + GPUBlendDescriptor alphaBlend = {}; + GPUBlendDescriptor colorBlend = {}; + GPUColorWriteFlags writeMask = 0xF; // GPUColorWrite.ALL +}; + +dictionary GPUBlendDescriptor { + GPUBlendFactor srcFactor = "one"; + GPUBlendFactor dstFactor = "zero"; + GPUBlendOperation operation = "add"; +}; + +enum GPUBlendFactor { + "zero", + "one", + "src-color", + "one-minus-src-color", + "src-alpha", + "one-minus-src-alpha", + "dst-color", + "one-minus-dst-color", + "dst-alpha", + "one-minus-dst-alpha", + "src-alpha-saturated", + "blend-color", + "one-minus-blend-color" +}; + +enum GPUBlendOperation { + "add", + "subtract", + "reverse-subtract", + "min", + "max" +}; + +enum GPUStencilOperation { + "keep", + "zero", + "replace", + "invert", + "increment-clamp", + "decrement-clamp", + "increment-wrap", + "decrement-wrap" +}; + +typedef [EnforceRange] unsigned long GPUStencilValue; + +dictionary GPUDepthStencilStateDescriptor { + //required GPUTextureFormat format; + + boolean depthWriteEnabled = false; + GPUCompareFunction depthCompare = "always"; + + GPUStencilStateFaceDescriptor stencilFront = {}; + GPUStencilStateFaceDescriptor stencilBack = {}; + + GPUStencilValue stencilReadMask = 0xFFFFFFFF; + GPUStencilValue stencilWriteMask = 0xFFFFFFFF; +}; + +dictionary GPUStencilStateFaceDescriptor { + GPUCompareFunction compare = "always"; + GPUStencilOperation failOp = "keep"; + GPUStencilOperation depthFailOp = "keep"; + GPUStencilOperation passOp = "keep"; +}; + +enum GPUIndexFormat { + "uint16", + "uint32" +}; + +enum GPUVertexFormat { + "uchar2", + "uchar4", + "char2", + "char4", + "uchar2norm", + "uchar4norm", + "char2norm", + "char4norm", + "ushort2", + "ushort4", + "short2", + "short4", + "ushort2norm", + "ushort4norm", + "short2norm", + "short4norm", + "half2", + "half4", + "float", + "float2", + "float3", + "float4", + "uint", + "uint2", + "uint3", + "uint4", + "int", + "int2", + "int3", + "int4" +}; + +enum GPUInputStepMode { + "vertex", + "instance" +}; + +dictionary GPUVertexStateDescriptor { + GPUIndexFormat indexFormat = "uint32"; + sequence<GPUVertexBufferLayoutDescriptor?> vertexBuffers = []; +}; + +dictionary GPUVertexBufferLayoutDescriptor { + required GPUSize64 arrayStride; + GPUInputStepMode stepMode = "vertex"; + required sequence<GPUVertexAttributeDescriptor> attributes; +}; + +dictionary GPUVertexAttributeDescriptor { + required GPUVertexFormat format; + required GPUSize64 offset; + + required GPUIndex32 shaderLocation; +}; |