diff --git a/deno_webgpu/command_encoder.rs b/deno_webgpu/command_encoder.rs index 82a1f6d087..8df5d58bf1 100644 --- a/deno_webgpu/command_encoder.rs +++ b/deno_webgpu/command_encoder.rs @@ -157,13 +157,13 @@ pub fn op_webgpu_command_encoder_begin_render_pass( depth: wgpu_core::command::PassChannel { load_op: attachment.depth_load_op, store_op: attachment.depth_store_op, - clear_value: attachment.depth_clear_value, + clear_value: Some(attachment.depth_clear_value), read_only: attachment.depth_read_only, }, stencil: wgpu_core::command::PassChannel { load_op: attachment.stencil_load_op, store_op: attachment.stencil_store_op, - clear_value: attachment.stencil_clear_value, + clear_value: Some(attachment.stencil_clear_value), read_only: attachment.stencil_read_only, }, }); diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index b4f414b3cd..788c85e5c6 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -137,7 +137,7 @@ impl Default for PassChannel { } } -impl PassChannel, Option> { +impl PassChannel, Option, Option> { fn resolve(&self) -> Result, AttachmentError> { let load_op = if self.read_only { if self.load_op.is_some() { @@ -160,7 +160,7 @@ impl PassChannel, Option> { Ok(PassChannel { load_op, store_op, - clear_value: self.clear_value, + clear_value: self.clear_value.unwrap_or_default(), read_only: self.read_only, }) } @@ -216,10 +216,11 @@ pub struct RenderPassDepthStencilAttachment { /// The view to use as an attachment. pub view: id::TextureViewId, /// What operations will be performed on the depth part of the attachment. - pub depth: PassChannel, Option>, + pub depth: PassChannel, Option, Option>, /// What operations will be performed on the stencil part of the attachment. - pub stencil: PassChannel, Option>, + pub stencil: PassChannel, Option, Option>, } + /// Describes a depth/stencil attachment to a render pass. #[derive(Debug)] pub struct ArcRenderPassDepthStencilAttachment { @@ -649,6 +650,10 @@ pub enum AttachmentError { NoLoad, #[error("Attachment without store")] NoStore, + #[error("LoadOp is `Clear` but no clear value was provided")] + NoClearValue, + #[error("Clear value ({0}) must be between 0.0 and 1.0, inclusive")] + ClearValueOutOfRange(f32), } /// Error encountered when performing a render pass. @@ -1473,6 +1478,17 @@ impl Global { ))); } + // If this.depthLoadOp is "clear", this.depthClearValue must be provided and must be between 0.0 and 1.0, inclusive. + if depth_stencil_attachment.depth.load_op == Some(LoadOp::Clear) { + if let Some(clear_value) = depth_stencil_attachment.depth.clear_value { + if !(0.0..=1.0).contains(&clear_value) { + return Err(CommandEncoderError::InvalidAttachment(AttachmentError::ClearValueOutOfRange(clear_value))); + } + } else { + return Err(CommandEncoderError::InvalidAttachment(AttachmentError::NoClearValue)); + } + } + Some(ArcRenderPassDepthStencilAttachment { view, depth: if format.has_depth_aspect() { diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index e070fb93fe..8a7c8e1c31 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -404,16 +404,14 @@ fn map_store_op(op: StoreOp) -> wgc::command::StoreOp { } } -fn map_load_op(op: LoadOp) -> (wgc::command::LoadOp, V) { +fn map_load_op(op: LoadOp) -> (wgc::command::LoadOp, Option) { match op { - LoadOp::Clear(v) => (wgc::command::LoadOp::Clear, v), - LoadOp::Load => (wgc::command::LoadOp::Load, V::default()), + LoadOp::Clear(v) => (wgc::command::LoadOp::Clear, Some(v)), + LoadOp::Load => (wgc::command::LoadOp::Load, None), } } -fn map_pass_channel( - ops: Option<&Operations>, -) -> wgc::command::PassChannel { +fn map_pass_channel(ops: Option<&Operations>) -> wgc::command::PassChannel> { match ops { Some(&Operations { load, store }) => { let (load_op, clear_value) = map_load_op(load); @@ -427,7 +425,7 @@ fn map_pass_channel( None => wgc::command::PassChannel { load_op: None, store_op: None, - clear_value: V::default(), + clear_value: None, read_only: true, }, } @@ -2254,7 +2252,7 @@ impl dispatch::CommandEncoderInterface for CoreCommandEncoder { resolve_target: at.resolve_target.map(|view| view.inner.as_core().id), load_op, store_op: map_store_op(at.ops.store), - clear_value, + clear_value: clear_value.unwrap_or_default(), } }) })