From 627834fcbc3c4dd8925ae442bfbdaff2b229be97 Mon Sep 17 00:00:00 2001 From: Domenico Rizzo Date: Wed, 7 May 2025 17:50:16 +0200 Subject: [PATCH] Implement Droppable struct for gpubuffer Signed-off-by: Domenico Rizzo Corrected member access Signed-off-by: Domenico Rizzo removing unwanted macro Signed-off-by: Domenico Rizzo Corrected methods' name Signed-off-by: Domenico Rizzo applied mach fmt Signed-off-by: Domenico Rizzo --- components/script/dom/webgpu/gpubuffer.rs | 201 +++++++++++++--------- 1 file changed, 121 insertions(+), 80 deletions(-) diff --git a/components/script/dom/webgpu/gpubuffer.rs b/components/script/dom/webgpu/gpubuffer.rs index 0b41d386b4a..34524c9a43e 100644 --- a/components/script/dom/webgpu/gpubuffer.rs +++ b/components/script/dom/webgpu/gpubuffer.rs @@ -66,22 +66,13 @@ impl ActiveBufferMapping { #[dom_struct] pub(crate) struct GPUBuffer { reflector_: Reflector, - #[ignore_malloc_size_of = "defined in webgpu"] - #[no_trace] - channel: WebGPU, label: DomRefCell, - #[no_trace] - buffer: WebGPUBuffer, device: Dom, /// size: GPUSize64, /// usage: GPUFlagsConstant, - /// - #[ignore_malloc_size_of = "promises are hard"] - pending_map: DomRefCell>>, - /// - mapping: DomRefCell>, + droppable: DroppableGPUBuffer, } impl GPUBuffer { @@ -96,14 +87,16 @@ impl GPUBuffer { ) -> Self { Self { reflector_: Reflector::new(), - channel, label: DomRefCell::new(label), device: Dom::from_ref(device), - buffer, - pending_map: DomRefCell::new(None), size, usage, - mapping: DomRefCell::new(mapping), + droppable: DroppableGPUBuffer::new( + channel, + buffer, + DomRefCell::new(None), + DomRefCell::new(mapping), + ), } } @@ -131,7 +124,7 @@ impl GPUBuffer { impl GPUBuffer { pub(crate) fn id(&self) -> WebGPUBuffer { - self.buffer + self.droppable.buffer } /// @@ -182,62 +175,16 @@ impl GPUBuffer { } } -impl Drop for GPUBuffer { - fn drop(&mut self) { - self.Destroy() - } -} - impl GPUBufferMethods for GPUBuffer { #[allow(unsafe_code)] /// fn Unmap(&self) { - // Step 1 - if let Some(promise) = self.pending_map.borrow_mut().take() { - promise.reject_error(Error::Abort, CanGc::note()); - } - // Step 2 - let mut mapping = self.mapping.borrow_mut().take(); - let mapping = if let Some(mapping) = mapping.as_mut() { - mapping - } else { - return; - }; - - // Step 3 - mapping.data.clear_views(); - // Step 5&7 - if let Err(e) = self.channel.0.send(WebGPURequest::UnmapBuffer { - buffer_id: self.id().0, - mapping: if mapping.mode >= GPUMapModeConstants::WRITE { - Some(Mapping { - data: IpcSharedMemory::from_bytes(mapping.data.data()), - range: mapping.range.clone(), - mode: HostMap::Write, - }) - } else { - None - }, - }) { - warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e); - } + self.droppable.unmap() } /// fn Destroy(&self) { - // Step 1 - self.Unmap(); - // Step 2 - if let Err(e) = self - .channel - .0 - .send(WebGPURequest::DestroyBuffer(self.buffer.0)) - { - warn!( - "Failed to send WebGPURequest::DestroyBuffer({:?}) ({})", - self.buffer.0, e - ); - }; + self.droppable.destroy() } /// @@ -251,12 +198,12 @@ impl GPUBufferMethods for GPUBuffer { ) -> Rc { let promise = Promise::new_in_current_realm(comp, can_gc); // Step 2 - if self.pending_map.borrow().is_some() { + if self.droppable.pending_map.borrow().is_some() { promise.reject_error(Error::Operation, can_gc); return promise; } // Step 4 - *self.pending_map.borrow_mut() = Some(promise.clone()); + *self.droppable.pending_map.borrow_mut() = Some(promise.clone()); // Step 5 let host_map = match mode { GPUMapModeConstants::READ => HostMap::Read, @@ -276,17 +223,22 @@ impl GPUBufferMethods for GPUBuffer { self, self.global().task_manager().dom_manipulation_task_source(), ); - if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { - sender, - buffer_id: self.buffer.0, - device_id: self.device.id().0, - host_map, - offset, - size, - }) { + if let Err(e) = self + .droppable + .channel + .0 + .send(WebGPURequest::BufferMapAsync { + sender, + buffer_id: self.droppable.buffer.0, + device_id: self.device.id().0, + host_map, + offset, + size, + }) + { warn!( "Failed to send BufferMapAsync ({:?}) ({})", - self.buffer.0, e + self.droppable.buffer.0, e ); self.map_failure(&promise, can_gc); return promise; @@ -310,7 +262,7 @@ impl GPUBufferMethods for GPUBuffer { self.size.saturating_sub(offset) }; // Step 2: validation - let mut mapping = self.mapping.borrow_mut(); + let mut mapping = self.droppable.mapping.borrow_mut(); let mapping = mapping.as_mut().ok_or(Error::Operation)?; let valid = offset % wgpu_types::MAP_ALIGNMENT == 0 && @@ -355,9 +307,9 @@ impl GPUBufferMethods for GPUBuffer { /// fn MapState(&self) -> GPUBufferMapState { // Step 1&2&3 - if self.mapping.borrow().is_some() { + if self.droppable.mapping.borrow().is_some() { GPUBufferMapState::Mapped - } else if self.pending_map.borrow().is_some() { + } else if self.droppable.pending_map.borrow().is_some() { GPUBufferMapState::Pending } else { GPUBufferMapState::Unmapped @@ -367,7 +319,7 @@ impl GPUBufferMethods for GPUBuffer { impl GPUBuffer { fn map_failure(&self, p: &Rc, can_gc: CanGc) { - let mut pending_map = self.pending_map.borrow_mut(); + let mut pending_map = self.droppable.pending_map.borrow_mut(); // Step 1 if pending_map.as_ref() != Some(p) { assert!(p.is_rejected()); @@ -386,7 +338,7 @@ impl GPUBuffer { } fn map_success(&self, p: &Rc, wgpu_mapping: Mapping, can_gc: CanGc) { - let mut pending_map = self.pending_map.borrow_mut(); + let mut pending_map = self.droppable.pending_map.borrow_mut(); // Step 1 if pending_map.as_ref() != Some(p) { @@ -415,7 +367,7 @@ impl GPUBuffer { // Step 5 mapping.data.load(&wgpu_mapping.data); // Step 6 - self.mapping.borrow_mut().replace(mapping); + self.droppable.mapping.borrow_mut().replace(mapping); // Step 7 pending_map.take(); p.resolve_native(&(), can_gc); @@ -437,3 +389,92 @@ impl RoutedPromiseListener> for GPUBuffer { } } } + +#[derive(JSTraceable, MallocSizeOf)] +pub(crate) struct DroppableGPUBuffer { + #[ignore_malloc_size_of = "defined in webgpu"] + #[no_trace] + pub(crate) channel: WebGPU, + #[no_trace] + pub(crate) buffer: WebGPUBuffer, + /// + #[ignore_malloc_size_of = "promises are hard"] + pub(crate) pending_map: DomRefCell>>, + /// + pub(crate) mapping: DomRefCell>, +} + +impl DroppableGPUBuffer { + pub(crate) fn new( + channel: WebGPU, + buffer: WebGPUBuffer, + pending_map: DomRefCell>>, + mapping: DomRefCell>, + ) -> Self { + Self { + channel, + buffer, + pending_map, + mapping, + } + } +} + +impl DroppableGPUBuffer { + #[allow(unsafe_code)] + /// + pub(crate) fn unmap(&self) { + // Step 1 + if let Some(promise) = self.pending_map.borrow_mut().take() { + promise.reject_error(Error::Abort, CanGc::note()); + } + // Step 2 + let mut mapping = self.mapping.borrow_mut().take(); + let mapping = if let Some(mapping) = mapping.as_mut() { + mapping + } else { + return; + }; + + // Step 3 + mapping.data.clear_views(); + // Step 5&7 + if let Err(e) = self.channel.0.send(WebGPURequest::UnmapBuffer { + buffer_id: self.buffer.0, + mapping: if mapping.mode >= GPUMapModeConstants::WRITE { + Some(Mapping { + data: IpcSharedMemory::from_bytes(mapping.data.data()), + range: mapping.range.clone(), + mode: HostMap::Write, + }) + } else { + None + }, + }) { + warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e); + } + } + + /// + pub(crate) fn destroy(&self) { + // Step 1 + self.unmap(); + // Step 2 + if let Err(e) = self + .channel + .0 + .send(WebGPURequest::DestroyBuffer(self.buffer.0)) + { + warn!( + "Failed to send WebGPURequest::DestroyBuffer({:?}) ({})", + self.buffer.0, e + ); + }; + } +} + +impl Drop for DroppableGPUBuffer { + fn drop(&mut self) { + self.destroy() + } +}