diff options
author | Samson <16504129+sagudev@users.noreply.github.com> | 2024-05-22 18:47:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-22 16:47:35 +0000 |
commit | 794110ebe58ad72d809291e9feb3f2cc92819941 (patch) | |
tree | 9c01451fa022f433fa8a305d58c2a79da747e838 /components/script | |
parent | 9f32809671c8c8e79d59c95194dcc466452299fc (diff) | |
download | servo-794110ebe58ad72d809291e9feb3f2cc92819941.tar.gz servo-794110ebe58ad72d809291e9feb3f2cc92819941.zip |
webgpu: Move errorscopes to WGPU thread (#32304)
* Prepare errorscopes logic in wgpu_thread
* remove scope_id from ipc
* new GPUErrors per spec
* remove cotent timeline error_scope
* fixup poperrorscope types
* device_scope -> gpu_error and nice errors
* Handle errors detection more elegantly
* good expectations
* new expectations
* Make error_scope.errors Vec as per spec
Diffstat (limited to 'components/script')
30 files changed, 491 insertions, 596 deletions
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index e49afb42b67..a220df2b73d 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -232,7 +232,7 @@ class Descriptor(DescriptorProvider): self.register = desc.get('register', True) self.path = desc.get('path', pathDefault) self.inRealmMethods = [name for name in desc.get('inRealms', [])] - self.bindingPath = f"crate::dom::bindings::codegen::Bindings::{ifaceName}Binding::{ifaceName}_Binding" + self.bindingPath = f"{getModuleFromObject(self.interface)}::{ifaceName}_Binding" self.outerObjectHook = desc.get('outerObjectHook', 'None') self.proxy = False self.weakReferenceable = desc.get('weakReferenceable', False) diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 7586a58793e..89b6f858b1d 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -56,7 +56,7 @@ use script_traits::{ }; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use uuid::Uuid; -use webgpu::{ErrorScopeId, WebGPUDevice, WebGPUOpResult}; +use webgpu::WebGPUDevice; use super::bindings::trace::HashMapTracedValues; use crate::dom::bindings::cell::{DomRefCell, RefMut}; @@ -3097,17 +3097,12 @@ impl GlobalScope { let _ = self.gpu_devices.borrow_mut().remove(&device); } - pub fn handle_wgpu_msg( - &self, - device: WebGPUDevice, - scope: Option<ErrorScopeId>, - result: WebGPUOpResult, - ) { + pub fn handle_uncaptured_gpu_error(&self, device: WebGPUDevice, error: webgpu::Error) { self.gpu_devices .borrow() .get(&device) .expect("GPUDevice not found") - .handle_server_msg(scope, result); + .fire_uncaptured_error(error); } pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) { diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index 6473ec22fb1..8e0c29b895b 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -91,7 +91,7 @@ impl Drop for GPUAdapter { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropAdapter(self.adapter.0))) + .send(WebGPURequest::DropAdapter(self.adapter.0)) { warn!( "Failed to send WebGPURequest::DropAdapter({:?}) ({})", @@ -217,16 +217,13 @@ impl GPUAdapterMethods for GPUAdapter { if self .channel .0 - .send(( - None, - WebGPURequest::RequestDevice { - sender, - adapter_id: self.adapter, - descriptor: desc, - device_id: id, - pipeline_id, - }, - )) + .send(WebGPURequest::RequestDevice { + sender, + adapter_id: self.adapter, + descriptor: desc, + device_id: id, + pipeline_id, + }) .is_err() { promise.reject_error(Error::Operation); diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs index 5477cd3a2c1..2c4fa1bd2e8 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -73,7 +73,7 @@ impl Drop for GPUBindGroup { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropBindGroup(self.bind_group.0))) + .send(WebGPURequest::DropBindGroup(self.bind_group.0)) { warn!( "Failed to send WebGPURequest::DropBindGroup({:?}) ({})", diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index 0124065b0cd..2a4cb199d41 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -62,10 +62,11 @@ impl GPUBindGroupLayout { impl Drop for GPUBindGroupLayout { fn drop(&mut self) { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DropBindGroupLayout(self.bind_group_layout.0), - )) { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DropBindGroupLayout(self.bind_group_layout.0)) + { warn!( "Failed to send WebGPURequest::DropBindGroupLayout({:?}) ({})", self.bind_group_layout.0, e diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index bb747a998cc..0a7689cdb5a 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -12,9 +12,7 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; use js::typedarray::{ArrayBuffer, ArrayBufferU8}; use webgpu::wgc::device::HostMap; -use webgpu::{ - WebGPU, WebGPUBuffer, WebGPUOpResult, WebGPURequest, WebGPUResponse, WebGPUResponseResult, -}; +use webgpu::{WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse, WebGPUResponseResult}; use super::bindings::buffer_source::{create_new_external_array_buffer, HeapBufferSource}; use crate::dom::bindings::cell::DomRefCell; @@ -137,7 +135,7 @@ impl Drop for GPUBuffer { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropBuffer(self.buffer.0))) + .send(WebGPURequest::DropBuffer(self.buffer.0)) { warn!( "Failed to send WebGPURequest::DropBuffer({:?}) ({})", @@ -166,17 +164,14 @@ impl GPUBufferMethods for GPUBuffer { return Err(Error::Operation); }; let m_range = m_info.mapping_range.clone(); - if let Err(e) = self.channel.0.send(( - self.device.use_current_scope(), - WebGPURequest::UnmapBuffer { - buffer_id: self.id().0, - device_id: self.device.id().0, - array_buffer: IpcSharedMemory::from_bytes(&m_info.mapping.lock().unwrap()), - is_map_read: m_info.map_mode == Some(GPUMapModeConstants::READ), - offset: m_range.start, - size: m_range.end - m_range.start, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::UnmapBuffer { + buffer_id: self.id().0, + device_id: self.device.id().0, + array_buffer: IpcSharedMemory::from_bytes(&m_info.mapping.lock().unwrap()), + is_map_read: m_info.map_mode == Some(GPUMapModeConstants::READ), + offset: m_range.start, + size: m_range.end - m_range.start, + }) { warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e); } // Step 3.3 @@ -209,7 +204,7 @@ impl GPUBufferMethods for GPUBuffer { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DestroyBuffer(self.buffer.0))) + .send(WebGPURequest::DestroyBuffer(self.buffer.0)) { warn!( "Failed to send WebGPURequest::DestroyBuffer({:?}) ({})", @@ -237,12 +232,11 @@ impl GPUBufferMethods for GPUBuffer { } else { self.size - offset }; - let scope_id = self.device.use_current_scope(); if self.state.get() != GPUBufferState::Unmapped { - self.device.handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from("Buffer is not Unmapped")), - ); + self.device + .dispatch_error(webgpu::Error::Validation(String::from( + "Buffer is not Unmapped", + ))); promise.reject_error(Error::Abort); return promise; } @@ -250,10 +244,10 @@ impl GPUBufferMethods for GPUBuffer { GPUMapModeConstants::READ => HostMap::Read, GPUMapModeConstants::WRITE => HostMap::Write, _ => { - self.device.handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from("Invalid MapModeFlags")), - ); + self.device + .dispatch_error(webgpu::Error::Validation(String::from( + "Invalid MapModeFlags", + ))); promise.reject_error(Error::Abort); return promise; }, @@ -262,17 +256,14 @@ impl GPUBufferMethods for GPUBuffer { let map_range = offset..offset + range_size; let sender = response_async(&promise, self); - if let Err(e) = self.channel.0.send(( - scope_id, - WebGPURequest::BufferMapAsync { - sender, - buffer_id: self.buffer.0, - device_id: self.device.id().0, - host_map, - offset, - size: Some(range_size), - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { + sender, + buffer_id: self.buffer.0, + device_id: self.device.id().0, + host_map, + offset, + size: Some(range_size), + }) { warn!( "Failed to send BufferMapAsync ({:?}) ({})", self.buffer.0, e diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs index 0aa45648f8e..eebc3b782b3 100644 --- a/components/script/dom/gpucanvascontext.rs +++ b/components/script/dom/gpucanvascontext.rs @@ -111,7 +111,7 @@ pub struct GPUCanvasContext { impl GPUCanvasContext { fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas, channel: WebGPU) -> Self { let (sender, receiver) = ipc::channel().unwrap(); - if let Err(e) = channel.0.send((None, WebGPURequest::CreateContext(sender))) { + if let Err(e) = channel.0.send(WebGPURequest::CreateContext(sender)) { warn!("Failed to send CreateContext ({:?})", e); } let external_id = receiver.recv().unwrap(); @@ -153,14 +153,11 @@ impl GPUCanvasContext { .wgpu_id_hub() .lock() .create_command_encoder_id(texture_id.backend()); - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::SwapChainPresent { - external_id: self.context_id.0, - texture_id, - encoder_id, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::SwapChainPresent { + external_id: self.context_id.0, + texture_id, + encoder_id, + }) { warn!( "Failed to send UpdateWebrenderData({:?}) ({})", self.context_id, e @@ -275,17 +272,14 @@ impl GPUCanvasContextMethods for GPUCanvasContext { self.channel .0 - .send(( - None, - WebGPURequest::CreateSwapChain { - device_id: descriptor.device.id().0, - buffer_ids, - external_id: self.context_id.0, - sender, - image_desc, - image_data, - }, - )) + .send(WebGPURequest::CreateSwapChain { + device_id: descriptor.device.id().0, + buffer_ids, + external_id: self.context_id.0, + sender, + image_desc, + image_data, + }) .expect("Failed to create WebGPU SwapChain"); self.texture @@ -298,13 +292,10 @@ impl GPUCanvasContextMethods for GPUCanvasContext { /// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-unconfigure> fn Unconfigure(&self) { if let Some(image_key) = self.webrender_image.take() { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DestroySwapChain { - external_id: self.context_id.0, - image_key, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::DestroySwapChain { + external_id: self.context_id.0, + image_key, + }) { warn!( "Failed to send DestroySwapChain-ImageKey({:?}) ({})", image_key, e diff --git a/components/script/dom/gpucommandbuffer.rs b/components/script/dom/gpucommandbuffer.rs index 0b78559e54e..e50c350f18c 100644 --- a/components/script/dom/gpucommandbuffer.rs +++ b/components/script/dom/gpucommandbuffer.rs @@ -72,10 +72,11 @@ impl GPUCommandBuffer { impl Drop for GPUCommandBuffer { fn drop(&mut self) { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DropCommandBuffer(self.command_buffer.0), - )) { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DropCommandBuffer(self.command_buffer.0)) + { warn!( "Failed to send DropCommandBuffer({:?}) ({})", self.command_buffer.0, e diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 8f26601b122..799db233a28 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -270,17 +270,14 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { .insert(DomRoot::from_ref(destination)); self.channel .0 - .send(( - None, - WebGPURequest::CopyBufferToBuffer { - command_encoder_id: self.encoder.0, - source_id: source.id().0, - source_offset, - destination_id: destination.id().0, - destination_offset, - size, - }, - )) + .send(WebGPURequest::CopyBufferToBuffer { + command_encoder_id: self.encoder.0, + source_id: source.id().0, + source_offset, + destination_id: destination.id().0, + destination_offset, + size, + }) .expect("Failed to send CopyBufferToBuffer"); } @@ -302,17 +299,12 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { self.channel .0 - .send(( - None, - WebGPURequest::CopyBufferToTexture { - command_encoder_id: self.encoder.0, - source: convert_ic_buffer(source), - destination: convert_ic_texture(destination), - copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict( - ©_size, - )), - }, - )) + .send(WebGPURequest::CopyBufferToTexture { + command_encoder_id: self.encoder.0, + source: convert_ic_buffer(source), + destination: convert_ic_texture(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) .expect("Failed to send CopyBufferToTexture"); } @@ -334,17 +326,12 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { self.channel .0 - .send(( - None, - WebGPURequest::CopyTextureToBuffer { - command_encoder_id: self.encoder.0, - source: convert_ic_texture(source), - destination: convert_ic_buffer(destination), - copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict( - ©_size, - )), - }, - )) + .send(WebGPURequest::CopyTextureToBuffer { + command_encoder_id: self.encoder.0, + source: convert_ic_texture(source), + destination: convert_ic_buffer(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) .expect("Failed to send CopyTextureToBuffer"); } @@ -362,17 +349,12 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { self.channel .0 - .send(( - None, - WebGPURequest::CopyTextureToTexture { - command_encoder_id: self.encoder.0, - source: convert_ic_texture(source), - destination: convert_ic_texture(destination), - copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict( - ©_size, - )), - }, - )) + .send(WebGPURequest::CopyTextureToTexture { + command_encoder_id: self.encoder.0, + source: convert_ic_texture(source), + destination: convert_ic_texture(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) .expect("Failed to send CopyTextureToTexture"); } @@ -380,16 +362,13 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { fn Finish(&self, descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> { self.channel .0 - .send(( - self.device.use_current_scope(), - 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 - }, - )) + .send(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 + }) .expect("Failed to send Finish"); *self.state.borrow_mut() = GPUCommandEncoderState::Closed; diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs index cb0153b3c22..23ffba400fc 100644 --- a/components/script/dom/gpucomputepassencoder.rs +++ b/components/script/dom/gpucomputepassencoder.rs @@ -100,13 +100,10 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder { let compute_pass = self.compute_pass.borrow_mut().take(); self.channel .0 - .send(( - None, - WebGPURequest::RunComputePass { - command_encoder_id: self.command_encoder.id().0, - compute_pass, - }, - )) + .send(WebGPURequest::RunComputePass { + command_encoder_id: self.command_encoder.id().0, + compute_pass, + }) .expect("Failed to send RunComputePass"); //TODO: handle error self.command_encoder.set_state( diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs index febf758e1fe..0433d22e5e7 100644 --- a/components/script/dom/gpucomputepipeline.rs +++ b/components/script/dom/gpucomputepipeline.rs @@ -103,10 +103,11 @@ impl GPUComputePipelineMethods for GPUComputePipeline { impl Drop for GPUComputePipeline { fn drop(&mut self) { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DropComputePipeline(self.compute_pipeline.0), - )) { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DropComputePipeline(self.compute_pipeline.0)) + { warn!( "Failed to send WebGPURequest::DropComputePipeline({:?}) ({})", self.compute_pipeline.0, e diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index f208ee37c47..01c2b0a54a8 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -17,19 +17,21 @@ use webgpu::wgc::id::{BindGroupLayoutId, PipelineLayoutId}; use webgpu::wgc::{ binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res, }; -use webgpu::{self, wgt, ErrorScopeId, WebGPU, WebGPUOpResult, WebGPURequest}; +use webgpu::{self, wgt, PopError, WebGPU, WebGPURequest, WebGPUResponse, WebGPUResponseResult}; use super::bindings::codegen::UnionTypes::GPUPipelineLayoutOrGPUAutoLayoutMode; use super::bindings::error::Fallible; +use super::gpu::AsyncWGPUListener; use super::gpudevicelostinfo::GPUDeviceLostInfo; use super::gpusupportedlimits::GPUSupportedLimits; +use super::types::GPUError; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit; use crate::dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ GPUBindGroupDescriptor, GPUBindGroupLayoutDescriptor, GPUBindingResource, GPUBufferBindingType, GPUBufferDescriptor, GPUCommandEncoderDescriptor, GPUComputePipelineDescriptor, - GPUDeviceLostReason, GPUDeviceMethods, GPUError, GPUErrorFilter, GPUPipelineLayoutDescriptor, + GPUDeviceLostReason, GPUDeviceMethods, GPUErrorFilter, GPUPipelineLayoutDescriptor, GPURenderBundleEncoderDescriptor, GPURenderPipelineDescriptor, GPUSamplerBindingType, GPUSamplerDescriptor, GPUShaderModuleDescriptor, GPUStorageTextureAccess, GPUSupportedLimitsMethods, GPUTextureDescriptor, GPUTextureDimension, GPUTextureSampleType, @@ -42,6 +44,7 @@ use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpu::response_async; use crate::dom::gpuadapter::GPUAdapter; use crate::dom::gpubindgroup::GPUBindGroup; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; @@ -54,7 +57,6 @@ use crate::dom::gpuconvert::{ convert_texture_size_to_dict, convert_texture_size_to_wgt, convert_vertex_format, convert_view_dimension, }; -use crate::dom::gpuoutofmemoryerror::GPUOutOfMemoryError; use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpuqueue::GPUQueue; use crate::dom::gpurenderbundleencoder::GPURenderBundleEncoder; @@ -64,33 +66,9 @@ use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gpusupportedfeatures::GPUSupportedFeatures; use crate::dom::gputexture::GPUTexture; use crate::dom::gpuuncapturederrorevent::GPUUncapturedErrorEvent; -use crate::dom::gpuvalidationerror::GPUValidationError; use crate::dom::promise::Promise; use crate::realms::InRealm; -#[derive(JSTraceable, MallocSizeOf)] -struct ErrorScopeInfo { - op_count: u64, - #[ignore_malloc_size_of = "Because it is non-owning"] - error: Option<GPUError>, - #[ignore_malloc_size_of = "promises are hard"] - promise: Option<Rc<Promise>>, -} - -#[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<ErrorScopeMetadata>, - next_scope_id: ErrorScopeId, -} - #[dom_struct] pub struct GPUDevice { eventtarget: EventTarget, @@ -106,7 +84,6 @@ pub struct GPUDevice { #[no_trace] device: webgpu::WebGPUDevice, default_queue: Dom<GPUQueue>, - scope_context: DomRefCell<ScopeContext>, #[ignore_malloc_size_of = "promises are hard"] lost_promise: DomRefCell<Option<Rc<Promise>>>, valid: Cell<bool>, @@ -134,11 +111,6 @@ impl GPUDevice { label: DomRefCell::new(USVString::from(label)), device, default_queue: Dom::from_ref(queue), - scope_context: DomRefCell::new(ScopeContext { - error_scopes: HashMap::new(), - scope_stack: Vec::new(), - next_scope_id: ErrorScopeId::new(1).unwrap(), - }), lost_promise: DomRefCell::new(None), valid: Cell::new(true), } @@ -179,110 +151,28 @@ impl GPUDevice { self.channel.clone() } - pub fn handle_server_msg(&self, scope: Option<ErrorScopeId>, result: WebGPUOpResult) { - let result = match result { - WebGPUOpResult::Success => Ok(()), - WebGPUOpResult::ValidationError(m) => { - let val_err = GPUValidationError::new(&self.global(), DOMString::from_string(m)); - Err(( - GPUError::GPUValidationError(val_err), - GPUErrorFilter::Validation, - )) - }, - WebGPUOpResult::OutOfMemoryError => { - let oom_err = GPUOutOfMemoryError::new(&self.global()); - Err(( - GPUError::GPUOutOfMemoryError(oom_err), - GPUErrorFilter::Out_of_memory, - )) - }, - }; - - if let Some(s_id) = scope { - if let Err((err, filter)) = result { - let scop = self - .scope_context - .borrow() - .scope_stack - .iter() - .rev() - .find(|meta| meta.id <= s_id && meta.filter == filter) - .map(|meta| meta.id); - if let Some(s) = scop { - self.handle_error(s, err); - } else { - self.fire_uncaptured_error(err); - } - } - self.try_remove_scope(s_id); - } else if let Err((err, _)) = result { - self.fire_uncaptured_error(err); + pub fn dispatch_error(&self, error: webgpu::Error) { + if let Err(e) = self.channel.0.send(WebGPURequest::DispatchError { + device_id: self.device.0, + error, + }) { + warn!("Failed to send WebGPURequest::DispatchError due to {e:?}"); } } - fn handle_error(&self, scope: ErrorScopeId, error: GPUError) { - let mut context = self.scope_context.borrow_mut(); - if let Some(err_scope) = context.error_scopes.get_mut(&scope) { - if err_scope.error.is_none() { - err_scope.error = Some(error); - } - } else { - warn!("Could not find ErrorScope with Id({})", scope); - } - } - - fn try_remove_scope(&self, scope: ErrorScopeId) { - let mut context = self.scope_context.borrow_mut(); - let remove = if let Some(err_scope) = context.error_scopes.get_mut(&scope) { - err_scope.op_count -= 1; - if let Some(ref promise) = err_scope.promise { - if !promise.is_fulfilled() { - if let Some(ref e) = err_scope.error { - promise.resolve_native(e); - } else if err_scope.op_count == 0 { - promise.resolve_native(&None::<GPUError>); - } - } - } - err_scope.op_count == 0 && err_scope.promise.is_some() - } else { - warn!("Could not find ErrorScope with Id({})", scope); - false - }; - if remove { - let _ = context.error_scopes.remove(&scope); - context.scope_stack.retain(|meta| meta.id != scope); - } - } - - fn fire_uncaptured_error(&self, err: GPUError) { + pub fn fire_uncaptured_error(&self, error: webgpu::Error) { + let error = GPUError::from_error(&self.global(), error); let ev = GPUUncapturedErrorEvent::new( &self.global(), DOMString::from("uncapturederror"), &GPUUncapturedErrorEventInit { - error: err, + error, parent: EventInit::empty(), }, ); let _ = self.eventtarget.DispatchEvent(ev.event()); } - pub fn use_current_scope(&self) -> Option<ErrorScopeId> { - let mut context = self.scope_context.borrow_mut(); - 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(|scope| { - scope.op_count += 1; - s_id - }) - }) - } - fn get_pipeline_layout_data( &self, layout: &GPUPipelineLayoutOrGPUAutoLayoutMode, @@ -379,24 +269,19 @@ impl GPUDeviceMethods for GPUDevice { .lock() .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.dispatch_error(webgpu::Error::Validation(String::from( + "Invalid GPUBufferUsage", + ))); } self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateBuffer { - device_id: self.device.0, - buffer_id: id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateBuffer { + device_id: self.device.0, + buffer_id: id, + descriptor: desc, + }) .expect("Failed to create WebGPU buffer"); let buffer = webgpu::WebGPUBuffer(id); @@ -509,18 +394,15 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(); - let scope_id = self.use_current_scope(); - let desc = if valid { Some(wgpu_bind::BindGroupLayoutDescriptor { label: convert_label(&descriptor.parent), entries: Cow::Owned(entries), }) } else { - self.handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from("Invalid GPUShaderStage")), - ); + self.dispatch_error(webgpu::Error::Validation(String::from( + "Invalid GPUShaderStage", + ))); None }; @@ -531,14 +413,11 @@ impl GPUDeviceMethods for GPUDevice { .create_bind_group_layout_id(self.device.0.backend()); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateBindGroupLayout { - device_id: self.device.0, - bind_group_layout_id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateBindGroupLayout { + device_id: self.device.0, + bind_group_layout_id, + descriptor: desc, + }) .expect("Failed to create WebGPU BindGroupLayout"); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); @@ -568,8 +447,6 @@ impl GPUDeviceMethods for GPUDevice { push_constant_ranges: Cow::Owned(vec![]), }; - let scope_id = self.use_current_scope(); - let pipeline_layout_id = self .global() .wgpu_id_hub() @@ -577,14 +454,11 @@ impl GPUDeviceMethods for GPUDevice { .create_pipeline_layout_id(self.device.0.backend()); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreatePipelineLayout { - device_id: self.device.0, - pipeline_layout_id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreatePipelineLayout { + device_id: self.device.0, + pipeline_layout_id, + descriptor: desc, + }) .expect("Failed to create WebGPU PipelineLayout"); let bgls = descriptor @@ -633,8 +507,6 @@ impl GPUDeviceMethods for GPUDevice { entries: Cow::Owned(entries), }; - let scope_id = self.use_current_scope(); - let bind_group_id = self .global() .wgpu_id_hub() @@ -642,14 +514,11 @@ impl GPUDeviceMethods for GPUDevice { .create_bind_group_id(self.device.0.backend()); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateBindGroup { - device_id: self.device.0, - bind_group_id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateBindGroup { + device_id: self.device.0, + bind_group_id, + descriptor: desc, + }) .expect("Failed to create WebGPU BindGroup"); let bind_group = webgpu::WebGPUBindGroup(bind_group_id); @@ -675,18 +544,14 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_shader_module_id(self.device.0.backend()); - let scope_id = self.use_current_scope(); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateShaderModule { - device_id: self.device.0, - program_id, - program: descriptor.code.0.clone(), - label: None, - }, - )) + .send(WebGPURequest::CreateShaderModule { + device_id: self.device.0, + program_id, + program: descriptor.code.0.clone(), + label: None, + }) .expect("Failed to create WebGPU ShaderModule"); let shader_module = webgpu::WebGPUShaderModule(program_id); @@ -709,7 +574,6 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_compute_pipeline_id(self.device.0.backend()); - let scope_id = self.use_current_scope(); let (layout, implicit_ids, bgls) = self.get_pipeline_layout_data(&descriptor.parent.layout); let desc = wgpu_pipe::ComputePipelineDescriptor { @@ -725,15 +589,12 @@ impl GPUDeviceMethods for GPUDevice { self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateComputePipeline { - device_id: self.device.0, - compute_pipeline_id, - descriptor: desc, - implicit_ids, - }, - )) + .send(WebGPURequest::CreateComputePipeline { + device_id: self.device.0, + compute_pipeline_id, + descriptor: desc, + implicit_ids, + }) .expect("Failed to create WebGPU ComputePipeline"); let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); @@ -768,17 +629,13 @@ impl GPUDeviceMethods for GPUDevice { .wgpu_id_hub() .lock() .create_command_encoder_id(self.device.0.backend()); - let scope_id = self.use_current_scope(); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateCommandEncoder { - device_id: self.device.0, - command_encoder_id, - label: convert_label(&descriptor.parent), - }, - )) + .send(WebGPURequest::CreateCommandEncoder { + device_id: self.device.0, + command_encoder_id, + label: convert_label(&descriptor.parent), + }) .expect("Failed to create WebGPU command encoder"); let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id); @@ -822,20 +679,16 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_texture_id(self.device.0.backend()); - let scope_id = self.use_current_scope(); if desc.is_none() { return Err(Error::Type(String::from("Invalid GPUTextureUsage"))); } self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateTexture { - device_id: self.device.0, - texture_id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateTexture { + device_id: self.device.0, + texture_id, + descriptor: desc, + }) .expect("Failed to create WebGPU Texture"); let texture = webgpu::WebGPUTexture(texture_id); @@ -880,17 +733,13 @@ impl GPUDeviceMethods for GPUDevice { border_color: None, }; - let scope_id = self.use_current_scope(); self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateSampler { - device_id: self.device.0, - sampler_id, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateSampler { + device_id: self.device.0, + sampler_id, + descriptor: desc, + }) .expect("Failed to create WebGPU sampler"); let sampler = webgpu::WebGPUSampler(sampler_id); @@ -910,7 +759,6 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPURenderPipelineDescriptor, ) -> DomRoot<GPURenderPipeline> { - let scope_id = self.use_current_scope(); let mut valid = true; let (layout, implicit_ids, bgls) = self.get_pipeline_layout_data(&descriptor.parent.layout); @@ -1028,10 +876,9 @@ impl GPUDeviceMethods for GPUDevice { multiview: None, }) } else { - self.handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from("Invalid GPUColorWriteFlags")), - ); + self.dispatch_error(webgpu::Error::Validation(String::from( + "Invalid GPUColorWriteFlags", + ))); None }; @@ -1043,15 +890,12 @@ impl GPUDeviceMethods for GPUDevice { self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateRenderPipeline { - device_id: self.device.0, - render_pipeline_id, - descriptor: desc, - implicit_ids, - }, - )) + .send(WebGPURequest::CreateRenderPipeline { + device_id: self.device.0, + render_pipeline_id, + descriptor: desc, + implicit_ids, + }) .expect("Failed to create WebGPU render pipeline"); let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); @@ -1117,50 +961,33 @@ impl GPUDeviceMethods for GPUDevice { /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope> fn PushErrorScope(&self, filter: GPUErrorFilter) { - let mut context = self.scope_context.borrow_mut(); - let scope_id = context.next_scope_id; - context.next_scope_id = ErrorScopeId::new(scope_id.get() + 1).unwrap(); - let err_scope = ErrorScopeInfo { - op_count: 0, - error: None, - promise: None, - }; - let res = context.error_scopes.insert(scope_id, err_scope); - context.scope_stack.push(ErrorScopeMetadata { - id: scope_id, - filter, - popped: Cell::new(false), - }); - assert!(res.is_none()); + if self + .channel + .0 + .send(WebGPURequest::PushErrorScope { + device_id: self.device.0, + filter: filter.to_webgpu(), + }) + .is_err() + { + warn!("Failed sending WebGPURequest::PushErrorScope"); + } } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope> fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> { - let mut context = self.scope_context.borrow_mut(); let promise = Promise::new_in_current_realm(comp); - 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(err_scope) = context.error_scopes.get_mut(&scope_id) { - if let Some(ref e) = err_scope.error { - promise.resolve_native(e); - } else if err_scope.op_count == 0 { - promise.resolve_native(&None::<GPUError>); - } - err_scope.promise = Some(promise.clone()); - err_scope.op_count == 0 - } else { - error!("Could not find ErrorScope with Id({})", scope_id); - false - }; - if remove { - let _ = context.error_scopes.remove(&scope_id); - context.scope_stack.retain(|meta| meta.id != scope_id); + let sender = response_async(&promise, self); + if self + .channel + .0 + .send(WebGPURequest::PopErrorScope { + device_id: self.device.0, + sender, + }) + .is_err() + { + warn!("Error when sending WebGPURequest::PopErrorScope"); } promise } @@ -1178,7 +1005,7 @@ impl GPUDeviceMethods for GPUDevice { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DestroyDevice(self.device.0))) + .send(WebGPURequest::DestroyDevice(self.device.0)) { warn!("Failed to send DestroyDevice ({:?}) ({})", self.device.0, e); } @@ -1186,19 +1013,35 @@ impl GPUDeviceMethods for GPUDevice { } } +impl AsyncWGPUListener for GPUDevice { + fn handle_response(&self, response: Option<WebGPUResponseResult>, promise: &Rc<Promise>) { + match response { + Some(Ok(WebGPUResponse::PoppedErrorScope(result))) => match result { + Ok(None) | Err(PopError::Lost) => promise.resolve_native(&None::<Option<GPUError>>), + Err(PopError::Empty) => promise.reject_error(Error::Operation), + Ok(Some(error)) => { + let error = GPUError::from_error(&self.global(), error); + promise.resolve_native(&error); + }, + }, + _ => unreachable!("Wrong response recived on AsyncWGPUListener for GPUDevice"), + } + } +} + impl Drop for GPUDevice { fn drop(&mut self) { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DestroyDevice(self.device.0))) + .send(WebGPURequest::DestroyDevice(self.device.0)) { warn!("Failed to send DestroyDevice ({:?}) ({})", self.device.0, e); } if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropDevice(self.device.0))) + .send(WebGPURequest::DropDevice(self.device.0)) { warn!("Failed to send DropDevice ({:?}) ({})", self.device.0, e); } diff --git a/components/script/dom/gpuerror.rs b/components/script/dom/gpuerror.rs new file mode 100644 index 00000000000..107277dd00e --- /dev/null +++ b/components/script/dom/gpuerror.rs @@ -0,0 +1,90 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use dom_struct::dom_struct; +use js::rust::HandleObject; +use webgpu::{Error, ErrorFilter}; + +use super::types::{GPUInternalError, GPUOutOfMemoryError, GPUValidationError}; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{GPUErrorFilter, GPUErrorMethods}; +use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; + +#[dom_struct] +pub struct GPUError { + reflector_: Reflector, + message: DOMString, +} + +impl GPUError { + pub fn new_inherited(message: DOMString) -> Self { + Self { + reflector_: Reflector::new(), + message, + } + } + + #[allow(dead_code)] + pub fn new(global: &GlobalScope, message: DOMString) -> DomRoot<Self> { + Self::new_with_proto(global, None, message) + } + + #[allow(dead_code)] + pub fn new_with_proto( + global: &GlobalScope, + proto: Option<HandleObject>, + message: DOMString, + ) -> DomRoot<Self> { + reflect_dom_object_with_proto(Box::new(GPUError::new_inherited(message)), global, proto) + } + + pub fn from_error(global: &GlobalScope, error: Error) -> DomRoot<Self> { + match error { + Error::Validation(msg) => DomRoot::upcast(GPUValidationError::new_with_proto( + global, + None, + DOMString::from_string(msg), + )), + Error::OutOfMemory(msg) => DomRoot::upcast(GPUOutOfMemoryError::new_with_proto( + global, + None, + DOMString::from_string(msg), + )), + Error::Internal(msg) => DomRoot::upcast(GPUInternalError::new_with_proto( + global, + None, + DOMString::from_string(msg), + )), + } + } +} + +impl GPUErrorMethods for GPUError { + /// <https://gpuweb.github.io/gpuweb/#dom-gpuerror-message> + fn Message(&self) -> DOMString { + self.message.clone() + } +} + +impl From<ErrorFilter> for GPUErrorFilter { + fn from(filter: ErrorFilter) -> Self { + match filter { + ErrorFilter::Validation => GPUErrorFilter::Validation, + ErrorFilter::OutOfMemory => GPUErrorFilter::Out_of_memory, + ErrorFilter::Internal => GPUErrorFilter::Internal, + } + } +} + +impl GPUErrorFilter { + pub fn to_webgpu(&self) -> ErrorFilter { + match self { + GPUErrorFilter::Validation => ErrorFilter::Validation, + GPUErrorFilter::Out_of_memory => ErrorFilter::OutOfMemory, + GPUErrorFilter::Internal => ErrorFilter::Internal, + } + } +} diff --git a/components/script/dom/gpuinternalerror.rs b/components/script/dom/gpuinternalerror.rs new file mode 100644 index 00000000000..5c5987b2649 --- /dev/null +++ b/components/script/dom/gpuinternalerror.rs @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use dom_struct::dom_struct; +use js::rust::HandleObject; + +use super::types::GPUError; +use crate::dom::bindings::reflector::reflect_dom_object_with_proto; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; + +#[dom_struct] +pub struct GPUInternalError { + gpu_error: GPUError, +} + +impl GPUInternalError { + fn new_inherited(message: DOMString) -> Self { + Self { + gpu_error: GPUError::new_inherited(message), + } + } + + pub fn new_with_proto( + global: &GlobalScope, + proto: Option<HandleObject>, + message: DOMString, + ) -> DomRoot<Self> { + reflect_dom_object_with_proto(Box::new(Self::new_inherited(message)), global, proto) + } + + /// <https://gpuweb.github.io/gpuweb/#dom-GPUInternalError-GPUInternalError> + #[allow(non_snake_case)] + pub fn Constructor( + global: &GlobalScope, + proto: Option<HandleObject>, + message: DOMString, + ) -> DomRoot<Self> { + Self::new_with_proto(global, proto, message) + } +} diff --git a/components/script/dom/gpuoutofmemoryerror.rs b/components/script/dom/gpuoutofmemoryerror.rs index 65252a28530..c3278473970 100644 --- a/components/script/dom/gpuoutofmemoryerror.rs +++ b/components/script/dom/gpuoutofmemoryerror.rs @@ -5,37 +5,39 @@ use dom_struct::dom_struct; use js::rust::HandleObject; -use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector}; +use super::types::GPUError; +use crate::dom::bindings::reflector::reflect_dom_object_with_proto; use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; #[dom_struct] pub struct GPUOutOfMemoryError { - reflector_: Reflector, + gpu_error: GPUError, } impl GPUOutOfMemoryError { - fn new_inherited() -> Self { + fn new_inherited(message: DOMString) -> Self { Self { - reflector_: Reflector::new(), + gpu_error: GPUError::new_inherited(message), } } - pub fn new(global: &GlobalScope) -> DomRoot<Self> { - Self::new_with_proto(global, None) + pub fn new_with_proto( + global: &GlobalScope, + proto: Option<HandleObject>, + message: DOMString, + ) -> DomRoot<Self> { + reflect_dom_object_with_proto(Box::new(Self::new_inherited(message)), global, proto) } - fn new_with_proto(global: &GlobalScope, proto: Option<HandleObject>) -> DomRoot<Self> { - reflect_dom_object_with_proto( - Box::new(GPUOutOfMemoryError::new_inherited()), - global, - proto, - ) - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpuoutofmemoryerror-gpuoutofmemoryerror> + /// <https://gpuweb.github.io/gpuweb/#dom-GPUOutOfMemoryError-GPUOutOfMemoryError> #[allow(non_snake_case)] - pub fn Constructor(global: &GlobalScope, proto: Option<HandleObject>) -> DomRoot<Self> { - GPUOutOfMemoryError::new_with_proto(global, proto) + pub fn Constructor( + global: &GlobalScope, + proto: Option<HandleObject>, + message: DOMString, + ) -> DomRoot<Self> { + Self::new_with_proto(global, proto, message) } } diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index 264b31bf30d..c2554f3b882 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -84,10 +84,11 @@ impl GPUPipelineLayoutMethods for GPUPipelineLayout { impl Drop for GPUPipelineLayout { fn drop(&mut self) { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DropPipelineLayout(self.pipeline_layout.0), - )) { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DropPipelineLayout(self.pipeline_layout.0)) + { warn!( "Failed to send DropPipelineLayout ({:?}) ({})", self.pipeline_layout.0, e diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs index 4a2fef174b3..a3c49db0182 100644 --- a/components/script/dom/gpuqueue.rs +++ b/components/script/dom/gpuqueue.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; -use webgpu::{wgt, WebGPU, WebGPUOpResult, WebGPUQueue, WebGPURequest, WebGPUResponse}; +use webgpu::{wgt, WebGPU, WebGPUQueue, WebGPURequest, WebGPUResponse}; use super::bindings::codegen::Bindings::WebGPUBinding::{GPUImageCopyTexture, GPUImageDataLayout}; use super::gpu::{response_async, AsyncWGPUListener}; @@ -81,26 +81,23 @@ impl GPUQueueMethods for GPUQueue { .iter() .all(|b| matches!(b.state(), GPUBufferState::Unmapped)) }); - let scope_id = self.device.borrow().as_ref().unwrap().use_current_scope(); if !valid { - self.device.borrow().as_ref().unwrap().handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from( + self.device + .borrow() + .as_ref() + .unwrap() + .dispatch_error(webgpu::Error::Validation(String::from( "Referenced GPUBuffer(s) are not Unmapped", - )), - ); + ))); return; } let command_buffers = command_buffers.iter().map(|cb| cb.id().0).collect(); self.channel .0 - .send(( - scope_id, - WebGPURequest::Submit { - queue_id: self.queue.0, - command_buffers, - }, - )) + .send(WebGPURequest::Submit { + queue_id: self.queue.0, + command_buffers, + }) .unwrap(); } @@ -135,15 +132,12 @@ impl GPUQueueMethods for GPUQueue { let final_data = IpcSharedMemory::from_bytes( &bytes[data_offset as usize..(data_offset + content_size) as usize], ); - if let Err(e) = self.channel.0.send(( - self.device.borrow().as_ref().unwrap().use_current_scope(), - WebGPURequest::WriteBuffer { - queue_id: self.queue.0, - buffer_id: buffer.id().0, - buffer_offset, - data: final_data, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::WriteBuffer { + queue_id: self.queue.0, + buffer_id: buffer.id().0, + buffer_offset, + data: final_data, + }) { warn!("Failed to send WriteBuffer({:?}) ({})", buffer.id(), e); return Err(Error::Operation); } @@ -174,16 +168,13 @@ impl GPUQueueMethods for GPUQueue { let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size)); let final_data = IpcSharedMemory::from_bytes(&bytes); - if let Err(e) = self.channel.0.send(( - self.device.borrow().as_ref().unwrap().use_current_scope(), - WebGPURequest::WriteTexture { - queue_id: self.queue.0, - texture_cv, - data_layout: texture_layout, - size: write_size, - data: final_data, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::WriteTexture { + queue_id: self.queue.0, + texture_cv, + data_layout: texture_layout, + size: write_size, + data: final_data, + }) { warn!( "Failed to send WriteTexture({:?}) ({})", destination.texture.id().0, @@ -200,13 +191,14 @@ impl GPUQueueMethods for GPUQueue { let global = self.global(); let promise = Promise::new(&global); let sender = response_async(&promise, self); - if let Err(e) = self.channel.0.send(( - self.device.borrow().as_ref().unwrap().use_current_scope(), - WebGPURequest::QueueOnSubmittedWorkDone { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::QueueOnSubmittedWorkDone { sender, queue_id: self.queue.0, - }, - )) { + }) + { warn!("QueueOnSubmittedWorkDone failed with {e}") } promise diff --git a/components/script/dom/gpurenderbundle.rs b/components/script/dom/gpurenderbundle.rs index 7dff530b222..92827df6ab7 100644 --- a/components/script/dom/gpurenderbundle.rs +++ b/components/script/dom/gpurenderbundle.rs @@ -83,7 +83,7 @@ impl Drop for GPURenderBundle { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropRenderBundle(self.render_bundle.0))) + .send(WebGPURequest::DropRenderBundle(self.render_bundle.0)) { warn!( "Failed to send DropRenderBundle ({:?}) ({})", diff --git a/components/script/dom/gpurenderbundleencoder.rs b/components/script/dom/gpurenderbundleencoder.rs index 7fb3de9c489..ee405e2e60c 100644 --- a/components/script/dom/gpurenderbundleencoder.rs +++ b/components/script/dom/gpurenderbundleencoder.rs @@ -209,15 +209,12 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder { self.channel .0 - .send(( - self.device.use_current_scope(), - WebGPURequest::RenderBundleEncoderFinish { - render_bundle_encoder: encoder, - descriptor: desc, - render_bundle_id, - device_id: self.device.id().0, - }, - )) + .send(WebGPURequest::RenderBundleEncoderFinish { + render_bundle_encoder: encoder, + descriptor: desc, + render_bundle_id, + device_id: self.device.id().0, + }) .expect("Failed to send RenderBundleEncoderFinish"); let render_bundle = WebGPURenderBundle(render_bundle_id); diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs index a0a87ad4f4d..e650284664f 100644 --- a/components/script/dom/gpurenderpassencoder.rs +++ b/components/script/dom/gpurenderpassencoder.rs @@ -164,13 +164,10 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder { let render_pass = self.render_pass.borrow_mut().take(); self.channel .0 - .send(( - None, - WebGPURequest::RunRenderPass { - command_encoder_id: self.command_encoder.id().0, - render_pass, - }, - )) + .send(WebGPURequest::RunRenderPass { + command_encoder_id: self.command_encoder.id().0, + render_pass, + }) .expect("Failed to send RunRenderPass"); self.command_encoder.set_state( diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs index 411c176c326..cf2dc885ce4 100644 --- a/components/script/dom/gpurenderpipeline.rs +++ b/components/script/dom/gpurenderpipeline.rs @@ -100,10 +100,11 @@ impl GPURenderPipelineMethods for GPURenderPipeline { impl Drop for GPURenderPipeline { fn drop(&mut self) { - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DropRenderPipeline(self.render_pipeline.0), - )) { + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DropRenderPipeline(self.render_pipeline.0)) + { warn!( "Failed to send WebGPURequest::DropRenderPipeline({:?}) ({})", self.render_pipeline.0, e diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs index 5325877c8fd..5a7ce54814d 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -88,7 +88,7 @@ impl Drop for GPUSampler { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropSampler(self.sampler.0))) + .send(WebGPURequest::DropSampler(self.sampler.0)) { warn!("Failed to send DropSampler ({:?}) ({})", self.sampler.0, e); } diff --git a/components/script/dom/gpushadermodule.rs b/components/script/dom/gpushadermodule.rs index 56e37808031..26f9fad8388 100644 --- a/components/script/dom/gpushadermodule.rs +++ b/components/script/dom/gpushadermodule.rs @@ -82,7 +82,7 @@ impl Drop for GPUShaderModule { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropShaderModule(self.shader_module.0))) + .send(WebGPURequest::DropShaderModule(self.shader_module.0)) { warn!( "Failed to send DropShaderModule ({:?}) ({})", diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 4f97024f774..062b2101d0a 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -7,7 +7,7 @@ use std::string::String; use dom_struct::dom_struct; use webgpu::wgc::resource; -use webgpu::{wgt, WebGPU, WebGPUOpResult, WebGPURequest, WebGPUTexture, WebGPUTextureView}; +use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ @@ -114,7 +114,7 @@ impl Drop for GPUTexture { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropTexture(self.texture.0))) + .send(WebGPURequest::DropTexture(self.texture.0)) { warn!( "Failed to send WebGPURequest::DropTexture({:?}) ({})", @@ -143,8 +143,6 @@ impl GPUTextureMethods for GPUTexture { /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-createview> fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot<GPUTextureView> { - let scope_id = self.device.use_current_scope(); - let desc = if !matches!(descriptor.mipLevelCount, Some(0)) && !matches!(descriptor.arrayLayerCount, Some(0)) { @@ -165,12 +163,10 @@ impl GPUTextureMethods for GPUTexture { }, }) } else { - self.device.handle_server_msg( - scope_id, - WebGPUOpResult::ValidationError(String::from( + self.device + .dispatch_error(webgpu::Error::Validation(String::from( "arrayLayerCount and mipLevelCount cannot be 0", - )), - ); + ))); None }; @@ -182,15 +178,12 @@ impl GPUTextureMethods for GPUTexture { self.channel .0 - .send(( - scope_id, - WebGPURequest::CreateTextureView { - texture_id: self.texture.0, - texture_view_id, - device_id: self.device.id().0, - descriptor: desc, - }, - )) + .send(WebGPURequest::CreateTextureView { + texture_id: self.texture.0, + texture_view_id, + device_id: self.device.id().0, + descriptor: desc, + }) .expect("Failed to create WebGPU texture view"); let texture_view = WebGPUTextureView(texture_view_id); @@ -209,13 +202,10 @@ impl GPUTextureMethods for GPUTexture { if self.destroyed.get() { return; } - if let Err(e) = self.channel.0.send(( - None, - WebGPURequest::DestroyTexture { - device_id: self.device.id().0, - texture_id: self.texture.0, - }, - )) { + if let Err(e) = self.channel.0.send(WebGPURequest::DestroyTexture { + device_id: self.device.id().0, + texture_id: self.texture.0, + }) { warn!( "Failed to send WebGPURequest::DestroyTexture({:?}) ({})", self.texture.0, e diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index d9bac21aa25..b7e703d670a 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -83,7 +83,7 @@ impl Drop for GPUTextureView { if let Err(e) = self .channel .0 - .send((None, WebGPURequest::DropTextureView(self.texture_view.0))) + .send(WebGPURequest::DropTextureView(self.texture_view.0)) { warn!( "Failed to send DropTextureView ({:?}) ({})", diff --git a/components/script/dom/gpuuncapturederrorevent.rs b/components/script/dom/gpuuncapturederrorevent.rs index fbc210516f7..5b33146082a 100644 --- a/components/script/dom/gpuuncapturederrorevent.rs +++ b/components/script/dom/gpuuncapturederrorevent.rs @@ -8,25 +8,26 @@ use servo_atoms::Atom; use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUError, GPUUncapturedErrorEventInit, GPUUncapturedErrorEventMethods, + GPUUncapturedErrorEventInit, GPUUncapturedErrorEventMethods, }; use crate::dom::bindings::reflector::reflect_dom_object_with_proto; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::event::Event; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpuerror::GPUError; #[dom_struct] pub struct GPUUncapturedErrorEvent { event: Event, #[ignore_malloc_size_of = "Because it is non-owning"] - gpu_error: GPUError, + gpu_error: Dom<GPUError>, } impl GPUUncapturedErrorEvent { fn new_inherited(init: &GPUUncapturedErrorEventInit) -> Self { Self { - gpu_error: clone_gpu_error(&init.error), + gpu_error: Dom::from_ref(&init.error), event: Event::new_inherited(), } } @@ -78,8 +79,8 @@ impl GPUUncapturedErrorEvent { impl GPUUncapturedErrorEventMethods for GPUUncapturedErrorEvent { /// <https://gpuweb.github.io/gpuweb/#dom-gpuuncapturederrorevent-error> - fn Error(&self) -> GPUError { - clone_gpu_error(&self.gpu_error) + fn Error(&self) -> DomRoot<GPUError> { + DomRoot::from_ref(&self.gpu_error) } /// <https://dom.spec.whatwg.org/#dom-event-istrusted> @@ -87,10 +88,3 @@ impl GPUUncapturedErrorEventMethods for GPUUncapturedErrorEvent { self.event.IsTrusted() } } - -fn clone_gpu_error(error: &GPUError) -> GPUError { - match *error { - GPUError::GPUValidationError(ref v) => GPUError::GPUValidationError(v.clone()), - GPUError::GPUOutOfMemoryError(ref w) => GPUError::GPUOutOfMemoryError(w.clone()), - } -} diff --git a/components/script/dom/gpuvalidationerror.rs b/components/script/dom/gpuvalidationerror.rs index 176429ef490..ebabee325f8 100644 --- a/components/script/dom/gpuvalidationerror.rs +++ b/components/script/dom/gpuvalidationerror.rs @@ -5,41 +5,30 @@ use dom_struct::dom_struct; use js::rust::HandleObject; -use super::bindings::error::Fallible; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUValidationErrorMethods; -use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector}; +use super::types::GPUError; +use crate::dom::bindings::reflector::reflect_dom_object_with_proto; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; #[dom_struct] pub struct GPUValidationError { - reflector_: Reflector, - message: DOMString, + gpu_error: GPUError, } impl GPUValidationError { fn new_inherited(message: DOMString) -> Self { Self { - reflector_: Reflector::new(), - message, + gpu_error: GPUError::new_inherited(message), } } - pub fn new(global: &GlobalScope, message: DOMString) -> DomRoot<Self> { - Self::new_with_proto(global, None, message) - } - - fn new_with_proto( + pub fn new_with_proto( global: &GlobalScope, proto: Option<HandleObject>, message: DOMString, ) -> DomRoot<Self> { - reflect_dom_object_with_proto( - Box::new(GPUValidationError::new_inherited(message)), - global, - proto, - ) + reflect_dom_object_with_proto(Box::new(Self::new_inherited(message)), global, proto) } /// <https://gpuweb.github.io/gpuweb/#dom-gpuvalidationerror-gpuvalidationerror> @@ -48,14 +37,7 @@ impl GPUValidationError { global: &GlobalScope, proto: Option<HandleObject>, message: DOMString, - ) -> Fallible<DomRoot<Self>> { - Ok(GPUValidationError::new_with_proto(global, proto, message)) - } -} - -impl GPUValidationErrorMethods for GPUValidationError { - /// <https://gpuweb.github.io/gpuweb/#dom-gpuvalidationerror-message> - fn Message(&self) -> DOMString { - self.message.clone() + ) -> DomRoot<Self> { + Self::new_with_proto(global, proto, message) } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 3c738b52d3b..7f8bea43ff3 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -340,6 +340,8 @@ pub mod gpucomputepipeline; pub mod gpuconvert; pub mod gpudevice; pub mod gpudevicelostinfo; +pub mod gpuerror; +pub mod gpuinternalerror; pub mod gpumapmode; pub mod gpuoutofmemoryerror; pub mod gpupipelinelayout; diff --git a/components/script/dom/webidls/WebGPU.webidl b/components/script/dom/webidls/WebGPU.webidl index 20b5a3ba5ff..82d6968080f 100644 --- a/components/script/dom/webidls/WebGPU.webidl +++ b/components/script/dom/webidls/WebGPU.webidl @@ -1086,19 +1086,28 @@ partial interface GPUDevice { readonly attribute Promise<GPUDeviceLostInfo> lost; }; -[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] -interface GPUValidationError { - [Throws] - constructor(DOMString message); +[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"] +interface GPUError { readonly attribute DOMString message; }; -[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] -interface GPUOutOfMemoryError { - constructor(); +[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"] +interface GPUValidationError + : GPUError { + constructor(DOMString message); }; -typedef (GPUOutOfMemoryError or GPUValidationError) GPUError; +[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"] +interface GPUOutOfMemoryError + : GPUError { + constructor(DOMString message); +}; + +[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"] +interface GPUInternalError + : GPUError { + constructor(DOMString message); +}; enum GPUErrorFilter { "validation", @@ -1112,7 +1121,7 @@ partial interface GPUDevice { Promise<GPUError?> popErrorScope(); }; -[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +[Exposed=(Window, Worker), Pref="dom.webgpu.enabled"] interface GPUUncapturedErrorEvent : Event { constructor( DOMString type, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 7bcf54f8bae..25fc32fcdb7 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -2398,22 +2398,21 @@ impl ScriptThread { WebGPUMsg::FreeTexture(id) => self.gpu_id_hub.lock().kill_texture_id(id), WebGPUMsg::FreeTextureView(id) => self.gpu_id_hub.lock().kill_texture_view_id(id), WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None, - WebGPUMsg::WebGPUOpResult { - device, - scope_id, + WebGPUMsg::CleanDevice { pipeline_id, - result, + device, } => { let global = self.documents.borrow().find_global(pipeline_id).unwrap(); - let _ac = enter_realm(&*global); - global.handle_wgpu_msg(device, scope_id, result); + global.remove_gpu_device(device); }, - WebGPUMsg::CleanDevice { - pipeline_id, + WebGPUMsg::UncapturedError { device, + pipeline_id, + error, } => { let global = self.documents.borrow().find_global(pipeline_id).unwrap(); - global.remove_gpu_device(device); + let _ac = enter_realm(&*global); + global.handle_uncaptured_gpu_error(device, error); }, _ => {}, } |