diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/codegen/Bindings.conf | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 2 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 38 | ||||
-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 | 179 | ||||
-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/htmlscriptelement.rs | 18 | ||||
-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 | ||||
-rw-r--r-- | components/script/dom/xmlhttprequest.rs | 6 | ||||
-rw-r--r-- | components/script/script_module.rs | 6 | ||||
-rw-r--r-- | components/script/script_thread.rs | 16 |
17 files changed, 432 insertions, 35 deletions
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf index 9cca9647e94..6c6e0ed6618 100644 --- a/components/script/dom/bindings/codegen/Bindings.conf +++ b/components/script/dom/bindings/codegen/Bindings.conf @@ -158,6 +158,10 @@ DOMInterfaces = { 'GPUBuffer': { 'inRealms': ['MapAsync'], +}, + +'GPUDevice': { + 'inRealms': ['PopErrorScope', 'Lost'], } } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 8dbb7ff08ba..92d6ebcb7bf 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -167,6 +167,7 @@ use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{ wgpu::command::{ComputePass, RenderPass}, + wgt::BindGroupLayoutEntry, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice, WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule, @@ -604,6 +605,7 @@ unsafe_no_jsmanaged_fields!(WebGPUContextId); unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer); unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder); unsafe_no_jsmanaged_fields!(WebGPUDevice); +unsafe_no_jsmanaged_fields!(BindGroupLayoutEntry); unsafe_no_jsmanaged_fields!(Option<RenderPass>); unsafe_no_jsmanaged_fields!(Option<ComputePass>); unsafe_no_jsmanaged_fields!(GPUBufferState); diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index d20f9084fcc..a6427224882 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -5,6 +5,7 @@ use crate::dom::bindings::cell::{DomRefCell, RefMut}; 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; @@ -126,6 +130,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 { @@ -293,6 +298,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>>>, @@ -752,6 +760,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()), @@ -2995,6 +3004,35 @@ 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 remove_gpu_device(&self, device: WebGPUDevice) { + let _ = self.gpu_devices.borrow_mut().remove(&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..d438e6c23e0 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,38 @@ 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::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; use webgpu::wgpu::binding_model::BufferBinding; use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest}; +type ErrorScopeId = u64; + +#[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>>, +} + +#[derive(JSTraceable, MallocSizeOf)] +struct ScopeContext { + error_scopes: HashMap<ErrorScopeId, ErrorScopeInfo>, + scope_stack: Vec<ErrorScopeId>, + next_scope_id: ErrorScopeId, +} + #[dom_struct] pub struct GPUDevice { eventtarget: EventTarget, @@ -73,6 +99,12 @@ pub struct GPUDevice { label: DomRefCell<Option<DOMString>>, device: webgpu::WebGPUDevice, default_queue: Dom<GPUQueue>, + scope_context: DomRefCell<ScopeContext>, + #[ignore_malloc_size_of = "promises are hard"] + lost_promise: DomRefCell<Option<Rc<Promise>>>, + #[ignore_malloc_size_of = "defined in webgpu"] + bind_group_layouts: + DomRefCell<HashMap<Vec<wgt::BindGroupLayoutEntry>, Dom<GPUBindGroupLayout>>>, } impl GPUDevice { @@ -93,6 +125,13 @@ impl GPUDevice { label: DomRefCell::new(None), device, default_queue: Dom::from_ref(queue), + scope_context: DomRefCell::new(ScopeContext { + error_scopes: HashMap::new(), + scope_stack: Vec::new(), + next_scope_id: 0, + }), + lost_promise: DomRefCell::new(None), + bind_group_layouts: DomRefCell::new(HashMap::new()), } } @@ -119,6 +158,51 @@ impl GPUDevice { pub fn id(&self) -> webgpu::WebGPUDevice { self.device } + + pub fn handle_server_msg(&self, scope: ErrorScopeId, result: Result<(), GPUError>) { + let mut context = self.scope_context.borrow_mut(); + let remove = if let Some(mut err_scope) = context.error_scopes.get_mut(&scope) { + 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>); + } + } + } + err_scope.op_count == 0 && err_scope.promise.is_some() + } else { + warn!("Could not find ErrroScope with Id({})", scope); + false + }; + if remove { + let _ = context.error_scopes.remove(&scope); + } + } + + fn use_current_scope(&self) -> Option<ErrorScopeId> { + let mut context = self.scope_context.borrow_mut(); + let scope_id = context.scope_stack.last().cloned(); + scope_id.and_then(|s_id| { + context.error_scopes.get_mut(&s_id).map(|mut scope| { + scope.op_count += 1; + s_id + }) + }) + } } impl GPUDeviceMethods for GPUDevice { @@ -152,6 +236,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 +380,23 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(); + let scope_id = self.use_current_scope(); + + // Check for equivalent GPUBindGroupLayout + { + let layout = self + .bind_group_layouts + .borrow() + .get(&entries) + .map(|bgl| DomRoot::from_ref(&**bgl)); + if let Some(l) = layout { + if let Some(i) = scope_id { + self.handle_server_msg(i, Ok(())); + } + return l; + } + } + let bind_group_layout_id = self .global() .wgpu_id_hub() @@ -299,13 +407,20 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroupLayout { device_id: self.device.0, bind_group_layout_id, - entries, + entries: entries.clone(), + scope_id, }) .expect("Failed to create WebGPU BindGroupLayout"); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); - GPUBindGroupLayout::new(&self.global(), bgl, true) + let layout = GPUBindGroupLayout::new(&self.global(), bgl, true); + + self.bind_group_layouts + .borrow_mut() + .insert(entries, Dom::from_ref(&*layout)); + + layout } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout @@ -320,6 +435,8 @@ impl GPUDeviceMethods for GPUDevice { } }); + let scope_id = self.use_current_scope(); + let pipeline_layout_id = self .global() .wgpu_id_hub() @@ -331,6 +448,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 +487,8 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::<Vec<_>>(); + let scope_id = self.use_current_scope(); + let bind_group_id = self .global() .wgpu_id_hub() @@ -381,10 +501,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 +558,13 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_compute_pipeline_id(self.device.0.backend()); + let scope_id = self.use_current_scope(); + 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 +808,14 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_render_pipeline_id(self.device.0.backend()); + let scope_id = self.use_current_scope(); + 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 +836,53 @@ 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 mut context = self.scope_context.borrow_mut(); + let scope_id = context.next_scope_id; + context.next_scope_id += 1; + let err_scope = ErrorScopeInfo { + filter, + op_count: 0, + error: None, + promise: None, + }; + let res = context.error_scopes.insert(scope_id, err_scope); + context.scope_stack.push(scope_id); + assert!(res.is_none()); + } + + /// 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(&self.global(), comp); + let scope_id = if let Some(e) = context.scope_stack.pop() { + e + } 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 { + 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()); + 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); + } + 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/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 6a2b5e53acc..2ad7444f7f4 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -425,9 +425,9 @@ impl HTMLScriptElement { // Step 4. let element = self.upcast::<Element>(); - let r#async = element.has_attribute(&local_name!("async")); + let asynch = element.has_attribute(&local_name!("async")); // Note: confusingly, this is done if the element does *not* have an "async" attribute. - if was_parser_inserted && !r#async { + if was_parser_inserted && !asynch { self.non_blocking.set(true); } @@ -592,14 +592,14 @@ impl HTMLScriptElement { // Preparation for step 26. let kind = if element.has_attribute(&local_name!("defer")) && was_parser_inserted && - !r#async + !asynch { // Step 26.a: classic, has src, has defer, was parser-inserted, is not async. ExternalScriptKind::Deferred - } else if was_parser_inserted && !r#async { + } else if was_parser_inserted && !asynch { // Step 26.c: classic, has src, was parser-inserted, is not async. ExternalScriptKind::ParsingBlocking - } else if !r#async && !self.non_blocking.get() { + } else if !asynch && !self.non_blocking.get() { // Step 26.d: classic, has src, is not async, is not non-blocking. ExternalScriptKind::AsapInOrder } else { @@ -628,9 +628,9 @@ impl HTMLScriptElement { options, ); - if !r#async && was_parser_inserted { + if !asynch && was_parser_inserted { doc.add_deferred_script(self); - } else if !r#async && !self.non_blocking.get() { + } else if !asynch && !self.non_blocking.get() { doc.push_asap_in_order_script(self); } else { doc.add_asap_script(self); @@ -670,9 +670,9 @@ impl HTMLScriptElement { // We should add inline module script elements // into those vectors in case that there's no // descendants in the inline module script. - if !r#async && was_parser_inserted { + if !asynch && was_parser_inserted { doc.add_deferred_script(self); - } else if !r#async && !self.non_blocking.get() { + } else if !asynch && !self.non_blocking.get() { doc.push_asap_in_order_script(self); } else { doc.add_asap_script(self); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 2125608d809..698cff979c9 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -333,7 +333,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; @@ -345,6 +347,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(); +}; diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 842bf5f9441..4d4ec43fa38 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -340,7 +340,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { &self, method: ByteString, url: USVString, - r#async: bool, + asynch: bool, username: Option<USVString>, password: Option<USVString>, ) -> ErrorResult { @@ -396,7 +396,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { } // Step 10 - if !r#async { + if !asynch { // FIXME: This should only happen if the global environment is a document environment if self.timeout.get() != 0 || self.response_type.get() != XMLHttpRequestResponseType::_empty @@ -416,7 +416,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // Step 12 *self.request_method.borrow_mut() = parsed_method; *self.request_url.borrow_mut() = Some(parsed_url); - self.sync.set(!r#async); + self.sync.set(!asynch); *self.request_headers.borrow_mut() = HeaderMap::new(); self.send_flag.set(false); *self.status_text.borrow_mut() = ByteString::new(vec![]); diff --git a/components/script/script_module.rs b/components/script/script_module.rs index 4b7b7192654..55b4c0d3562 100644 --- a/components/script/script_module.rs +++ b/components/script/script_module.rs @@ -939,14 +939,14 @@ impl ModuleOwner { } }; - let r#async = script + let asynch = script .root() .upcast::<Element>() .has_attribute(&local_name!("async")); - if !r#async && (&*script.root()).get_parser_inserted() { + if !asynch && (&*script.root()).get_parser_inserted() { document.deferred_script_loaded(&*script.root(), load); - } else if !r#async && !(&*script.root()).get_non_blocking() { + } else if !asynch && !(&*script.root()).get_non_blocking() { document.asap_in_order_script_loaded(&*script.root(), load); } else { document.asap_script_loaded(&*script.root(), load); diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index d2ddaebd747..b5ea3f619a6 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -2061,6 +2061,22 @@ 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, + pipeline_id, + result, + } => { + let global = self.documents.borrow().find_global(pipeline_id).unwrap(); + global.handle_wgpu_msg(device, scope_id, result); + }, + WebGPUMsg::CleanDevice { + pipeline_id, + device, + } => { + let global = self.documents.borrow().find_global(pipeline_id).unwrap(); + global.remove_gpu_device(device); + }, _ => {}, } } |