aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/gpucommandencoder.rs217
-rw-r--r--components/script/dom/gpucomputepassencoder.rs44
-rw-r--r--components/script/dom/gpudevice.rs343
-rw-r--r--components/script/dom/gpurenderpassencoder.rs79
-rw-r--r--components/script/dom/gputexture.rs67
5 files changed, 430 insertions, 320 deletions
diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs
index 9fabd77a6fa..7d0a4153289 100644
--- a/components/script/dom/gpucommandencoder.rs
+++ b/components/script/dom/gpucommandencoder.rs
@@ -125,14 +125,32 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
&self,
descriptor: &GPUComputePassDescriptor,
) -> DomRoot<GPUComputePassEncoder> {
+ let scope_id = self.device.use_current_scope();
self.set_state(
GPUCommandEncoderState::EncodingComputePass,
GPUCommandEncoderState::Open,
);
+ let (compute_pass, res) = if !self.valid.get() {
+ (
+ None,
+ WebGPUOpResult::ValidationError(String::from(
+ "CommandEncoder is not in Open State",
+ )),
+ )
+ } else {
+ (
+ Some(wgpu_com::ComputePass::new(self.encoder.0)),
+ WebGPUOpResult::Success,
+ )
+ };
+
+ self.device.handle_server_msg(scope_id, res);
+
GPUComputePassEncoder::new(
&self.global(),
self.channel.clone(),
&self,
+ compute_pass,
descriptor.parent.label.as_ref().cloned(),
)
}
@@ -142,102 +160,118 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
&self,
descriptor: &GPURenderPassDescriptor,
) -> DomRoot<GPURenderPassEncoder> {
+ let scope_id = self.device.use_current_scope();
self.set_state(
GPUCommandEncoderState::EncodingRenderPass,
GPUCommandEncoderState::Open,
);
- 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),
- GPULoadOpOrFloat::Float(f) => (wgpu_com::LoadOp::Clear, *f),
- };
- let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue {
- GPUStencilLoadValue::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0u32),
- GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (wgpu_com::LoadOp::Clear, l),
- };
- let depth_channel = wgpu_com::PassChannel {
- load_op: depth_load_op,
- store_op: match depth.depthStoreOp {
- GPUStoreOp::Store => wgpu_com::StoreOp::Store,
- GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
- },
- clear_value: clear_depth,
- read_only: depth.depthReadOnly,
- };
- let stencil_channel = wgpu_com::PassChannel {
- load_op: stencil_load_op,
- store_op: match depth.stencilStoreOp {
- GPUStoreOp::Store => wgpu_com::StoreOp::Store,
- GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
- },
- clear_value: clear_stencil,
- read_only: depth.stencilReadOnly,
- };
- wgpu_com::DepthStencilAttachmentDescriptor {
- attachment: depth.attachment.id().0,
- depth: depth_channel,
- stencil: stencil_channel,
- }
- });
-
- let desc = wgpu_com::RenderPassDescriptor {
- 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));
- (
+ let (render_pass, res) = if !self.valid.get() {
+ (
+ None,
+ WebGPUOpResult::ValidationError(String::from(
+ "CommandEncoder is not in Open State",
+ )),
+ )
+ } else {
+ 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),
+ GPULoadOpOrFloat::Float(f) => (wgpu_com::LoadOp::Clear, *f),
+ };
+ let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue {
+ GPUStencilLoadValue::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0u32),
+ GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => {
+ (wgpu_com::LoadOp::Clear, l)
+ },
+ };
+ let depth_channel = wgpu_com::PassChannel {
+ load_op: depth_load_op,
+ store_op: match depth.depthStoreOp {
+ GPUStoreOp::Store => wgpu_com::StoreOp::Store,
+ GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
+ },
+ clear_value: clear_depth,
+ read_only: depth.depthReadOnly,
+ };
+ let stencil_channel = wgpu_com::PassChannel {
+ load_op: stencil_load_op,
+ store_op: match depth.stencilStoreOp {
+ GPUStoreOp::Store => wgpu_com::StoreOp::Store,
+ GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
+ },
+ clear_value: clear_stencil,
+ read_only: depth.stencilReadOnly,
+ };
+ wgpu_com::DepthStencilAttachmentDescriptor {
+ attachment: depth.attachment.id().0,
+ depth: depth_channel,
+ stencil: stencil_channel,
+ }
+ });
+
+ let desc = wgpu_com::RenderPassDescriptor {
+ 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: *w[0],
- g: *w[1],
- b: *w[2],
- a: *w[3],
+ r: *d.r,
+ g: *d.g,
+ b: *d.b,
+ a: *d.a,
},
- )
- },
- 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,
},
- ),
- };
- 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::<Vec<_>>(),
- ),
- depth_stencil_attachment: depth_stencil.as_ref(),
+ 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::<Vec<_>>(),
+ ),
+ depth_stencil_attachment: depth_stencil.as_ref(),
+ };
+ (
+ Some(wgpu_com::RenderPass::new(self.encoder.0, desc)),
+ WebGPUOpResult::Success,
+ )
};
- let render_pass = wgpu_com::RenderPass::new(self.encoder.0, desc);
+ self.device.handle_server_msg(scope_id, res);
GPURenderPassEncoder::new(
&self.global(),
@@ -257,10 +291,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
destination_offset: GPUSize64,
size: GPUSize64,
) {
- let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
- if !valid {
+ if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
@@ -299,10 +332,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
destination: &GPUTextureCopyView,
copy_size: GPUExtent3D,
) {
- let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
- if !valid {
+ if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
@@ -341,10 +373,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
destination: &GPUBufferCopyView,
copy_size: GPUExtent3D,
) {
- let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
- if !valid {
+ if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
@@ -383,10 +414,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
destination: &GPUTextureCopyView,
copy_size: GPUExtent3D,
) {
- let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
- if !valid {
+ if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
@@ -423,6 +453,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
WebGPURequest::CommandEncoderFinish {
command_encoder_id: self.encoder.0,
device_id: self.device.id().0,
+ is_error: !self.valid.get(),
// TODO(zakorgy): We should use `_descriptor` here after it's not empty
// and the underlying wgpu-core struct is serializable
},
diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs
index c55eaf86fe2..a73ee8bde34 100644
--- a/components/script/dom/gpucomputepassencoder.rs
+++ b/components/script/dom/gpucomputepassencoder.rs
@@ -33,13 +33,14 @@ impl GPUComputePassEncoder {
fn new_inherited(
channel: WebGPU,
parent: &GPUCommandEncoder,
+ compute_pass: Option<ComputePass>,
label: Option<USVString>,
) -> Self {
Self {
channel,
reflector_: Reflector::new(),
label: DomRefCell::new(label),
- compute_pass: DomRefCell::new(Some(ComputePass::new(parent.id().0))),
+ compute_pass: DomRefCell::new(compute_pass),
command_encoder: Dom::from_ref(parent),
}
}
@@ -48,10 +49,16 @@ impl GPUComputePassEncoder {
global: &GlobalScope,
channel: WebGPU,
parent: &GPUCommandEncoder,
+ compute_pass: Option<ComputePass>,
label: Option<USVString>,
) -> DomRoot<Self> {
reflect_dom_object(
- Box::new(GPUComputePassEncoder::new_inherited(channel, parent, label)),
+ Box::new(GPUComputePassEncoder::new_inherited(
+ channel,
+ parent,
+ compute_pass,
+ label,
+ )),
global,
)
}
@@ -88,24 +95,23 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
fn EndPass(&self) {
- if let Some(compute_pass) = self.compute_pass.borrow_mut().take() {
- self.channel
- .0
- .send((
- self.command_encoder.device().use_current_scope(),
- WebGPURequest::RunComputePass {
- command_encoder_id: self.command_encoder.id().0,
- device_id: self.command_encoder.device().id().0,
- compute_pass,
- },
- ))
- .expect("Failed to send RunComputePass");
+ let compute_pass = self.compute_pass.borrow_mut().take();
+ self.channel
+ .0
+ .send((
+ self.command_encoder.device().use_current_scope(),
+ WebGPURequest::RunComputePass {
+ command_encoder_id: self.command_encoder.id().0,
+ device_id: self.command_encoder.device().id().0,
+ compute_pass,
+ },
+ ))
+ .expect("Failed to send RunComputePass");
- self.command_encoder.set_state(
- GPUCommandEncoderState::Open,
- GPUCommandEncoderState::EncodingComputePass,
- );
- }
+ self.command_encoder.set_state(
+ GPUCommandEncoderState::Open,
+ GPUCommandEncoderState::EncodingComputePass,
+ );
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs
index 9e3e6d4976d..e54c0d1540a 100644
--- a/components/script/dom/gpudevice.rs
+++ b/components/script/dom/gpudevice.rs
@@ -64,7 +64,7 @@ use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject};
use std::borrow::Cow;
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::ptr::NonNull;
use std::rc::Rc;
@@ -83,9 +83,16 @@ struct ErrorScopeInfo {
}
#[derive(JSTraceable, MallocSizeOf)]
+struct ErrorScopeMetadata {
+ id: ErrorScopeId,
+ filter: GPUErrorFilter,
+ popped: Cell<bool>,
+}
+
+#[derive(JSTraceable, MallocSizeOf)]
struct ScopeContext {
error_scopes: HashMap<ErrorScopeId, ErrorScopeInfo>,
- scope_stack: Vec<(ErrorScopeId, GPUErrorFilter)>,
+ scope_stack: Vec<ErrorScopeMetadata>,
next_scope_id: ErrorScopeId,
}
@@ -189,8 +196,8 @@ impl GPUDevice {
.scope_stack
.iter()
.rev()
- .find(|&&(id, fil)| id <= s_id && fil == filter)
- .map(|(id, _)| *id);
+ .find(|meta| meta.id <= s_id && meta.filter == filter)
+ .map(|meta| meta.id);
if let Some(s) = scop {
self.handle_error(s, err);
} else {
@@ -237,14 +244,19 @@ impl GPUDevice {
};
if remove {
let _ = context.error_scopes.remove(&scope);
- context.scope_stack.retain(|(id, _)| *id != scope);
+ context.scope_stack.retain(|meta| meta.id != scope);
}
}
pub fn use_current_scope(&self) -> Option<ErrorScopeId> {
let mut context = self.scope_context.borrow_mut();
- let scope_id = context.scope_stack.last().copied();
- scope_id.and_then(|(s_id, _)| {
+ let scope_id = context
+ .scope_stack
+ .iter()
+ .rev()
+ .find(|meta| !meta.popped.get())
+ .map(|meta| meta.id);
+ scope_id.and_then(|s_id| {
context.error_scopes.get_mut(&s_id).map(|mut scope| {
scope.op_count += 1;
s_id
@@ -293,15 +305,12 @@ impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer
fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> {
- let wgpu_descriptor = wgt::BufferDescriptor {
+ let desc = wgt::BufferUsage::from_bits(descriptor.usage).map(|usg| wgt::BufferDescriptor {
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,
- None => wgt::BufferUsage::empty(),
- },
+ usage: usg,
mapped_at_creation: descriptor.mappedAtCreation,
- };
+ });
let id = self
.global()
.wgpu_id_hub()
@@ -309,6 +318,13 @@ impl GPUDeviceMethods for GPUDevice {
.create_buffer_id(self.device.0.backend());
let scope_id = self.use_current_scope();
+ if desc.is_none() {
+ self.handle_server_msg(
+ scope_id,
+ WebGPUOpResult::ValidationError(String::from("Invalid GPUBufferUsage")),
+ );
+ }
+
self.channel
.0
.send((
@@ -316,7 +332,7 @@ impl GPUDeviceMethods for GPUDevice {
WebGPURequest::CreateBuffer {
device_id: self.device.0,
buffer_id: id,
- descriptor: wgpu_descriptor,
+ descriptor: desc,
},
))
.expect("Failed to create WebGPU buffer");
@@ -357,13 +373,17 @@ impl GPUDeviceMethods for GPUDevice {
&self,
descriptor: &GPUBindGroupLayoutDescriptor,
) -> DomRoot<GPUBindGroupLayout> {
+ let mut valid = true;
let entries = descriptor
.entries
.iter()
.map(|bind| {
let visibility = match wgt::ShaderStage::from_bits(bind.visibility) {
Some(visibility) => visibility,
- None => wgt::ShaderStage::from_bits(0).unwrap(),
+ None => {
+ valid = false;
+ wgt::ShaderStage::empty()
+ },
};
let ty = match bind.type_ {
GPUBindingType::Uniform_buffer => wgt::BindingType::UniformBuffer {
@@ -435,13 +455,21 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope();
- let desc = wgt::BindGroupLayoutDescriptor {
- label: descriptor
- .parent
- .label
- .as_ref()
- .map(|s| Cow::Owned(s.to_string())),
- entries: Cow::Owned(entries),
+ let desc = if valid {
+ Some(wgt::BindGroupLayoutDescriptor {
+ label: descriptor
+ .parent
+ .label
+ .as_ref()
+ .map(|s| Cow::Owned(s.to_string())),
+ entries: Cow::Owned(entries),
+ })
+ } else {
+ self.handle_server_msg(
+ scope_id,
+ WebGPUOpResult::ValidationError(String::from("Invalid GPUShaderStage")),
+ );
+ None
};
let bind_group_layout_id = self
@@ -695,22 +723,20 @@ impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture
fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> DomRoot<GPUTexture> {
let size = convert_texture_size_to_dict(&descriptor.size);
- let desc = wgt::TextureDescriptor {
- 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,
- dimension: match descriptor.dimension {
- GPUTextureDimension::_1d => wgt::TextureDimension::D1,
- GPUTextureDimension::_2d => wgt::TextureDimension::D2,
- GPUTextureDimension::_3d => wgt::TextureDimension::D3,
- },
- format: convert_texture_format(descriptor.format),
- usage: match wgt::TextureUsage::from_bits(descriptor.usage) {
- Some(t) => t,
- None => wgt::TextureUsage::empty(),
- },
- };
+ let desc =
+ wgt::TextureUsage::from_bits(descriptor.usage).map(|usg| wgt::TextureDescriptor {
+ 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,
+ dimension: match descriptor.dimension {
+ GPUTextureDimension::_1d => wgt::TextureDimension::D1,
+ GPUTextureDimension::_2d => wgt::TextureDimension::D2,
+ GPUTextureDimension::_3d => wgt::TextureDimension::D3,
+ },
+ format: convert_texture_format(descriptor.format),
+ usage: usg,
+ });
let texture_id = self
.global()
@@ -719,7 +745,12 @@ impl GPUDeviceMethods for GPUDevice {
.create_texture_id(self.device.0.backend());
let scope_id = self.use_current_scope();
-
+ if desc.is_none() {
+ self.handle_server_msg(
+ scope_id,
+ WebGPUOpResult::ValidationError(String::from("Invalid GPUTextureUsage")),
+ );
+ }
self.channel
.0
.send((
@@ -803,110 +834,124 @@ impl GPUDeviceMethods for GPUDevice {
) -> DomRoot<GPURenderPipeline> {
let ref rs_desc = descriptor.rasterizationState;
let ref vs_desc = descriptor.vertexState;
+ let scope_id = self.use_current_scope();
+ let mut valid = true;
+ let 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 => {
+ valid = false;
+ wgt::ColorWrite::empty()
+ },
+ },
+ })
+ .collect::<Vec<_>>(),
+ );
- 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,
+ let desc = if valid {
+ Some(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()),
},
- cull_mode: match rs_desc.cullMode {
- GPUCullMode::None => wgt::CullMode::None,
- GPUCullMode::Front => wgt::CullMode::Front,
- GPUCullMode::Back => wgt::CullMode::Back,
+ 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,
+ },
+ cull_mode: match rs_desc.cullMode {
+ GPUCullMode::None => wgt::CullMode::None,
+ 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,
+ }),
+ 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,
},
- clamp_depth: rs_desc.clampDepth,
- 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,
- },
- 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(),
+ color_states,
+ 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),
},
- })
- .collect::<Vec<_>>(),
- ),
- 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_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,
},
- 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::<Vec<_>>(),
+ ),
+ })
+ .collect::<Vec<_>>(),
+ ),
},
- 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::<Vec<_>>(),
- ),
- })
- .collect::<Vec<_>>(),
- ),
- },
- sample_count: descriptor.sampleCount,
- sample_mask: descriptor.sampleMask,
- alpha_to_coverage_enabled: descriptor.alphaToCoverageEnabled,
+ sample_count: descriptor.sampleCount,
+ sample_mask: descriptor.sampleMask,
+ alpha_to_coverage_enabled: descriptor.alphaToCoverageEnabled,
+ })
+ } else {
+ self.handle_server_msg(
+ scope_id,
+ WebGPUOpResult::ValidationError(String::from("Invalid GPUColorWriteFlags")),
+ );
+ None
};
let render_pipeline_id = self
@@ -915,8 +960,6 @@ impl GPUDeviceMethods for GPUDevice {
.lock()
.create_render_pipeline_id(self.device.0.backend());
- let scope_id = self.use_current_scope();
-
self.channel
.0
.send((
@@ -986,7 +1029,11 @@ impl GPUDeviceMethods for GPUDevice {
promise: None,
};
let res = context.error_scopes.insert(scope_id, err_scope);
- context.scope_stack.push((scope_id, filter));
+ context.scope_stack.push(ErrorScopeMetadata {
+ id: scope_id,
+ filter,
+ popped: Cell::new(false),
+ });
assert!(res.is_none());
}
@@ -994,12 +1041,14 @@ impl GPUDeviceMethods for GPUDevice {
fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> {
let mut context = self.scope_context.borrow_mut();
let promise = Promise::new_in_current_realm(&self.global(), comp);
- let scope_id = if let Some((e, _)) = context.scope_stack.last() {
- *e
- } else {
- promise.reject_error(Error::Operation);
- return promise;
- };
+ let scope_id =
+ if let Some(meta) = context.scope_stack.iter().rev().find(|m| !m.popped.get()) {
+ meta.popped.set(true);
+ meta.id
+ } else {
+ promise.reject_error(Error::Operation);
+ return promise;
+ };
let remove = if let Some(mut err_scope) = context.error_scopes.get_mut(&scope_id) {
if let Some(ref e) = err_scope.error {
match e {
@@ -1017,7 +1066,7 @@ impl GPUDeviceMethods for GPUDevice {
};
if remove {
let _ = context.error_scopes.remove(&scope_id);
- let _ = context.scope_stack.pop();
+ context.scope_stack.retain(|meta| meta.id != scope_id);
}
promise
}
diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs
index 0e68b384ac5..9d1abf12511 100644
--- a/components/script/dom/gpurenderpassencoder.rs
+++ b/components/script/dom/gpurenderpassencoder.rs
@@ -35,7 +35,7 @@ pub struct GPURenderPassEncoder {
impl GPURenderPassEncoder {
fn new_inherited(
channel: WebGPU,
- render_pass: RenderPass,
+ render_pass: Option<RenderPass>,
parent: &GPUCommandEncoder,
label: Option<USVString>,
) -> Self {
@@ -43,7 +43,7 @@ impl GPURenderPassEncoder {
channel,
reflector_: Reflector::new(),
label: DomRefCell::new(label),
- render_pass: DomRefCell::new(Some(render_pass)),
+ render_pass: DomRefCell::new(render_pass),
command_encoder: Dom::from_ref(parent),
}
}
@@ -51,7 +51,7 @@ impl GPURenderPassEncoder {
pub fn new(
global: &GlobalScope,
channel: WebGPU,
- render_pass: RenderPass,
+ render_pass: Option<RenderPass>,
parent: &GPUCommandEncoder,
label: Option<USVString>,
) -> DomRoot<Self> {
@@ -126,27 +126,27 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
/// 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(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() {
+ let colors = match color {
+ GPUColor::GPUColorDict(d) => wgt::Color {
+ r: *d.r,
+ g: *d.g,
+ b: *d.b,
+ a: *d.a,
+ },
+ 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],
+ }
+ },
+ };
wgpu_render::wgpu_render_pass_set_blend_color(render_pass, &colors);
}
}
@@ -160,24 +160,23 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
fn EndPass(&self) {
- if let Some(render_pass) = self.render_pass.borrow_mut().take() {
- self.channel
- .0
- .send((
- self.command_encoder.device().use_current_scope(),
- WebGPURequest::RunRenderPass {
- command_encoder_id: self.command_encoder.id().0,
- device_id: self.command_encoder.device().id().0,
- render_pass,
- },
- ))
- .expect("Failed to send RunRenderPass");
+ let render_pass = self.render_pass.borrow_mut().take();
+ self.channel
+ .0
+ .send((
+ self.command_encoder.device().use_current_scope(),
+ WebGPURequest::RunRenderPass {
+ command_encoder_id: self.command_encoder.id().0,
+ device_id: self.command_encoder.device().id().0,
+ render_pass,
+ },
+ ))
+ .expect("Failed to send RunRenderPass");
- self.command_encoder.set_state(
- GPUCommandEncoderState::Open,
- GPUCommandEncoderState::EncodingRenderPass,
- );
- }
+ self.command_encoder.set_state(
+ GPUCommandEncoderState::Open,
+ GPUCommandEncoderState::EncodingRenderPass,
+ );
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setpipeline
diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs
index 64b56e82607..a7137d1bd61 100644
--- a/components/script/dom/gputexture.rs
+++ b/components/script/dom/gputexture.rs
@@ -16,8 +16,11 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::gpudevice::{convert_texture_format, convert_texture_view_dimension, GPUDevice};
use crate::dom::gputextureview::GPUTextureView;
use dom_struct::dom_struct;
+use std::num::NonZeroU32;
use std::string::String;
-use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView};
+use webgpu::{
+ identity::WebGPUOpResult, wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView,
+};
#[dom_struct]
pub struct GPUTexture {
@@ -137,24 +140,48 @@ impl GPUTextureMethods for GPUTexture {
};
let format = descriptor.format.unwrap_or(self.format);
-
- let desc = wgt::TextureViewDescriptor {
- label: descriptor
- .parent
- .label
- .as_ref()
- .map(|s| String::from(s.as_ref())),
- format: convert_texture_format(format),
- dimension: convert_texture_view_dimension(dimension),
- aspect: match descriptor.aspect {
- GPUTextureAspect::All => wgt::TextureAspect::All,
- GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
- GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
- },
- base_mip_level: descriptor.baseMipLevel,
- level_count: descriptor.mipLevelCount.as_ref().copied(),
- base_array_layer: descriptor.baseArrayLayer,
- array_layer_count: descriptor.arrayLayerCount.as_ref().copied(),
+ let scope_id = self.device.use_current_scope();
+ let mut valid = true;
+ let level_count = descriptor.mipLevelCount.and_then(|count| {
+ if count == 0 {
+ valid = false;
+ }
+ NonZeroU32::new(count)
+ });
+ let array_layer_count = descriptor.arrayLayerCount.and_then(|count| {
+ if count == 0 {
+ valid = false;
+ }
+ NonZeroU32::new(count)
+ });
+
+ let desc = if valid {
+ Some(wgt::TextureViewDescriptor {
+ label: descriptor
+ .parent
+ .label
+ .as_ref()
+ .map(|s| String::from(s.as_ref())),
+ format: convert_texture_format(format),
+ dimension: convert_texture_view_dimension(dimension),
+ aspect: match descriptor.aspect {
+ GPUTextureAspect::All => wgt::TextureAspect::All,
+ GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
+ GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
+ },
+ base_mip_level: descriptor.baseMipLevel,
+ level_count,
+ base_array_layer: descriptor.baseArrayLayer,
+ array_layer_count,
+ })
+ } else {
+ self.device.handle_server_msg(
+ scope_id,
+ WebGPUOpResult::ValidationError(String::from(
+ "arrayLayerCount and mipLevelCount cannot be 0",
+ )),
+ );
+ None
};
let texture_view_id = self
@@ -163,8 +190,6 @@ impl GPUTextureMethods for GPUTexture {
.lock()
.create_texture_view_id(self.device.id().0.backend());
- let scope_id = self.device.use_current_scope();
-
self.channel
.0
.send((