Record errors in GPUCommandEncoder.BeginPass() and EncoderPass.endPass()

This commit is contained in:
Kunal Mohan 2020-08-07 22:36:05 +05:30
parent 78c9466fdb
commit 1d80f57aab
4 changed files with 230 additions and 168 deletions

View file

@ -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 (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));
(
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
},

View file

@ -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

View file

@ -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