diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 168e1e74924..6da1028af40 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -157,7 +157,7 @@ use style_traits::CSSPixel; #[cfg(feature = "webgpu")] use webgpu::swapchain::WGPUImageMap; #[cfg(feature = "webgpu")] -use webgpu::{self, WebGPU, WebGPURequest, WebGPUResponse}; +use webgpu::{self, WebGPU, WebGPURequest}; #[cfg(feature = "webgpu")] use webrender::RenderApi; use webrender::RenderApiSender; @@ -1936,7 +1936,7 @@ where FromScriptMsg::RequestAdapter(response_sender, options, adapter_id) => { match webgpu_chan { None => { - if let Err(e) = response_sender.send(WebGPUResponse::None) { + if let Err(e) = response_sender.send(None) { warn!("Failed to send request adapter message: {}", e) } }, diff --git a/components/script/dom/servointernals.rs b/components/script/dom/servointernals.rs index 7fe0bf85122..295bd838443 100644 --- a/components/script/dom/servointernals.rs +++ b/components/script/dom/servointernals.rs @@ -52,11 +52,8 @@ impl ServoInternalsMethods for ServoInternals { } } -impl RoutedPromiseListener for ServoInternals { - type Response = MemoryReportResult; - - #[cfg_attr(crown, allow(crown::unrooted_must_root))] - fn handle_response(&self, response: Self::Response, promise: &Rc, can_gc: CanGc) { +impl RoutedPromiseListener for ServoInternals { + fn handle_response(&self, response: MemoryReportResult, promise: &Rc, can_gc: CanGc) { promise.resolve_native(&response.content, can_gc); } } diff --git a/components/script/dom/webgpu/gpu.rs b/components/script/dom/webgpu/gpu.rs index 163c4599d4a..ce5f3d1f5fd 100644 --- a/components/script/dom/webgpu/gpu.rs +++ b/components/script/dom/webgpu/gpu.rs @@ -5,26 +5,24 @@ use std::rc::Rc; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; -use ipc_channel::router::ROUTER; use js::jsapi::Heap; use script_traits::ScriptMsg; use webgpu::wgt::PowerPreference; -use webgpu::{WebGPUResponse, wgc}; +use webgpu::{WebGPUAdapterResponse, wgc}; use super::wgsllanguagefeatures::WGSLLanguageFeatures; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ GPUMethods, GPUPowerPreference, GPURequestAdapterOptions, GPUTextureFormat, }; use crate::dom::bindings::error::Error; -use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; -use crate::dom::bindings::reflector::{DomGlobal, DomObject, Reflector, reflect_dom_object}; +use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::dom::webgpu::gpuadapter::GPUAdapter; use crate::realms::InRealm; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::CanGc; #[dom_struct] @@ -48,59 +46,6 @@ impl GPU { } } -pub(crate) trait AsyncWGPUListener { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc); -} - -struct WGPUResponse { - trusted: TrustedPromise, - receiver: Trusted, -} - -impl WGPUResponse { - #[cfg_attr(crown, allow(crown::unrooted_must_root))] - fn response(self, response: WebGPUResponse, can_gc: CanGc) { - let promise = self.trusted.root(); - self.receiver - .root() - .handle_response(response, &promise, can_gc); - } -} - -pub(crate) fn response_async( - promise: &Rc, - receiver: &T, -) -> IpcSender { - let (action_sender, action_receiver) = ipc::channel().unwrap(); - let task_source = receiver - .global() - .task_manager() - .dom_manipulation_task_source() - .to_sendable(); - let mut trusted: Option = Some(TrustedPromise::new(promise.clone())); - let trusted_receiver = Trusted::new(receiver); - ROUTER.add_typed_route( - action_receiver, - Box::new(move |message| { - let trusted = if let Some(trusted) = trusted.take() { - trusted - } else { - error!("WebGPU callback called twice!"); - return; - }; - - let context = WGPUResponse { - trusted, - receiver: trusted_receiver.clone(), - }; - task_source.queue(task!(process_webgpu_task: move|| { - context.response(message.unwrap(), CanGc::note()); - })); - }), - ); - action_sender -} - impl GPUMethods for GPU { // https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter fn RequestAdapter( @@ -111,7 +56,7 @@ impl GPUMethods for GPU { ) -> Rc { let global = &self.global(); let promise = Promise::new_in_current_realm(comp, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); let power_preference = match options.powerPreference { Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower, Some(GPUPowerPreference::High_performance) => PowerPreference::HighPerformance, @@ -150,10 +95,15 @@ impl GPUMethods for GPU { } } -impl AsyncWGPUListener for GPU { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc) { +impl RoutedPromiseListener for GPU { + fn handle_response( + &self, + response: WebGPUAdapterResponse, + promise: &Rc, + can_gc: CanGc, + ) { match response { - WebGPUResponse::Adapter(Ok(adapter)) => { + Some(Ok(adapter)) => { let adapter = GPUAdapter::new( &self.global(), adapter.channel, @@ -170,15 +120,14 @@ impl AsyncWGPUListener for GPU { ); promise.resolve_native(&adapter, can_gc); }, - WebGPUResponse::Adapter(Err(e)) => { + Some(Err(e)) => { warn!("Could not get GPUAdapter ({:?})", e); promise.resolve_native(&None::, can_gc); }, - WebGPUResponse::None => { + None => { warn!("Couldn't get a response, because WebGPU is disabled"); promise.resolve_native(&None::, can_gc); }, - _ => unreachable!("GPU received wrong WebGPUResponse"), } } } diff --git a/components/script/dom/webgpu/gpuadapter.rs b/components/script/dom/webgpu/gpuadapter.rs index a8b50516234..04a7b9e42ad 100644 --- a/components/script/dom/webgpu/gpuadapter.rs +++ b/components/script/dom/webgpu/gpuadapter.rs @@ -8,7 +8,7 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use webgpu::wgc::instance::RequestDeviceError; use webgpu::wgt::MemoryHints; -use webgpu::{WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, wgt}; +use webgpu::{WebGPU, WebGPUAdapter, WebGPUDeviceResponse, WebGPURequest, wgt}; use super::gpusupportedfeatures::GPUSupportedFeatures; use super::gpusupportedlimits::set_limit; @@ -22,10 +22,10 @@ use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::dom::types::{GPUAdapterInfo, GPUSupportedLimits}; -use crate::dom::webgpu::gpu::{AsyncWGPUListener, response_async}; use crate::dom::webgpu::gpudevice::GPUDevice; use crate::dom::webgpu::gpusupportedfeatures::gpu_to_wgt_feature; use crate::realms::InRealm; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::CanGc; #[dom_struct] @@ -116,7 +116,7 @@ impl GPUAdapterMethods for GPUAdapter { ) -> Rc { // Step 2 let promise = Promise::new_in_current_realm(comp, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); let mut required_features = wgt::Features::empty(); for &ext in descriptor.requiredFeatures.iter() { if let Some(feature) = gpu_to_wgt_feature(ext) { @@ -205,10 +205,15 @@ impl GPUAdapterMethods for GPUAdapter { } } -impl AsyncWGPUListener for GPUAdapter { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc) { +impl RoutedPromiseListener for GPUAdapter { + fn handle_response( + &self, + response: WebGPUDeviceResponse, + promise: &Rc, + can_gc: CanGc, + ) { match response { - WebGPUResponse::Device((device_id, queue_id, Ok(descriptor))) => { + (device_id, queue_id, Ok(descriptor)) => { let device = GPUDevice::new( &self.global(), self.channel.clone(), @@ -224,16 +229,14 @@ impl AsyncWGPUListener for GPUAdapter { self.global().add_gpu_device(&device); promise.resolve_native(&device, can_gc); }, - WebGPUResponse::Device((_, _, Err(RequestDeviceError::UnsupportedFeature(f)))) => { - promise.reject_error( - Error::Type(RequestDeviceError::UnsupportedFeature(f).to_string()), - can_gc, - ) - }, - WebGPUResponse::Device((_, _, Err(RequestDeviceError::LimitsExceeded(_)))) => { + (_, _, Err(RequestDeviceError::UnsupportedFeature(f))) => promise.reject_error( + Error::Type(RequestDeviceError::UnsupportedFeature(f).to_string()), + can_gc, + ), + (_, _, Err(RequestDeviceError::LimitsExceeded(_))) => { promise.reject_error(Error::Operation, can_gc) }, - WebGPUResponse::Device((device_id, queue_id, Err(e))) => { + (device_id, queue_id, Err(e)) => { let device = GPUDevice::new( &self.global(), self.channel.clone(), @@ -249,8 +252,6 @@ impl AsyncWGPUListener for GPUAdapter { device.lose(GPUDeviceLostReason::Unknown, e.to_string(), can_gc); promise.resolve_native(&device, can_gc); }, - WebGPUResponse::None => unreachable!("Failed to get a response for RequestDevice"), - _ => unreachable!("GPUAdapter received wrong WebGPUResponse"), } } } diff --git a/components/script/dom/webgpu/gpubuffer.rs b/components/script/dom/webgpu/gpubuffer.rs index b28b3d8c184..b6c5d6c4977 100644 --- a/components/script/dom/webgpu/gpubuffer.rs +++ b/components/script/dom/webgpu/gpubuffer.rs @@ -10,7 +10,8 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; use js::typedarray::ArrayBuffer; use webgpu::wgc::device::HostMap; -use webgpu::{Mapping, WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse, wgt}; +use webgpu::{Mapping, WebGPU, WebGPUBuffer, WebGPURequest, wgc, wgt}; +use wgc::resource::BufferAccessError; use crate::conversions::Convert; use crate::dom::bindings::buffer_source::DataBlock; @@ -25,9 +26,9 @@ use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; -use crate::dom::webgpu::gpu::{AsyncWGPUListener, response_async}; use crate::dom::webgpu::gpudevice::GPUDevice; use crate::realms::InRealm; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::{CanGc, JSContext}; #[derive(JSTraceable, MallocSizeOf)] @@ -270,7 +271,7 @@ impl GPUBufferMethods for GPUBuffer { }, }; - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { sender, buffer_id: self.buffer.0, @@ -419,15 +420,16 @@ impl GPUBuffer { } } -impl AsyncWGPUListener for GPUBuffer { - #[allow(unsafe_code)] - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc) { +impl RoutedPromiseListener> for GPUBuffer { + fn handle_response( + &self, + response: Result, + promise: &Rc, + can_gc: CanGc, + ) { match response { - WebGPUResponse::BufferMapAsync(Ok(mapping)) => { - self.map_success(promise, mapping, can_gc) - }, - WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise, can_gc), - _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"), + Ok(mapping) => self.map_success(promise, mapping, can_gc), + Err(_) => self.map_failure(promise, can_gc), } } } diff --git a/components/script/dom/webgpu/gpucomputepipeline.rs b/components/script/dom/webgpu/gpucomputepipeline.rs index 418cf5f8fdd..fb6ac7b01e7 100644 --- a/components/script/dom/webgpu/gpucomputepipeline.rs +++ b/components/script/dom/webgpu/gpucomputepipeline.rs @@ -5,7 +5,10 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; use webgpu::wgc::pipeline::ComputePipelineDescriptor; -use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPURequest, WebGPUResponse}; +use webgpu::{ + WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPUComputePipelineResponse, + WebGPURequest, +}; use crate::conversions::Convert; use crate::dom::bindings::cell::DomRefCell; @@ -76,7 +79,7 @@ impl GPUComputePipeline { pub(crate) fn create( device: &GPUDevice, descriptor: &GPUComputePipelineDescriptor, - async_sender: Option>, + async_sender: Option>, ) -> WebGPUComputePipeline { let compute_pipeline_id = device.global().wgpu_id_hub().create_compute_pipeline_id(); diff --git a/components/script/dom/webgpu/gpudevice.rs b/components/script/dom/webgpu/gpudevice.rs index c5f4638479d..f0e82ff9020 100644 --- a/components/script/dom/webgpu/gpudevice.rs +++ b/components/script/dom/webgpu/gpudevice.rs @@ -15,11 +15,11 @@ use webgpu::wgc::pipeline as wgpu_pipe; use webgpu::wgc::pipeline::RenderPipelineDescriptor; use webgpu::wgt::TextureFormat; use webgpu::{ - PopError, WebGPU, WebGPUComputePipeline, WebGPURenderPipeline, WebGPURequest, WebGPUResponse, - wgt, + PopError, WebGPU, WebGPUComputePipeline, WebGPUComputePipelineResponse, + WebGPUPoppedErrorScopeResponse, WebGPURenderPipeline, WebGPURenderPipelineResponse, + WebGPURequest, wgt, }; -use super::gpu::AsyncWGPUListener; use super::gpudevicelostinfo::GPUDeviceLostInfo; use super::gpuerror::AsWebGpu; use super::gpupipelineerror::GPUPipelineError; @@ -46,7 +46,6 @@ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::dom::types::GPUError; -use crate::dom::webgpu::gpu::response_async; use crate::dom::webgpu::gpuadapter::GPUAdapter; use crate::dom::webgpu::gpubindgroup::GPUBindGroup; use crate::dom::webgpu::gpubindgrouplayout::GPUBindGroupLayout; @@ -63,6 +62,7 @@ use crate::dom::webgpu::gpusupportedfeatures::GPUSupportedFeatures; use crate::dom::webgpu::gputexture::GPUTexture; use crate::dom::webgpu::gpuuncapturederrorevent::GPUUncapturedErrorEvent; use crate::realms::InRealm; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::CanGc; #[dom_struct] @@ -469,7 +469,7 @@ impl GPUDeviceMethods for GPUDevice { can_gc: CanGc, ) -> Rc { let promise = Promise::new_in_current_realm(comp, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); GPUComputePipeline::create(self, descriptor, Some(sender)); promise } @@ -517,7 +517,7 @@ impl GPUDeviceMethods for GPUDevice { ) -> Fallible> { let (implicit_ids, desc) = self.parse_render_pipeline(descriptor)?; let promise = Promise::new_in_current_realm(comp, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); GPURenderPipeline::create(self, implicit_ids, desc, Some(sender))?; Ok(promise) } @@ -548,7 +548,7 @@ impl GPUDeviceMethods for GPUDevice { /// fn PopErrorScope(&self, comp: InRealm, can_gc: CanGc) -> Rc { let promise = Promise::new_in_current_realm(comp, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); if self .channel .0 @@ -582,82 +582,104 @@ impl GPUDeviceMethods for GPUDevice { } } -impl AsyncWGPUListener for GPUDevice { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc) { +impl RoutedPromiseListener for GPUDevice { + fn handle_response( + &self, + response: WebGPUPoppedErrorScopeResponse, + promise: &Rc, + can_gc: CanGc, + ) { match response { - WebGPUResponse::PoppedErrorScope(result) => match result { - Ok(None) | Err(PopError::Lost) => { - promise.resolve_native(&None::>, can_gc) - }, - Err(PopError::Empty) => promise.reject_error(Error::Operation, can_gc), - Ok(Some(error)) => { - let error = GPUError::from_error(&self.global(), error, can_gc); - promise.resolve_native(&error, can_gc); - }, + Ok(None) | Err(PopError::Lost) => { + promise.resolve_native(&None::>, can_gc) }, - WebGPUResponse::ComputePipeline(result) => match result { - Ok(pipeline) => promise.resolve_native( - &GPUComputePipeline::new( - &self.global(), - WebGPUComputePipeline(pipeline.id), - pipeline.label.into(), - self, - can_gc, - ), + Err(PopError::Empty) => promise.reject_error(Error::Operation, can_gc), + Ok(Some(error)) => { + let error = GPUError::from_error(&self.global(), error, can_gc); + promise.resolve_native(&error, can_gc); + }, + } + } +} + +impl RoutedPromiseListener for GPUDevice { + fn handle_response( + &self, + response: WebGPUComputePipelineResponse, + promise: &Rc, + can_gc: CanGc, + ) { + match response { + Ok(pipeline) => promise.resolve_native( + &GPUComputePipeline::new( + &self.global(), + WebGPUComputePipeline(pipeline.id), + pipeline.label.into(), + self, can_gc, ), - Err(webgpu::Error::Validation(msg)) => promise.reject_native( + can_gc, + ), + Err(webgpu::Error::Validation(msg)) => promise.reject_native( + &GPUPipelineError::new( + &self.global(), + msg.into(), + GPUPipelineErrorReason::Validation, + can_gc, + ), + can_gc, + ), + Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise + .reject_native( &GPUPipelineError::new( &self.global(), msg.into(), - GPUPipelineErrorReason::Validation, + GPUPipelineErrorReason::Internal, can_gc, ), can_gc, ), - Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise - .reject_native( - &GPUPipelineError::new( - &self.global(), - msg.into(), - GPUPipelineErrorReason::Internal, - can_gc, - ), - can_gc, - ), - }, - WebGPUResponse::RenderPipeline(result) => match result { - Ok(pipeline) => promise.resolve_native( - &GPURenderPipeline::new( - &self.global(), - WebGPURenderPipeline(pipeline.id), - pipeline.label.into(), - self, - can_gc, - ), + } + } +} + +impl RoutedPromiseListener for GPUDevice { + fn handle_response( + &self, + response: WebGPURenderPipelineResponse, + promise: &Rc, + can_gc: CanGc, + ) { + match response { + Ok(pipeline) => promise.resolve_native( + &GPURenderPipeline::new( + &self.global(), + WebGPURenderPipeline(pipeline.id), + pipeline.label.into(), + self, can_gc, ), - Err(webgpu::Error::Validation(msg)) => promise.reject_native( + can_gc, + ), + Err(webgpu::Error::Validation(msg)) => promise.reject_native( + &GPUPipelineError::new( + &self.global(), + msg.into(), + GPUPipelineErrorReason::Validation, + can_gc, + ), + can_gc, + ), + Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise + .reject_native( &GPUPipelineError::new( &self.global(), msg.into(), - GPUPipelineErrorReason::Validation, + GPUPipelineErrorReason::Internal, can_gc, ), can_gc, ), - Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise - .reject_native( - &GPUPipelineError::new( - &self.global(), - msg.into(), - GPUPipelineErrorReason::Internal, - can_gc, - ), - can_gc, - ), - }, - _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUDevice"), } } } diff --git a/components/script/dom/webgpu/gpuqueue.rs b/components/script/dom/webgpu/gpuqueue.rs index 1cf3589eadc..14a446604b2 100644 --- a/components/script/dom/webgpu/gpuqueue.rs +++ b/components/script/dom/webgpu/gpuqueue.rs @@ -6,9 +6,8 @@ use std::rc::Rc; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; -use webgpu::{WebGPU, WebGPUQueue, WebGPURequest, WebGPUResponse, wgt}; +use webgpu::{WebGPU, WebGPUQueue, WebGPURequest, wgt}; -use super::gpu::{AsyncWGPUListener, response_async}; use crate::conversions::{Convert, TryConvert}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ @@ -24,6 +23,7 @@ use crate::dom::promise::Promise; use crate::dom::webgpu::gpubuffer::GPUBuffer; use crate::dom::webgpu::gpucommandbuffer::GPUCommandBuffer; use crate::dom::webgpu::gpudevice::GPUDevice; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::CanGc; #[dom_struct] @@ -200,7 +200,7 @@ impl GPUQueueMethods for GPUQueue { fn OnSubmittedWorkDone(&self, can_gc: CanGc) -> Rc { let global = self.global(); let promise = Promise::new(&global, can_gc); - let sender = response_async(&promise, self); + let sender = route_promise(&promise, self); if let Err(e) = self .channel .0 @@ -215,21 +215,8 @@ impl GPUQueueMethods for GPUQueue { } } -impl AsyncWGPUListener for GPUQueue { - fn handle_response( - &self, - response: webgpu::WebGPUResponse, - promise: &Rc, - can_gc: CanGc, - ) { - match response { - WebGPUResponse::SubmittedWorkDone => { - promise.resolve_native(&(), can_gc); - }, - _ => { - warn!("GPUQueue received wrong WebGPUResponse"); - promise.reject_error(Error::Operation, can_gc); - }, - } +impl RoutedPromiseListener<()> for GPUQueue { + fn handle_response(&self, _response: (), promise: &Rc, can_gc: CanGc) { + promise.resolve_native(&(), can_gc); } } diff --git a/components/script/dom/webgpu/gpurenderpipeline.rs b/components/script/dom/webgpu/gpurenderpipeline.rs index b4321475913..4ac7acd2bce 100644 --- a/components/script/dom/webgpu/gpurenderpipeline.rs +++ b/components/script/dom/webgpu/gpurenderpipeline.rs @@ -5,7 +5,10 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; use webgpu::wgc::pipeline::RenderPipelineDescriptor; -use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPURenderPipeline, WebGPURequest, WebGPUResponse}; +use webgpu::{ + WebGPU, WebGPUBindGroupLayout, WebGPURenderPipeline, WebGPURenderPipelineResponse, + WebGPURequest, +}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPURenderPipelineMethods; @@ -74,7 +77,7 @@ impl GPURenderPipeline { device: &GPUDevice, pipeline_layout: PipelineLayout, descriptor: RenderPipelineDescriptor<'static>, - async_sender: Option>, + async_sender: Option>, ) -> Fallible { let render_pipeline_id = device.global().wgpu_id_hub().create_render_pipeline_id(); diff --git a/components/script/dom/webgpu/gpushadermodule.rs b/components/script/dom/webgpu/gpushadermodule.rs index 62dd456a054..a970e6dbf10 100644 --- a/components/script/dom/webgpu/gpushadermodule.rs +++ b/components/script/dom/webgpu/gpushadermodule.rs @@ -5,9 +5,8 @@ use std::rc::Rc; use dom_struct::dom_struct; -use webgpu::{WebGPU, WebGPURequest, WebGPUResponse, WebGPUShaderModule}; +use webgpu::{ShaderCompilationInfo, WebGPU, WebGPURequest, WebGPUShaderModule}; -use super::gpu::AsyncWGPUListener; use super::gpucompilationinfo::GPUCompilationInfo; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ @@ -20,8 +19,8 @@ use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::dom::types::GPUDevice; -use crate::dom::webgpu::gpu::response_async; use crate::realms::InRealm; +use crate::routed_promise::{RoutedPromiseListener, route_promise}; use crate::script_runtime::CanGc; #[dom_struct] @@ -96,7 +95,7 @@ impl GPUShaderModule { promise.clone(), can_gc, ); - let sender = response_async(&promise, &*shader_module); + let sender = route_promise(&promise, &*shader_module); device .channel() .0 @@ -129,15 +128,15 @@ impl GPUShaderModuleMethods for GPUShaderModule { } } -impl AsyncWGPUListener for GPUShaderModule { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc, can_gc: CanGc) { - match response { - WebGPUResponse::CompilationInfo(info) => { - let info = GPUCompilationInfo::from(&self.global(), info, can_gc); - promise.resolve_native(&info, can_gc); - }, - _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUShaderModule"), - } +impl RoutedPromiseListener> for GPUShaderModule { + fn handle_response( + &self, + response: Option, + promise: &Rc, + can_gc: CanGc, + ) { + let info = GPUCompilationInfo::from(&self.global(), response, can_gc); + promise.resolve_native(&info, can_gc); } } diff --git a/components/script/routed_promise.rs b/components/script/routed_promise.rs index 5a68287f450..67e5edd7370 100644 --- a/components/script/routed_promise.rs +++ b/components/script/routed_promise.rs @@ -14,20 +14,23 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject}; use crate::dom::promise::Promise; use crate::script_runtime::CanGc; -pub(crate) trait RoutedPromiseListener { - type Response: Serialize + DeserializeOwned + Send; - - fn handle_response(&self, response: Self::Response, promise: &Rc, can_gc: CanGc); +pub(crate) trait RoutedPromiseListener { + fn handle_response(&self, response: R, promise: &Rc, can_gc: CanGc); } -pub(crate) struct RoutedPromiseContext { +pub(crate) struct RoutedPromiseContext< + R: Serialize + DeserializeOwned + Send, + T: RoutedPromiseListener + DomObject, +> { trusted: TrustedPromise, receiver: Trusted, + _phantom: std::marker::PhantomData, } -impl RoutedPromiseContext { - #[cfg_attr(crown, allow(crown::unrooted_must_root))] - fn response(self, response: T::Response, can_gc: CanGc) { +impl + DomObject> + RoutedPromiseContext +{ + fn response(self, response: R, can_gc: CanGc) { let promise = self.trusted.root(); self.receiver .root() @@ -35,10 +38,13 @@ impl RoutedPromiseContext { } } -pub(crate) fn route_promise( +pub(crate) fn route_promise< + R: Serialize + DeserializeOwned + Send + 'static, + T: RoutedPromiseListener + DomObject + 'static, +>( promise: &Rc, receiver: &T, -) -> IpcSender { +) -> IpcSender { let (action_sender, action_receiver) = ipc::channel().unwrap(); let task_source = receiver .global() @@ -60,6 +66,7 @@ pub(crate) fn route_promise( let context = RoutedPromiseContext { trusted, receiver: trusted_receiver.clone(), + _phantom: Default::default(), }; task_source.queue(task!(routed_promise_task: move|| { context.response(message.unwrap(), CanGc::note()); diff --git a/components/shared/script/script_msg.rs b/components/shared/script/script_msg.rs index f67a7d0ac07..33ebb496dc7 100644 --- a/components/shared/script/script_msg.rs +++ b/components/shared/script/script_msg.rs @@ -24,7 +24,7 @@ use servo_url::{ImmutableOrigin, ServoUrl}; use strum_macros::IntoStaticStr; use style_traits::CSSPixel; #[cfg(feature = "webgpu")] -use webgpu::{WebGPU, WebGPUResponse, wgc}; +use webgpu::{WebGPU, WebGPUAdapterResponse, wgc}; use webrender_api::ImageKey; use crate::mem::MemoryReportResult; @@ -204,7 +204,7 @@ pub enum ScriptMsg { #[cfg(feature = "webgpu")] /// Create a WebGPU Adapter instance RequestAdapter( - IpcSender, + IpcSender, wgc::instance::RequestAdapterOptions, wgc::id::AdapterId, ), diff --git a/components/webgpu/ipc_messages/recv.rs b/components/webgpu/ipc_messages/recv.rs index 62399d87e21..ce69080760e 100644 --- a/components/webgpu/ipc_messages/recv.rs +++ b/components/webgpu/ipc_messages/recv.rs @@ -32,7 +32,12 @@ pub use {wgpu_core as wgc, wgpu_types as wgt}; use crate::identity::*; use crate::render_commands::RenderCommand; use crate::swapchain::WebGPUContextId; -use crate::{Error, ErrorFilter, Mapping, PRESENTATION_BUFFER_COUNT, WebGPUResponse}; +use crate::wgc::resource::BufferAccessError; +use crate::{ + Error, ErrorFilter, Mapping, PRESENTATION_BUFFER_COUNT, ShaderCompilationInfo, + WebGPUAdapterResponse, WebGPUComputePipelineResponse, WebGPUDeviceResponse, + WebGPUPoppedErrorScopeResponse, WebGPURenderPipelineResponse, +}; #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub struct ContextConfiguration { @@ -45,7 +50,7 @@ pub struct ContextConfiguration { #[derive(Debug, Deserialize, Serialize)] pub enum WebGPURequest { BufferMapAsync { - sender: IpcSender, + sender: IpcSender>, buffer_id: id::BufferId, device_id: id::DeviceId, host_map: HostMap, @@ -109,7 +114,7 @@ pub enum WebGPURequest { descriptor: ComputePipelineDescriptor<'static>, implicit_ids: Option<(id::PipelineLayoutId, Vec)>, /// present only on ASYNC versions - async_sender: Option>, + async_sender: Option>, }, CreatePipelineLayout { device_id: id::DeviceId, @@ -122,7 +127,7 @@ pub enum WebGPURequest { descriptor: RenderPipelineDescriptor<'static>, implicit_ids: Option<(id::PipelineLayoutId, Vec)>, /// present only on ASYNC versions - async_sender: Option>, + async_sender: Option>, }, CreateSampler { device_id: id::DeviceId, @@ -134,7 +139,7 @@ pub enum WebGPURequest { program_id: id::ShaderModuleId, program: String, label: Option, - sender: IpcSender, + sender: IpcSender>, }, /// Creates context CreateContext { @@ -206,12 +211,12 @@ pub enum WebGPURequest { device_id: id::DeviceId, }, RequestAdapter { - sender: IpcSender, + sender: IpcSender, options: RequestAdapterOptions, adapter_id: AdapterId, }, RequestDevice { - sender: IpcSender, + sender: IpcSender, adapter_id: WebGPUAdapter, descriptor: wgt::DeviceDescriptor>, device_id: id::DeviceId, @@ -300,7 +305,7 @@ pub enum WebGPURequest { data: IpcSharedMemory, }, QueueOnSubmittedWorkDone { - sender: IpcSender, + sender: IpcSender<()>, queue_id: id::QueueId, }, PushErrorScope { @@ -313,7 +318,7 @@ pub enum WebGPURequest { }, PopErrorScope { device_id: id::DeviceId, - sender: IpcSender, + sender: IpcSender, }, ComputeGetBindGroupLayout { device_id: id::DeviceId, diff --git a/components/webgpu/ipc_messages/to_dom.rs b/components/webgpu/ipc_messages/to_dom.rs index 8525a46d78c..5dfa2e1abca 100644 --- a/components/webgpu/ipc_messages/to_dom.rs +++ b/components/webgpu/ipc_messages/to_dom.rs @@ -12,7 +12,6 @@ use wgc::id; use wgc::pipeline::CreateShaderModuleError; use wgpu_core::device::HostMap; use wgpu_core::instance::{RequestAdapterError, RequestDeviceError}; -use wgpu_core::resource::BufferAccessError; pub use {wgpu_core as wgc, wgpu_types as wgt}; use crate::identity::*; @@ -82,23 +81,14 @@ pub struct Mapping { pub range: Range, } -#[derive(Debug, Deserialize, Serialize)] -#[allow(clippy::large_enum_variant)] -pub enum WebGPUResponse { - /// WebGPU is disabled - None, - Adapter(Result), - Device( - ( - WebGPUDevice, - WebGPUQueue, - Result>, RequestDeviceError>, - ), - ), - BufferMapAsync(Result), - SubmittedWorkDone, - PoppedErrorScope(Result, PopError>), - CompilationInfo(Option), - RenderPipeline(Result, Error>), - ComputePipeline(Result, Error>), -} +pub type WebGPUDeviceResponse = ( + WebGPUDevice, + WebGPUQueue, + Result>, RequestDeviceError>, +); + +pub type WebGPUAdapterResponse = Option>; + +pub type WebGPUPoppedErrorScopeResponse = Result, PopError>; +pub type WebGPURenderPipelineResponse = Result, Error>; +pub type WebGPUComputePipelineResponse = Result, Error>; diff --git a/components/webgpu/wgpu_thread.rs b/components/webgpu/wgpu_thread.rs index 01415e83cf4..d0cec8250ba 100644 --- a/components/webgpu/wgpu_thread.rs +++ b/components/webgpu/wgpu_thread.rs @@ -36,7 +36,7 @@ use crate::render_commands::apply_render_command; use crate::swapchain::{WGPUImageMap, WebGPUContextId}; use crate::{ Adapter, ComputePassId, Error, Mapping, Pipeline, PopError, RenderPassId, WebGPU, - WebGPUAdapter, WebGPUDevice, WebGPUMsg, WebGPUQueue, WebGPURequest, WebGPUResponse, + WebGPUAdapter, WebGPUDevice, WebGPUMsg, WebGPUQueue, WebGPURequest, }; #[derive(Eq, Hash, PartialEq)] @@ -196,9 +196,7 @@ impl WGPU { mode: host_map, }) }); - if let Err(e) = - resp_sender.send(WebGPUResponse::BufferMapAsync(response)) - { + if let Err(e) = resp_sender.send(response) { warn!("Could not send BufferMapAsync Response ({})", e); } }); @@ -392,8 +390,8 @@ impl WGPU { }), Some(e) => Err(Error::from_error(e)), }; - if let Err(e) = sender.send(WebGPUResponse::ComputePipeline(res)) { - warn!("Failed sending WebGPUResponse::ComputePipeline {e:?}"); + if let Err(e) = sender.send(res) { + warn!("Failed sending WebGPUComputePipelineResponse {e:?}"); } } else { self.maybe_dispatch_wgpu_error(device_id, error); @@ -451,8 +449,8 @@ impl WGPU { }), Some(e) => Err(Error::from_error(e)), }; - if let Err(e) = sender.send(WebGPUResponse::RenderPipeline(res)) { - warn!("Failed sending WebGPUResponse::RenderPipeline {e:?}"); + if let Err(e) = sender.send(res) { + warn!("Failed sending WebGPURenderPipelineResponse {e:?}"); } } else { self.maybe_dispatch_wgpu_error(device_id, error); @@ -488,12 +486,12 @@ impl WGPU { source, Some(program_id), ); - if let Err(e) = sender.send(WebGPUResponse::CompilationInfo( + if let Err(e) = sender.send( error .as_ref() .map(|e| crate::ShaderCompilationInfo::from(e, &program)), - )) { - warn!("Failed to send WebGPUResponse::CompilationInfo {e:?}"); + ) { + warn!("Failed to send CompilationInfo {e:?}"); } self.maybe_dispatch_wgpu_error(device_id, error); }, @@ -669,7 +667,7 @@ impl WGPU { } }); - if let Err(e) = sender.send(WebGPUResponse::Adapter(response)) { + if let Err(e) = sender.send(Some(response)) { warn!( "Failed to send response to WebGPURequest::RequestAdapter ({})", e @@ -739,8 +737,7 @@ impl WGPU { global.device_set_device_lost_closure(device_id, callback); descriptor }); - if let Err(e) = sender.send(WebGPUResponse::Device((device, queue, result))) - { + if let Err(e) = sender.send((device, queue, result)) { warn!( "Failed to send response to WebGPURequest::RequestDevice ({})", e @@ -1048,7 +1045,7 @@ impl WGPU { let token = self.poller.token(); let callback = Box::from(move || { drop(token); - if let Err(e) = sender.send(WebGPUResponse::SubmittedWorkDone) { + if let Err(e) = sender.send(()) { warn!("Could not send SubmittedWorkDone Response ({})", e); } }); @@ -1187,25 +1184,21 @@ impl WGPU { .expect("Device should not be dropped by this point"); if let Some(error_scope_stack) = &mut device_scope.error_scope_stack { if let Some(error_scope) = error_scope_stack.pop() { - if let Err(e) = sender.send(WebGPUResponse::PoppedErrorScope(Ok( + if let Err(e) = sender.send(Ok( // TODO: Do actual selection instead of selecting first error error_scope.errors.first().cloned(), - ))) { + )) { warn!( "Unable to send {:?} to poperrorscope: {e:?}", error_scope.errors ); } - } else if let Err(e) = - sender.send(WebGPUResponse::PoppedErrorScope(Err(PopError::Empty))) - { + } else if let Err(e) = sender.send(Err(PopError::Empty)) { warn!("Unable to send PopError::Empty: {e:?}"); } } else { // device lost - if let Err(e) = - sender.send(WebGPUResponse::PoppedErrorScope(Err(PopError::Lost))) - { + if let Err(e) = sender.send(Err(PopError::Lost)) { warn!("Unable to send PopError::Lost due {e:?}"); } }