aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorbors-servo <servo-ops@mozilla.com>2020-08-07 15:38:17 -0400
committerGitHub <noreply@github.com>2020-08-07 15:38:17 -0400
commit53467b80b9e79b27beeb305d77ebca5b18515d2f (patch)
tree573ec82b7510af0a73fc8d37c02eed69cbc2492a /components
parent9eab0acbb666d80c593eb69aab2e9cba0303c573 (diff)
parentecb8c914466adad7ee736422c0d9634b51ea07fe (diff)
downloadservo-53467b80b9e79b27beeb305d77ebca5b18515d2f.tar.gz
servo-53467b80b9e79b27beeb305d77ebca5b18515d2f.zip
Auto merge of #27536 - kunalmohan:update-wgpu, r=kvark
Major fixes in error reporting in GPUCommandEncoder and ErrorScope Model <!-- Please describe your changes on the following line: --> 1. Update wgpu to use the error model on wgpu-core side. Register error Ids separately. 2. ~~Record errors only in `GPUCommandEncoder.finish()`. Errors are no longer recorded in ErrorScopes in transfer commands or while recording passes. Any errors that occur are stored on the server-side in `error_command_encoders: HashMap<id::CommandEncoderId, String>` and reported on `CommandEncoderFinish`. Note: This should be reverted when the spec gets updated.~~ 3. Correct a major flaw in ErrorScope Model. If multiple operations are issued inside scope and an early operation fails, the promise resolves and script execution continues. The scope, however, was not popped until the results of all its operations were received. This meant that if the user issues another operation, it was assumed to be issued in an error scope that has already been popped by the user, which led to the failure of a number of tests. This is solved by storing a `popped` boolean to check whether `popErrorScope()` has been called on a scope or not. Operation is now issued in the lastest scope for which `popped == false`. One of the tests used to crash, but it no longer does (All subtests under it fail now). That explains the large number of failing test expectations that have been added. Most of them fail due to the tests being outdated. I'll switch to the updated branch in the next PR. r?@kvark --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Diffstat (limited to 'components')
-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
-rw-r--r--components/webgpu/lib.rs245
6 files changed, 597 insertions, 398 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((
diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs
index 7e20e30d4d6..944edcfa461 100644
--- a/components/webgpu/lib.rs
+++ b/components/webgpu/lib.rs
@@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize};
use servo_config::pref;
use smallvec::SmallVec;
use std::borrow::Cow;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::ffi::CString;
use std::num::NonZeroU64;
use std::ptr;
@@ -77,6 +77,7 @@ pub enum WebGPURequest {
CommandEncoderFinish {
command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
+ is_error: bool,
// TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core
// wgpu::command::CommandBufferDescriptor,
},
@@ -118,12 +119,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 +147,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 +170,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 {
@@ -207,12 +208,12 @@ pub enum WebGPURequest {
RunComputePass {
command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
- compute_pass: ComputePass,
+ compute_pass: Option<ComputePass>,
},
RunRenderPass {
command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
- render_pass: RenderPass,
+ render_pass: Option<RenderPass>,
},
Submit {
queue_id: id::QueueId,
@@ -337,6 +338,8 @@ struct WGPU<'a> {
// Presentation Buffers with pending mapping
present_buffer_maps:
HashMap<id::BufferId, Rc<BufferMapInfo<'a, (Option<ErrorScopeId>, WebGPURequest)>>>,
+ //TODO: Remove this (https://github.com/gfx-rs/wgpu/issues/867)
+ error_command_buffers: HashSet<id::CommandBufferId>,
webrender_api: webrender_api::RenderApi,
webrender_document: webrender_api::DocumentId,
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
@@ -368,6 +371,7 @@ impl<'a> WGPU<'a> {
_invalid_adapters: Vec::new(),
buffer_maps: HashMap::new(),
present_buffer_maps: HashMap::new(),
+ error_command_buffers: HashSet::new(),
webrender_api: webrender_api_sender.create_api(),
webrender_document,
external_images,
@@ -450,12 +454,21 @@ impl<'a> WGPU<'a> {
WebGPURequest::CommandEncoderFinish {
command_encoder_id,
device_id,
+ is_error,
} => {
let global = &self.global;
- let result = gfx_select!(command_encoder_id => global.command_encoder_finish(
- command_encoder_id,
- &wgt::CommandBufferDescriptor::default()
- ));
+ let result = if is_error {
+ Err(String::from("Invalid GPUCommandEncoder"))
+ } else {
+ gfx_select!(command_encoder_id => global.command_encoder_finish(
+ command_encoder_id,
+ &wgt::CommandBufferDescriptor::default()
+ ))
+ .map_err(|e| format!("{:?}", e))
+ };
+ if result.is_err() {
+ self.error_command_buffers.insert(command_encoder_id);
+ }
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CopyBufferToBuffer {
@@ -534,6 +547,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 +558,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 +577,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 +613,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 +626,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 +650,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 +692,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 +707,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 +761,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,24 +790,31 @@ 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;
- gfx_select!(buffer => global.buffer_destroy(buffer, false));
+ gfx_select!(buffer => global.buffer_drop(buffer, false));
},
WebGPURequest::DestroySwapChain {
external_id,
@@ -758,10 +828,10 @@ impl<'a> WGPU<'a> {
.unwrap();
let global = &self.global;
for b_id in data.available_buffer_ids.iter() {
- gfx_select!(b_id => global.buffer_destroy(*b_id, false));
+ gfx_select!(b_id => global.buffer_drop(*b_id, false));
}
for b_id in data.queued_buffer_ids.iter() {
- gfx_select!(b_id => global.buffer_destroy(*b_id, false));
+ gfx_select!(b_id => global.buffer_drop(*b_id, false));
}
for b_id in data.unassigned_buffer_ids.iter() {
if let Err(e) = self.script_sender.send(WebGPUMsg::FreeBuffer(*b_id)) {
@@ -775,7 +845,7 @@ impl<'a> WGPU<'a> {
},
WebGPURequest::DestroyTexture(texture) => {
let global = &self.global;
- gfx_select!(texture => global.texture_destroy(texture));
+ gfx_select!(texture => global.texture_drop(texture));
},
WebGPURequest::Exit(sender) => {
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
@@ -816,6 +886,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 {
@@ -823,15 +896,13 @@ impl<'a> WGPU<'a> {
options,
ids,
} => {
- let adapter_id = match self.global.pick_adapter(
+ let adapter_id = match self.global.request_adapter(
&options,
wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()),
) {
- Some(id) => id,
- None => {
- if let Err(e) =
- sender.send(Err("Failed to get webgpu adapter".to_string()))
- {
+ Ok(id) => id,
+ Err(w) => {
+ if let Err(e) = sender.send(Err(format!("{:?}", w))) {
warn!(
"Failed to send response to WebGPURequest::RequestAdapter ({})",
e
@@ -843,7 +914,8 @@ impl<'a> WGPU<'a> {
let adapter = WebGPUAdapter(adapter_id);
self.adapters.push(adapter);
let global = &self.global;
- let info = gfx_select!(adapter_id => global.adapter_get_info(adapter_id));
+ let info =
+ gfx_select!(adapter_id => global.adapter_get_info(adapter_id)).unwrap();
if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter {
adapter_name: info.name,
adapter_id: adapter,
@@ -872,6 +944,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 ({})",
@@ -904,10 +977,14 @@ impl<'a> WGPU<'a> {
compute_pass,
} => {
let global = &self.global;
- let result = gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass(
- command_encoder_id,
- &compute_pass
- ));
+ let result = if let Some(pass) = compute_pass {
+ gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass(
+ command_encoder_id,
+ &pass
+ )).map_err(|e| format!("{:?}", e))
+ } else {
+ Err(String::from("Invalid ComputePass"))
+ };
self.send_result(device_id, scope_id, result);
},
WebGPURequest::RunRenderPass {
@@ -916,10 +993,14 @@ impl<'a> WGPU<'a> {
render_pass,
} => {
let global = &self.global;
- let result = gfx_select!(command_encoder_id => global.command_encoder_run_render_pass(
- command_encoder_id,
- &render_pass
- ));
+ let result = if let Some(pass) = render_pass {
+ gfx_select!(command_encoder_id => global.command_encoder_run_render_pass(
+ command_encoder_id,
+ &pass
+ )).map_err(|e| format!("{:?}", e))
+ } else {
+ Err(String::from("Invalid RenderPass"))
+ };
self.send_result(device_id, scope_id, result);
},
WebGPURequest::Submit {
@@ -927,7 +1008,15 @@ impl<'a> WGPU<'a> {
command_buffers,
} => {
let global = &self.global;
- let result = gfx_select!(queue_id => global.queue_submit(queue_id, &command_buffers));
+ let cmd_id = command_buffers
+ .iter()
+ .find(|id| self.error_command_buffers.contains(id));
+ let result = if cmd_id.is_some() {
+ Err(String::from("Invalid command buffer submitted"))
+ } else {
+ gfx_select!(queue_id => global.queue_submit(queue_id, &command_buffers))
+ .map_err(|e| format!("{:?}", e))
+ };
self.send_result(queue_id, scope_id, result);
},
WebGPURequest::SwapChainPresent {