diff --git a/components/script/dom/gpu.rs b/components/script/dom/gpu.rs index 2839ed94835..eea21c1b988 100644 --- a/components/script/dom/gpu.rs +++ b/components/script/dom/gpu.rs @@ -41,7 +41,7 @@ impl GPU { } pub trait AsyncWGPUListener { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc); + fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc); } struct WGPUResponse { @@ -53,13 +53,7 @@ impl WGPUResponse { #[allow(unrooted_must_root)] fn response(self, response: WebGPUResponseResult) { let promise = self.trusted.root(); - match response { - Ok(response) => self.receiver.root().handle_response(response, &promise), - Err(error) => promise.reject_error(Error::Type(format!( - "Received error from WebGPU thread: {}", - error - ))), - } + self.receiver.root().handle_response(response, &promise); } } @@ -134,13 +128,13 @@ impl GPUMethods for GPU { } impl AsyncWGPUListener for GPU { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc) { + fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc) { match response { - WebGPUResponse::RequestAdapter { + Ok(WebGPUResponse::RequestAdapter { adapter_name, adapter_id, channel, - } => { + }) => { let adapter = GPUAdapter::new( &self.global(), channel, @@ -150,7 +144,14 @@ impl AsyncWGPUListener for GPU { ); promise.resolve_native(&adapter); }, - _ => promise.reject_error(Error::Operation), + Err(e) => { + warn!("Could not get GPUAdapter ({:?})", e); + promise.resolve_native(&None::); + }, + _ => { + warn!("GPU received wrong WebGPUResponse"); + promise.reject_error(Error::Operation); + }, } } } diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index 9392f1414fa..ca4eaacd2ae 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -20,7 +20,7 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use std::ptr::NonNull; use std::rc::Rc; -use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse}; +use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPUResponseResult}; #[dom_struct] pub struct GPUAdapter { @@ -114,14 +114,14 @@ impl GPUAdapterMethods for GPUAdapter { } impl AsyncWGPUListener for GPUAdapter { - fn handle_response(&self, response: WebGPUResponse, promise: &Rc) { + fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc) { match response { - WebGPUResponse::RequestDevice { + Ok(WebGPUResponse::RequestDevice { device_id, queue_id, _descriptor, label, - } => { + }) => { let device = GPUDevice::new( &self.global(), self.channel.clone(), @@ -135,7 +135,14 @@ impl AsyncWGPUListener for GPUAdapter { self.global().add_gpu_device(&device); promise.resolve_native(&device); }, - _ => promise.reject_error(Error::Operation), + Err(e) => { + warn!("Could not get GPUDevice({:?})", e); + promise.reject_error(Error::Operation); + }, + _ => { + warn!("GPUAdapter received wrong WebGPUResponse"); + promise.reject_error(Error::Operation); + }, } } } diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index 0650e1390e1..330e6a27efd 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -26,7 +26,10 @@ use std::ffi::c_void; use std::ops::Range; use std::ptr::NonNull; use std::rc::Rc; -use webgpu::{wgpu::device::HostMap, WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse}; +use webgpu::{ + wgpu::device::HostMap, WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse, + WebGPUResponseResult, +}; const RANGE_OFFSET_ALIGN_MASK: u64 = 8; const RANGE_SIZE_ALIGN_MASK: u64 = 4; @@ -197,19 +200,21 @@ impl GPUBufferMethods for GPUBuffer { &self, mode: u32, offset: GPUSize64, - size: GPUSize64, + size: Option, comp: InRealm, ) -> Rc { let promise = Promise::new_in_current_realm(&self.global(), comp); - let map_range = if size == 0 { - offset..self.size + if self.state.get() != GPUBufferState::Unmapped { + promise.reject_error(Error::Abort); + return promise; + } + let range_size = if let Some(s) = size { + s + } else if offset >= self.size { + promise.reject_error(Error::Operation); + return promise; } else { - if offset + size > self.size { - warn!("Requested mapping size is greated than buffer size"); - promise.reject_error(Error::Abort); - return promise; - } - offset..offset + size + self.size - offset }; let host_map = match mode { GPUMapModeConstants::READ => HostMap::Read, @@ -219,10 +224,8 @@ impl GPUBufferMethods for GPUBuffer { return promise; }, }; - if self.state.get() != GPUBufferState::Unmapped { - promise.reject_error(Error::Abort); - return promise; - } + + let map_range = offset..offset + range_size; let sender = response_async(&promise, self); if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { @@ -257,9 +260,16 @@ impl GPUBufferMethods for GPUBuffer { &self, cx: JSContext, offset: GPUSize64, - size: GPUSize64, + size: Option, ) -> Fallible> { - let m_end = if size == 0 { self.size } else { offset + size }; + let range_size = if let Some(s) = size { + s + } else if offset >= self.size { + return Err(Error::Operation); + } else { + self.size - offset + }; + let m_end = offset + range_size; let mut info = self.map_info.borrow_mut(); let m_info = info.as_mut().unwrap(); @@ -268,7 +278,7 @@ impl GPUBufferMethods for GPUBuffer { _ => false, }; valid &= offset % RANGE_OFFSET_ALIGN_MASK == 0 && - (m_end - offset) % RANGE_SIZE_ALIGN_MASK == 0 && + range_size % RANGE_SIZE_ALIGN_MASK == 0 && offset >= m_info.mapping_range.start && m_end <= m_info.mapping_range.end; valid &= m_info @@ -286,7 +296,7 @@ impl GPUBufferMethods for GPUBuffer { let array_buffer = unsafe { NewExternalArrayBuffer( *cx, - (m_end - offset) as usize, + range_size as usize, m_info.mapping.borrow_mut()[offset as usize..m_end as usize].as_mut_ptr() as _, Some(free_func), Rc::into_raw(m_info.mapping.clone()) as _, @@ -312,9 +322,9 @@ impl GPUBufferMethods for GPUBuffer { impl AsyncWGPUListener for GPUBuffer { #[allow(unsafe_code)] - fn handle_response(&self, response: WebGPUResponse, promise: &Rc) { + fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc) { match response { - WebGPUResponse::BufferMapAsync(bytes) => { + Ok(WebGPUResponse::BufferMapAsync(bytes)) => { *self .map_info .borrow_mut() @@ -325,8 +335,12 @@ impl AsyncWGPUListener for GPUBuffer { promise.resolve_native(&()); self.state.set(GPUBufferState::Mapped); }, + Err(e) => { + warn!("Could not map buffer({:?})", e); + promise.reject_error(Error::Abort); + }, _ => { - warn!("Wrong WebGPUResponse received"); + warn!("GPUBuffer received wrong WebGPUResponse"); promise.reject_error(Error::Operation); }, } diff --git a/components/script/dom/webidls/GPUBuffer.webidl b/components/script/dom/webidls/GPUBuffer.webidl index dc6936a60bf..2097db233e9 100644 --- a/components/script/dom/webidls/GPUBuffer.webidl +++ b/components/script/dom/webidls/GPUBuffer.webidl @@ -5,8 +5,8 @@ // https://gpuweb.github.io/gpuweb/#gpubuffer [Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] interface GPUBuffer { - Promise mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); - [Throws] ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size = 0); + Promise mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size); + [Throws] ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size); void unmap(); void destroy(); diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index df42c685ae5..3fed81811e3 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -412,7 +412,7 @@ impl<'a> WGPU<'a> { } => { let map_info = BufferMapInfo { buffer_id, - sender, + sender: sender.clone(), global: &self.global, size: (map_range.end - map_range.start) as usize, external_id: None, @@ -426,22 +426,24 @@ impl<'a> WGPU<'a> { let info = Rc::from_raw( userdata as *const BufferMapInfo, ); - match status { + let msg = match status { BufferMapAsyncStatus::Success => { let global = &info.global; let data_pt = gfx_select!(info.buffer_id => global.buffer_get_mapped_range(info.buffer_id, 0, None)) .unwrap(); let data = slice::from_raw_parts(data_pt, info.size); - if let Err(e) = - info.sender.send(Ok(WebGPUResponse::BufferMapAsync( - IpcSharedMemory::from_bytes(data), - ))) - { - warn!("Could not send BufferMapAsync Response ({})", e); - } + Ok(WebGPUResponse::BufferMapAsync(IpcSharedMemory::from_bytes( + data, + ))) }, - _ => error!("Could not map buffer({:?})", info.buffer_id), + _ => { + warn!("Could not map buffer({:?})", info.buffer_id); + Err(String::from("Failed to map Buffer")) + }, + }; + if let Err(e) = info.sender.send(msg) { + warn!("Could not send BufferMapAsync Response ({})", e); } } @@ -453,7 +455,12 @@ impl<'a> WGPU<'a> { ), }; let global = &self.global; - let _ = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); + let result = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); + if let Err(e) = result { + if let Err(w) = sender.send(Err(format!("{:?}", e))) { + warn!("Failed to send BufferMapAsync Response ({:?})", w); + } + } }, WebGPURequest::BufferMapComplete(buffer_id) => { self.buffer_maps.remove(&buffer_id); @@ -892,14 +899,23 @@ impl<'a> WGPU<'a> { label, } => { let global = &self.global; - let result = gfx_select!(device_id => global.adapter_request_device( + let id = match gfx_select!(device_id => global.adapter_request_device( adapter_id.0, &descriptor, None, device_id - )); - // TODO: Handle error gracefully acc. to spec. - let id = result.unwrap(); + )) { + Ok(id) => id, + Err(e) => { + if let Err(w) = sender.send(Err(format!("{:?}", e))) { + warn!( + "Failed to send response to WebGPURequest::RequestDevice ({})", + w + ) + } + return; + }, + }; let device = WebGPUDevice(id); // Note: (zakorgy) Note sure if sending the queue is needed at all, // since wgpu-core uses the same id for the device and the queue