Register invalid resources separately

This commit is contained in:
Kunal Mohan 2020-08-06 10:48:17 +05:30
parent 01c8b24e9f
commit 072770dbc0
3 changed files with 325 additions and 206 deletions

View file

@ -293,15 +293,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 +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<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 +443,21 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope();
let desc = wgt::BindGroupLayoutDescriptor {
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,7 +711,8 @@ 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 {
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,
@ -706,11 +723,8 @@ impl GPUDeviceMethods for GPUDevice {
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(),
},
};
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,8 +822,29 @@ 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 {
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,
@ -838,21 +878,7 @@ impl GPUDeviceMethods for GPUDevice {
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(),
},
})
.collect::<Vec<_>>(),
),
color_states,
depth_stencil_state: descriptor.depthStencilState.as_ref().map(|dss_desc| {
wgt::DepthStencilStateDescriptor {
format: convert_texture_format(dss_desc.format),
@ -907,6 +933,13 @@ impl GPUDeviceMethods for GPUDevice {
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((

View file

@ -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,8 +140,23 @@ 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 {
let desc = if valid {
Some(wgt::TextureViewDescriptor {
label: descriptor
.parent
.label
@ -153,9 +170,18 @@ impl GPUTextureMethods for GPUTexture {
GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
},
base_mip_level: descriptor.baseMipLevel,
level_count: descriptor.mipLevelCount.and_then(NonZeroU32::new),
level_count,
base_array_layer: descriptor.baseArrayLayer,
array_layer_count: descriptor.arrayLayerCount.and_then(NonZeroU32::new),
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((

View file

@ -118,12 +118,12 @@ pub enum WebGPURequest {
CreateBindGroupLayout {
device_id: id::DeviceId,
bind_group_layout_id: id::BindGroupLayoutId,
descriptor: wgt::BindGroupLayoutDescriptor<'static>,
descriptor: Option<wgt::BindGroupLayoutDescriptor<'static>>,
},
CreateBuffer {
device_id: id::DeviceId,
buffer_id: id::BufferId,
descriptor: wgt::BufferDescriptor<Option<String>>,
descriptor: Option<wgt::BufferDescriptor<Option<String>>>,
},
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<RenderPipelineDescriptor<'static>>,
},
CreateSampler {
device_id: id::DeviceId,
@ -169,13 +169,13 @@ pub enum WebGPURequest {
CreateTexture {
device_id: id::DeviceId,
texture_id: id::TextureId,
descriptor: wgt::TextureDescriptor<Option<String>>,
descriptor: Option<wgt::TextureDescriptor<Option<String>>>,
},
CreateTextureView {
texture_id: id::TextureId,
texture_view_id: id::TextureViewId,
device_id: id::DeviceId,
descriptor: wgt::TextureViewDescriptor<Option<String>>,
descriptor: Option<wgt::TextureViewDescriptor<Option<String>>>,
},
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;
if let Some(desc) = descriptor {
let result = gfx_select!(bind_group_layout_id =>
global.device_create_bind_group_layout(device_id, &descriptor, 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,8 +567,9 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let st;
let label = match descriptor.label {
let label = match desc.label {
Some(ref s) => {
st = CString::new(s.as_bytes()).unwrap();
st.as_ptr()
@ -561,8 +577,14 @@ impl<'a> WGPU<'a> {
None => ptr::null(),
};
let result = gfx_select!(buffer_id =>
global.device_create_buffer(device_id, &descriptor.map_label(|_| label), 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;
if let Some(desc) = descriptor {
let result = gfx_select!(render_pipeline_id =>
global.device_create_render_pipeline(device_id, &descriptor, 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,8 +751,9 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let st;
let label = match descriptor.label {
let label = match desc.label {
Some(ref s) => {
st = CString::new(s.as_bytes()).unwrap();
st.as_ptr()
@ -715,10 +762,16 @@ impl<'a> WGPU<'a> {
};
let result = gfx_select!(texture_id => global.device_create_texture(
device_id,
&descriptor.map_label(|_| label),
&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,8 +780,9 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let st;
let label = match descriptor.label {
let label = match desc.label {
Some(ref s) => {
st = CString::new(s.as_bytes()).unwrap();
st.as_ptr()
@ -737,10 +791,16 @@ impl<'a> WGPU<'a> {
};
let result = gfx_select!(texture_view_id => global.texture_create_view(
texture_id,
Some(&descriptor.map_label(|_| label)),
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 ({})",