diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/Bindings.conf | 4 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 34 | ||||
-rw-r--r-- | components/script/dom/gpuadapter.rs | 5 | ||||
-rw-r--r-- | components/script/dom/gpucommandencoder.rs | 35 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 165 | ||||
-rw-r--r-- | components/script/dom/gpudevicelostinfo.rs | 38 | ||||
-rw-r--r-- | components/script/dom/gpuoutofmemoryerror.rs | 31 | ||||
-rw-r--r-- | components/script/dom/gpuvalidationerror.rs | 42 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 3 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUDeviceLostInfo.webidl | 13 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUOutOfMemoryError.webidl | 9 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUValidationError.webidl | 22 |
12 files changed, 382 insertions, 19 deletions
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf index e4d4c234262..ec8974b6cbd 100644 --- a/components/script/dom/bindings/codegen/Bindings.conf +++ b/components/script/dom/bindings/codegen/Bindings.conf @@ -154,6 +154,10 @@ DOMInterfaces = { 'GPUBuffer': { 'inRealms': ['MapAsync'], +}, + +'GPUDevice': { + 'inRealms': ['PopErrorScope', 'Lost'], } } diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index ea25d443ccb..7b2d7ec25a0 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -5,6 +5,7 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods; use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSourceBinding::EventSourceMethods; +use crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::GPUError; use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::{ ImageBitmapOptions, ImageBitmapSource, }; @@ -34,6 +35,9 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::eventsource::EventSource; use crate::dom::eventtarget::EventTarget; use crate::dom::file::File; +use crate::dom::gpudevice::GPUDevice; +use crate::dom::gpuoutofmemoryerror::GPUOutOfMemoryError; +use crate::dom::gpuvalidationerror::GPUValidationError; use crate::dom::htmlscriptelement::ScriptId; use crate::dom::identityhub::Identities; use crate::dom::imagebitmap::ImageBitmap; @@ -122,6 +126,7 @@ use std::sync::Arc; use std::thread::JoinHandle; use time::{get_time, Timespec}; use uuid::Uuid; +use webgpu::{identity::WebGPUOpResult, WebGPUDevice}; #[derive(JSTraceable)] pub struct AutoCloseWorker { @@ -289,6 +294,9 @@ pub struct GlobalScope { #[ignore_malloc_size_of = "defined in wgpu"] gpu_id_hub: Arc<Mutex<Identities>>, + /// WebGPU devices + gpu_devices: DomRefCell<HashMap<WebGPUDevice, Dom<GPUDevice>>>, + // https://w3c.github.io/performance-timeline/#supportedentrytypes-attribute #[ignore_malloc_size_of = "mozjs"] frozen_supported_performance_entry_types: DomRefCell<Option<Heap<JSVal>>>, @@ -745,6 +753,7 @@ impl GlobalScope { is_headless, user_agent, gpu_id_hub, + gpu_devices: DomRefCell::new(HashMap::new()), frozen_supported_performance_entry_types: DomRefCell::new(Default::default()), https_state: Cell::new(HttpsState::None), console_group_stack: DomRefCell::new(Vec::new()), @@ -2939,6 +2948,31 @@ impl GlobalScope { self.gpu_id_hub.clone() } + pub fn add_gpu_device(&self, device: &GPUDevice) { + self.gpu_devices + .borrow_mut() + .insert(device.id(), Dom::from_ref(device)); + } + + pub fn handle_wgpu_msg(&self, device: WebGPUDevice, scope: u64, result: WebGPUOpResult) { + let result = match result { + WebGPUOpResult::Success => Ok(()), + WebGPUOpResult::ValidationError(m) => { + let val_err = GPUValidationError::new(&self, DOMString::from_string(m)); + Err(GPUError::GPUValidationError(val_err)) + }, + WebGPUOpResult::OutOfMemoryError => { + let oom_err = GPUOutOfMemoryError::new(&self); + Err(GPUError::GPUOutOfMemoryError(oom_err)) + }, + }; + self.gpu_devices + .borrow() + .get(&device) + .expect("GPUDevice not found") + .handle_server_msg(scope, result); + } + pub(crate) fn current_group_label(&self) -> Option<DOMString> { self.console_group_stack .borrow() diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index a965295fd73..afab6b89d09 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -34,7 +34,7 @@ pub struct GPUAdapter { } impl GPUAdapter { - pub fn new_inherited( + fn new_inherited( channel: WebGPU, name: DOMString, extensions: Heap<*mut JSObject>, @@ -93,6 +93,7 @@ impl GPUAdapterMethods for GPUAdapter { .wgpu_id_hub() .lock() .create_device_id(self.adapter.0.backend()); + let pipeline_id = self.global().pipeline_id(); if self .channel .0 @@ -101,6 +102,7 @@ impl GPUAdapterMethods for GPUAdapter { adapter_id: self.adapter, descriptor: desc, device_id: id, + pipeline_id, }) .is_err() { @@ -127,6 +129,7 @@ impl AsyncWGPUListener for GPUAdapter { device_id, queue_id, ); + self.global().add_gpu_device(&device); promise.resolve_native(&device); }, _ => promise.reject_error(Error::Operation), diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 4f41daccfa2..3e11e58d116 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -24,7 +24,8 @@ use dom_struct::dom_struct; use std::cell::Cell; use std::collections::HashSet; use webgpu::wgpu::command::{ - ColorAttachmentDescriptor, DepthStencilAttachmentDescriptor, RenderPass, RenderPassDescriptor, + ColorAttachmentDescriptor, DepthStencilAttachmentDescriptor, LoadOp, PassChannel, RenderPass, + RenderPassDescriptor, StoreOp, }; use webgpu::{self, wgt, WebGPU, WebGPUDevice, WebGPURequest}; @@ -138,9 +139,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { .iter() .map(|color| { let (load_op, clear_value) = match color.loadValue { - GPUColorLoad::GPULoadOp(_) => (wgt::LoadOp::Load, wgt::Color::TRANSPARENT), + GPUColorLoad::GPULoadOp(_) => (LoadOp::Load, wgt::Color::TRANSPARENT), GPUColorLoad::DoubleSequence(ref s) => ( - wgt::LoadOp::Clear, + LoadOp::Clear, wgt::Color { r: *s[0], g: *s[1], @@ -149,7 +150,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { }, ), GPUColorLoad::GPUColorDict(ref d) => ( - wgt::LoadOp::Clear, + LoadOp::Clear, wgt::Color { r: *d.r, g: *d.g, @@ -158,11 +159,11 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { }, ), }; - let channel = wgt::PassChannel { + let channel = PassChannel { load_op, store_op: match color.storeOp { - GPUStoreOp::Store => wgt::StoreOp::Store, - GPUStoreOp::Clear => wgt::StoreOp::Clear, + GPUStoreOp::Store => StoreOp::Store, + GPUStoreOp::Clear => StoreOp::Clear, }, clear_value, read_only: false, @@ -177,27 +178,27 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { let depth_stencil = descriptor.depthStencilAttachment.as_ref().map(|depth| { let (depth_load_op, clear_depth) = match depth.depthLoadValue { - GPULoadOpOrFloat::GPULoadOp(_) => (wgt::LoadOp::Load, 0.0f32), - GPULoadOpOrFloat::Float(f) => (wgt::LoadOp::Clear, *f), + GPULoadOpOrFloat::GPULoadOp(_) => (LoadOp::Load, 0.0f32), + GPULoadOpOrFloat::Float(f) => (LoadOp::Clear, *f), }; let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue { - GPUStencilLoadValue::GPULoadOp(_) => (wgt::LoadOp::Load, 0u32), - GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (wgt::LoadOp::Clear, l), + GPUStencilLoadValue::GPULoadOp(_) => (LoadOp::Load, 0u32), + GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (LoadOp::Clear, l), }; - let depth_channel = wgt::PassChannel { + let depth_channel = PassChannel { load_op: depth_load_op, store_op: match depth.depthStoreOp { - GPUStoreOp::Store => wgt::StoreOp::Store, - GPUStoreOp::Clear => wgt::StoreOp::Clear, + GPUStoreOp::Store => StoreOp::Store, + GPUStoreOp::Clear => StoreOp::Clear, }, clear_value: clear_depth, read_only: depth.depthReadOnly, }; - let stencil_channel = wgt::PassChannel { + let stencil_channel = PassChannel { load_op: stencil_load_op, store_op: match depth.stencilStoreOp { - GPUStoreOp::Store => wgt::StoreOp::Store, - GPUStoreOp::Clear => wgt::StoreOp::Clear, + GPUStoreOp::Store => StoreOp::Store, + GPUStoreOp::Clear => StoreOp::Clear, }, clear_value: clear_stencil, read_only: depth.stencilReadOnly, diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index c5e5803f7e6..cda3b5a586d 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -31,7 +31,11 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUTextureDimension, GPUTextureFormat, }; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewDimension; +use crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::{ + GPUError, GPUErrorFilter, +}; use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array}; +use crate::dom::bindings::error::Error; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; @@ -50,16 +54,29 @@ use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gputexture::GPUTexture; +use crate::dom::promise::Promise; +use crate::realms::InRealm; use crate::script_runtime::JSContext as SafeJSContext; use arrayvec::ArrayVec; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; +use std::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; use webgpu::wgpu::binding_model::BufferBinding; use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest}; +#[derive(JSTraceable, MallocSizeOf)] +struct ErrorScopeInfo { + filter: GPUErrorFilter, + op_count: u64, + #[ignore_malloc_size_of = "defined in webgpu"] + error: Option<GPUError>, + #[ignore_malloc_size_of = "promises are hard"] + promise: Option<Rc<Promise>>, +} + #[dom_struct] pub struct GPUDevice { eventtarget: EventTarget, @@ -73,6 +90,11 @@ pub struct GPUDevice { label: DomRefCell<Option<DOMString>>, device: webgpu::WebGPUDevice, default_queue: Dom<GPUQueue>, + error_scopes: DomRefCell<HashMap<u64, ErrorScopeInfo>>, + scope_stack: DomRefCell<Vec<u64>>, + next_scope_id: Cell<u64>, + #[ignore_malloc_size_of = "promises are hard"] + lost_promise: DomRefCell<Option<Rc<Promise>>>, } impl GPUDevice { @@ -93,6 +115,10 @@ impl GPUDevice { label: DomRefCell::new(None), device, default_queue: Dom::from_ref(queue), + error_scopes: DomRefCell::new(HashMap::new()), + scope_stack: DomRefCell::new(Vec::new()), + next_scope_id: Cell::new(0), + lost_promise: DomRefCell::new(None), } } @@ -119,6 +145,37 @@ impl GPUDevice { pub fn id(&self) -> webgpu::WebGPUDevice { self.device } + + pub fn handle_server_msg(&self, scope: u64, result: Result<(), GPUError>) { + let mut err_scope; + { + err_scope = self.error_scopes.borrow_mut().remove(&scope).unwrap(); + } + err_scope.op_count -= 1; + match result { + Ok(()) => {}, + Err(e) => { + if err_scope.error.is_none() { + err_scope.error = Some(e); + } + }, + } + if let Some(ref promise) = err_scope.promise { + if !promise.is_fulfilled() { + if let Some(ref e) = err_scope.error { + match e { + GPUError::GPUValidationError(v) => promise.resolve_native(&v), + GPUError::GPUOutOfMemoryError(w) => promise.resolve_native(&w), + } + } else if err_scope.op_count == 0 { + promise.resolve_native(&None::<GPUError>); + } + } + } + if err_scope.op_count > 0 || err_scope.promise.is_none() { + let _ = self.error_scopes.borrow_mut().insert(scope, err_scope); + } + } } impl GPUDeviceMethods for GPUDevice { @@ -152,6 +209,13 @@ impl GPUDeviceMethods for GPUDevice { *self.label.borrow_mut() = value; } + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-lost + fn Lost(&self, comp: InRealm) -> Rc<Promise> { + let promise = Promise::new_in_current_realm(&self.global(), comp); + *self.lost_promise.borrow_mut() = Some(promise.clone()); + promise + } + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> { let wgpu_descriptor = wgt::BufferDescriptor { @@ -289,6 +353,16 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(); + let mut scope_id = None; + if let Some(s_id) = self.scope_stack.borrow_mut().last() { + if let Some(mut scope) = self.error_scopes.borrow_mut().get_mut(&s_id) { + scope.op_count += 1; + scope_id = Some(*s_id); + } else { + warn!("Could not find Error Scope for id {}", s_id); + } + } + let bind_group_layout_id = self .global() .wgpu_id_hub() @@ -300,6 +374,7 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, bind_group_layout_id, entries, + scope_id, }) .expect("Failed to create WebGPU BindGroupLayout"); @@ -320,6 +395,16 @@ impl GPUDeviceMethods for GPUDevice { } }); + let mut scope_id = None; + if let Some(s_id) = self.scope_stack.borrow_mut().last() { + if let Some(mut scope) = self.error_scopes.borrow_mut().get_mut(&s_id) { + scope.op_count += 1; + scope_id = Some(*s_id); + } else { + warn!("Could not find Error Scope for id {}", s_id); + } + } + let pipeline_layout_id = self .global() .wgpu_id_hub() @@ -331,6 +416,7 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, pipeline_layout_id, bind_group_layouts: bgl_ids, + scope_id, }) .expect("Failed to create WebGPU PipelineLayout"); @@ -369,6 +455,16 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(); + let mut scope_id = None; + if let Some(s_id) = self.scope_stack.borrow_mut().last() { + if let Some(mut scope) = self.error_scopes.borrow_mut().get_mut(&s_id) { + scope.op_count += 1; + scope_id = Some(*s_id); + } else { + warn!("Could not find Error Scope for id {}", s_id); + } + } + let bind_group_id = self .global() .wgpu_id_hub() @@ -381,10 +477,12 @@ impl GPUDeviceMethods for GPUDevice { bind_group_id, bind_group_layout_id: descriptor.layout.id().0, entries, + scope_id, }) .expect("Failed to create WebGPU BindGroup"); let bind_group = webgpu::WebGPUBindGroup(bind_group_id); + GPUBindGroup::new( &self.global(), bind_group, @@ -436,10 +534,21 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_compute_pipeline_id(self.device.0.backend()); + let mut scope_id = None; + if let Some(s_id) = self.scope_stack.borrow_mut().last() { + if let Some(mut scope) = self.error_scopes.borrow_mut().get_mut(&s_id) { + scope.op_count += 1; + scope_id = Some(*s_id); + } else { + warn!("Could not find Error Scope for id {}", s_id); + } + } + self.channel .0 .send(WebGPURequest::CreateComputePipeline { device_id: self.device.0, + scope_id, compute_pipeline_id, pipeline_layout_id: pipeline.0, program_id: program.0, @@ -683,11 +792,22 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_render_pipeline_id(self.device.0.backend()); + let mut scope_id = None; + if let Some(s_id) = self.scope_stack.borrow_mut().last() { + if let Some(mut scope) = self.error_scopes.borrow_mut().get_mut(&s_id) { + scope.op_count += 1; + scope_id = Some(*s_id); + } else { + warn!("Could not find Error Scope for id {}", s_id); + } + } + self.channel .0 .send(WebGPURequest::CreateRenderPipeline { device_id: self.device.0, render_pipeline_id, + scope_id, pipeline_layout_id: descriptor.parent.layout.id().0, vertex_module, vertex_entry_point, @@ -708,6 +828,49 @@ impl GPUDeviceMethods for GPUDevice { GPURenderPipeline::new(&self.global(), render_pipeline, self.device, valid) } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope + fn PushErrorScope(&self, filter: GPUErrorFilter) { + let scope_id = self.next_scope_id.get(); + self.next_scope_id.set(scope_id + 1); + let err_scope = ErrorScopeInfo { + filter, + op_count: 0, + error: None, + promise: None, + }; + let res = self.error_scopes.borrow_mut().insert(scope_id, err_scope); + self.scope_stack.borrow_mut().push(scope_id); + assert!(res.is_none()); + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope + fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> { + let promise = Promise::new_in_current_realm(&self.global(), comp); + let scope_id = if let Some(e) = self.scope_stack.borrow_mut().pop() { + e + } else { + promise.reject_error(Error::Operation); + return promise; + }; + let mut err_scope; + { + err_scope = self.error_scopes.borrow_mut().remove(&scope_id).unwrap(); + } + if let Some(ref e) = err_scope.error { + match e { + GPUError::GPUValidationError(ref v) => promise.resolve_native(&v), + GPUError::GPUOutOfMemoryError(ref w) => promise.resolve_native(&w), + } + } else if err_scope.op_count == 0 { + promise.resolve_native(&None::<GPUError>); + } + err_scope.promise = Some(promise.clone()); + if err_scope.op_count > 0 { + self.error_scopes.borrow_mut().insert(scope_id, err_scope); + } + promise + } } fn convert_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { diff --git a/components/script/dom/gpudevicelostinfo.rs b/components/script/dom/gpudevicelostinfo.rs new file mode 100644 index 00000000000..f054cbce8cd --- /dev/null +++ b/components/script/dom/gpudevicelostinfo.rs @@ -0,0 +1,38 @@ +/* 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/. */ + +#![allow(dead_code)] + +use crate::dom::bindings::codegen::Bindings::GPUDeviceLostInfoBinding::GPUDeviceLostInfoMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct GPUDeviceLostInfo { + reflector_: Reflector, + message: DOMString, +} + +impl GPUDeviceLostInfo { + fn new_inherited(message: DOMString) -> Self { + Self { + reflector_: Reflector::new(), + message, + } + } + + pub fn new(global: &GlobalScope, message: DOMString) -> DomRoot<Self> { + reflect_dom_object(Box::new(GPUDeviceLostInfo::new_inherited(message)), global) + } +} + +impl GPUDeviceLostInfoMethods for GPUDeviceLostInfo { + /// https://gpuweb.github.io/gpuweb/#dom-gpudevicelostinfo-message + fn Message(&self) -> DOMString { + self.message.clone() + } +} diff --git a/components/script/dom/gpuoutofmemoryerror.rs b/components/script/dom/gpuoutofmemoryerror.rs new file mode 100644 index 00000000000..fb0b2e11d86 --- /dev/null +++ b/components/script/dom/gpuoutofmemoryerror.rs @@ -0,0 +1,31 @@ +/* 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 crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct GPUOutOfMemoryError { + reflector_: Reflector, +} + +impl GPUOutOfMemoryError { + fn new_inherited() -> Self { + Self { + reflector_: Reflector::new(), + } + } + + pub fn new(global: &GlobalScope) -> DomRoot<Self> { + reflect_dom_object(Box::new(GPUOutOfMemoryError::new_inherited()), global) + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuoutofmemoryerror-gpuoutofmemoryerror + #[allow(non_snake_case)] + pub fn Constructor(global: &GlobalScope) -> DomRoot<Self> { + GPUOutOfMemoryError::new(global) + } +} diff --git a/components/script/dom/gpuvalidationerror.rs b/components/script/dom/gpuvalidationerror.rs new file mode 100644 index 00000000000..4b0b6ec1627 --- /dev/null +++ b/components/script/dom/gpuvalidationerror.rs @@ -0,0 +1,42 @@ +/* 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 crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::GPUValidationErrorMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct GPUValidationError { + reflector_: Reflector, + message: DOMString, +} + +impl GPUValidationError { + fn new_inherited(message: DOMString) -> Self { + Self { + reflector_: Reflector::new(), + message, + } + } + + pub fn new(global: &GlobalScope, message: DOMString) -> DomRoot<Self> { + reflect_dom_object(Box::new(GPUValidationError::new_inherited(message)), global) + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuvalidationerror-gpuvalidationerror + #[allow(non_snake_case)] + pub fn Constructor(global: &GlobalScope, message: DOMString) -> DomRoot<Self> { + GPUValidationError::new(global, message) + } +} + +impl GPUValidationErrorMethods for GPUValidationError { + /// https://gpuweb.github.io/gpuweb/#dom-gpuvalidationerror-message + fn Message(&self) -> DOMString { + self.message.clone() + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 82dc33bd7e3..3047ce2c983 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -332,7 +332,9 @@ pub mod gpucommandencoder; pub mod gpucomputepassencoder; pub mod gpucomputepipeline; pub mod gpudevice; +pub mod gpudevicelostinfo; pub mod gpumapmode; +pub mod gpuoutofmemoryerror; pub mod gpupipelinelayout; pub mod gpuqueue; pub mod gpurenderpassencoder; @@ -344,6 +346,7 @@ pub mod gpuswapchain; pub mod gputexture; pub mod gputextureusage; pub mod gputextureview; +pub mod gpuvalidationerror; pub mod hashchangeevent; pub mod headers; pub mod history; diff --git a/components/script/dom/webidls/GPUDeviceLostInfo.webidl b/components/script/dom/webidls/GPUDeviceLostInfo.webidl new file mode 100644 index 00000000000..cd9ec544408 --- /dev/null +++ b/components/script/dom/webidls/GPUDeviceLostInfo.webidl @@ -0,0 +1,13 @@ +/* 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/. */ + +// https://gpuweb.github.io/gpuweb/#gpudevicelostinfo +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPUDeviceLostInfo { + readonly attribute DOMString message; +}; + +partial interface GPUDevice { + readonly attribute Promise<GPUDeviceLostInfo> lost; +}; diff --git a/components/script/dom/webidls/GPUOutOfMemoryError.webidl b/components/script/dom/webidls/GPUOutOfMemoryError.webidl new file mode 100644 index 00000000000..470684edaab --- /dev/null +++ b/components/script/dom/webidls/GPUOutOfMemoryError.webidl @@ -0,0 +1,9 @@ +/* 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/. */ + +// https://gpuweb.github.io/gpuweb/#gpuoutofmemoryerror +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPUOutOfMemoryError { + constructor(); +}; diff --git a/components/script/dom/webidls/GPUValidationError.webidl b/components/script/dom/webidls/GPUValidationError.webidl new file mode 100644 index 00000000000..8e5d211d981 --- /dev/null +++ b/components/script/dom/webidls/GPUValidationError.webidl @@ -0,0 +1,22 @@ +/* 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/. */ + +// https://gpuweb.github.io/gpuweb/#gpuvalidationerror +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPUValidationError { + constructor(DOMString message); + readonly attribute DOMString message; +}; + +typedef (GPUOutOfMemoryError or GPUValidationError) GPUError; + +enum GPUErrorFilter { + "out-of-memory", + "validation" +}; + +partial interface GPUDevice { + void pushErrorScope(GPUErrorFilter filter); + Promise<GPUError?> popErrorScope(); +}; |