diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 9e3e6d4976d..5044fc8f3dd 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -293,15 +293,12 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot { - 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 +306,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 +320,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 +361,17 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUBindGroupLayoutDescriptor, ) -> DomRoot { + 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 +443,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 +711,20 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> DomRoot { 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 +733,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 +822,124 @@ impl GPUDeviceMethods for GPUDevice { ) -> DomRoot { let ref rs_desc = descriptor.rasterizationState; let ref vs_desc = descriptor.vertexState; - - 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, - }, - 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, - }, - 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(), + 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::>(), - ), - 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_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, + }) + .collect::>(), + ); + + 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()), }, - 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::>(), - ), - }) - .collect::>(), - ), - }, - sample_count: descriptor.sampleCount, - sample_mask: descriptor.sampleMask, - alpha_to_coverage_enabled: descriptor.alphaToCoverageEnabled, + 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, + }, + 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), + }, + 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, + }, + 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::>(), + ), + }) + .collect::>(), + ), + }, + 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 +948,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(( diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 977aa0efc7c..a7137d1bd61 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -18,7 +18,9 @@ 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 { @@ -138,24 +140,48 @@ impl GPUTextureMethods for GPUTexture { }; let format = descriptor.format.unwrap_or(self.format); + 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 = 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.and_then(NonZeroU32::new), - base_array_layer: descriptor.baseArrayLayer, - array_layer_count: descriptor.arrayLayerCount.and_then(NonZeroU32::new), + 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 @@ -164,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(( diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 451dbb9fed1..11ae4f29d6a 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -118,12 +118,12 @@ pub enum WebGPURequest { CreateBindGroupLayout { device_id: id::DeviceId, bind_group_layout_id: id::BindGroupLayoutId, - descriptor: wgt::BindGroupLayoutDescriptor<'static>, + descriptor: Option>, }, CreateBuffer { device_id: id::DeviceId, buffer_id: id::BufferId, - descriptor: wgt::BufferDescriptor>, + descriptor: Option>>, }, CreateCommandEncoder { device_id: id::DeviceId, @@ -146,7 +146,7 @@ pub enum WebGPURequest { CreateRenderPipeline { device_id: id::DeviceId, render_pipeline_id: id::RenderPipelineId, - descriptor: RenderPipelineDescriptor<'static>, + descriptor: Option>, }, CreateSampler { device_id: id::DeviceId, @@ -169,13 +169,13 @@ pub enum WebGPURequest { CreateTexture { device_id: id::DeviceId, texture_id: id::TextureId, - descriptor: wgt::TextureDescriptor>, + descriptor: Option>>, }, CreateTextureView { texture_id: id::TextureId, texture_view_id: id::TextureViewId, device_id: id::DeviceId, - descriptor: wgt::TextureViewDescriptor>, + descriptor: Option>>, }, DestroyBuffer(id::BufferId), DestroySwapChain { @@ -456,6 +456,9 @@ impl<'a> WGPU<'a> { command_encoder_id, &wgt::CommandBufferDescriptor::default() )); + if result.is_err() { + let _ = gfx_select!(command_encoder_id => global.command_buffer_error(command_encoder_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CopyBufferToBuffer { @@ -534,6 +537,9 @@ impl<'a> WGPU<'a> { let global = &self.global; let result = gfx_select!(bind_group_id => global.device_create_bind_group(device_id, &descriptor, bind_group_id)); + if result.is_err() { + let _ = gfx_select!(bind_group_id => global.bind_group_error(bind_group_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CreateBindGroupLayout { @@ -542,9 +548,18 @@ impl<'a> WGPU<'a> { descriptor, } => { let global = &self.global; - let result = gfx_select!(bind_group_layout_id => - global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); - self.send_result(device_id, scope_id, result); + if let Some(desc) = descriptor { + let result = gfx_select!(bind_group_layout_id => + global.device_create_bind_group_layout(device_id, &desc, bind_group_layout_id)); + if result.is_err() { + let _ = gfx_select!(bind_group_layout_id => + global.bind_group_layout_error(bind_group_layout_id)); + } + self.send_result(device_id, scope_id, result); + } else { + let _ = gfx_select!(bind_group_layout_id => + global.bind_group_layout_error(bind_group_layout_id)); + } }, WebGPURequest::CreateBuffer { device_id, @@ -552,17 +567,24 @@ impl<'a> WGPU<'a> { descriptor, } => { let global = &self.global; - let st; - let label = match descriptor.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; - let result = gfx_select!(buffer_id => - global.device_create_buffer(device_id, &descriptor.map_label(|_| label), buffer_id)); - self.send_result(device_id, scope_id, result); + if let Some(desc) = descriptor { + let st; + let label = match desc.label { + Some(ref s) => { + st = CString::new(s.as_bytes()).unwrap(); + st.as_ptr() + }, + None => ptr::null(), + }; + let result = gfx_select!(buffer_id => + global.device_create_buffer(device_id, &desc.map_label(|_| label), buffer_id)); + if result.is_err() { + let _ = gfx_select!(buffer_id => global.buffer_error(buffer_id)); + } + self.send_result(device_id, scope_id, result); + } else { + let _ = gfx_select!(buffer_id => global.buffer_error(buffer_id)); + } }, WebGPURequest::CreateCommandEncoder { device_id, @@ -581,6 +603,9 @@ impl<'a> WGPU<'a> { let desc = wgt::CommandEncoderDescriptor { label }; let result = gfx_select!(command_encoder_id => global.device_create_command_encoder(device_id, &desc, command_encoder_id)); + if result.is_err() { + let _ = gfx_select!(command_encoder_id => global.command_encoder_error(command_encoder_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CreateComputePipeline { @@ -591,6 +616,10 @@ impl<'a> WGPU<'a> { let global = &self.global; let result = gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); + if result.is_err() { + let _ = gfx_select!(compute_pipeline_id => + global.compute_pipeline_error(compute_pipeline_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CreateContext(sender) => { @@ -611,18 +640,28 @@ impl<'a> WGPU<'a> { let global = &self.global; let result = gfx_select!(pipeline_layout_id => global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)); + if result.is_err() { + let _ = gfx_select!(pipeline_layout_id => global.pipeline_layout_error(pipeline_layout_id)); + } self.send_result(device_id, scope_id, result); }, - //TODO: consider https://github.com/gfx-rs/wgpu/issues/684 WebGPURequest::CreateRenderPipeline { device_id, render_pipeline_id, descriptor, } => { let global = &self.global; - let result = gfx_select!(render_pipeline_id => - global.device_create_render_pipeline(device_id, &descriptor, render_pipeline_id)); - self.send_result(device_id, scope_id, result); + if let Some(desc) = descriptor { + let result = gfx_select!(render_pipeline_id => + global.device_create_render_pipeline(device_id, &desc, render_pipeline_id)); + if result.is_err() { + let _ = gfx_select!(render_pipeline_id => + global.render_pipeline_error(render_pipeline_id)); + } + self.send_result(device_id, scope_id, result); + } else { + let _ = gfx_select!(render_pipeline_id => global.render_pipeline_error(render_pipeline_id)); + } }, WebGPURequest::CreateSampler { device_id, @@ -643,6 +682,9 @@ impl<'a> WGPU<'a> { &descriptor.map_label(|_| label), sampler_id )); + if result.is_err() { + let _ = gfx_select!(sampler_id => global.sampler_error(sampler_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CreateShaderModule { @@ -655,6 +697,10 @@ impl<'a> WGPU<'a> { wgpu_core::pipeline::ShaderModuleSource::SpirV(Cow::Owned(program)); let result = gfx_select!(program_id => global.device_create_shader_module(device_id, source, program_id)); + if result.is_err() { + let _ = + gfx_select!(program_id => global.shader_module_error(program_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::CreateSwapChain { @@ -705,20 +751,27 @@ impl<'a> WGPU<'a> { descriptor, } => { let global = &self.global; - let st; - let label = match descriptor.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; - let result = gfx_select!(texture_id => global.device_create_texture( - device_id, - &descriptor.map_label(|_| label), - texture_id - )); - self.send_result(device_id, scope_id, result); + if let Some(desc) = descriptor { + let st; + let label = match desc.label { + Some(ref s) => { + st = CString::new(s.as_bytes()).unwrap(); + st.as_ptr() + }, + None => ptr::null(), + }; + let result = gfx_select!(texture_id => global.device_create_texture( + device_id, + &desc.map_label(|_| label), + texture_id + )); + if result.is_err() { + let _ = gfx_select!(texture_id => global.texture_error(texture_id)); + } + self.send_result(device_id, scope_id, result); + } else { + let _ = gfx_select!(texture_id => global.texture_error(texture_id)); + } }, WebGPURequest::CreateTextureView { texture_id, @@ -727,20 +780,27 @@ impl<'a> WGPU<'a> { descriptor, } => { let global = &self.global; - let st; - let label = match descriptor.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; - let result = gfx_select!(texture_view_id => global.texture_create_view( - texture_id, - Some(&descriptor.map_label(|_| label)), - texture_view_id - )); - self.send_result(device_id, scope_id, result); + if let Some(desc) = descriptor { + let st; + let label = match desc.label { + Some(ref s) => { + st = CString::new(s.as_bytes()).unwrap(); + st.as_ptr() + }, + None => ptr::null(), + }; + let result = gfx_select!(texture_view_id => global.texture_create_view( + texture_id, + Some(&desc.map_label(|_| label)), + texture_view_id + )); + if result.is_err() { + let _ = gfx_select!(texture_view_id => global.texture_view_error(texture_view_id)); + } + self.send_result(device_id, scope_id, result); + } else { + let _ = gfx_select!(texture_view_id => global.texture_view_error(texture_view_id)); + } }, WebGPURequest::DestroyBuffer(buffer) => { let global = &self.global; @@ -816,6 +876,9 @@ impl<'a> WGPU<'a> { &descriptor.map_label(|_| label), render_bundle_id )); + if result.is_err() { + let _ = gfx_select!(render_bundle_id => global.render_bundle_error(render_bundle_id)); + } self.send_result(device_id, scope_id, result); }, WebGPURequest::RequestAdapter { @@ -871,6 +934,7 @@ impl<'a> WGPU<'a> { )) { Ok(id) => id, Err(e) => { + let _ = gfx_select!(device_id => global.device_error(device_id)); if let Err(w) = sender.send(Err(format!("{:?}", e))) { warn!( "Failed to send response to WebGPURequest::RequestDevice ({})",