aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorbors-servo <servo-ops@mozilla.com>2020-05-30 14:22:47 -0400
committerGitHub <noreply@github.com>2020-05-30 14:22:47 -0400
commite0f3e9b9808a2660d6b601a6b571227a4ad93469 (patch)
tree947c187042e53e05f41adef666bfecbe6f12103b /components/script/dom
parent5dae012db80deb2ebb1c5589bbddf3e35f730842 (diff)
parent130de8b8e645867c5c834655d8b94defea599681 (diff)
downloadservo-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.py7
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/gpucolorwrite.rs11
-rw-r--r--components/script/dom/gpudevice.rs276
-rw-r--r--components/script/dom/gpupipelinelayout.rs4
-rw-r--r--components/script/dom/gpurenderpipeline.rs67
-rw-r--r--components/script/dom/identityhub.rs12
-rw-r--r--components/script/dom/mod.rs2
-rw-r--r--components/script/dom/webidls/GPUColorWrite.webidl15
-rw-r--r--components/script/dom/webidls/GPUDevice.webidl2
-rw-r--r--components/script/dom/webidls/GPURenderPipeline.webidl188
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;
+};