diff options
author | atbrakhi <atbrakhi@igalia.com> | 2024-11-28 15:24:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-28 14:24:15 +0000 |
commit | d2d3407501b83d03db522b5dde5e159073fd9e4b (patch) | |
tree | 299be7d04ca2470f1c6c8741e46784a2c7e85dd7 /components/script/dom/gpubuffer.rs | |
parent | a37ccc3e64c92e8ba10a3cdc48ebd7f031bb7298 (diff) | |
download | servo-d2d3407501b83d03db522b5dde5e159073fd9e4b.tar.gz servo-d2d3407501b83d03db522b5dde5e159073fd9e4b.zip |
Move script gpu files into webgpu folder (#34415)
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Diffstat (limited to 'components/script/dom/gpubuffer.rs')
-rw-r--r-- | components/script/dom/gpubuffer.rs | 427 |
1 files changed, 0 insertions, 427 deletions
diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs deleted file mode 100644 index e7bddcde8f1..00000000000 --- a/components/script/dom/gpubuffer.rs +++ /dev/null @@ -1,427 +0,0 @@ -/* 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 std::ops::Range; -use std::rc::Rc; -use std::string::String; - -use dom_struct::dom_struct; -use ipc_channel::ipc::IpcSharedMemory; -use js::typedarray::ArrayBuffer; -use webgpu::wgc::device::HostMap; -use webgpu::{wgt, Mapping, WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse}; - -use super::bindings::buffer_source::DataBlock; -use super::bindings::codegen::Bindings::WebGPUBinding::{ - GPUBufferDescriptor, GPUBufferMapState, GPUFlagsConstant, GPUMapModeFlags, -}; -use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUBufferMethods, GPUMapModeConstants, GPUSize64, -}; -use crate::dom::bindings::error::{Error, Fallible}; -use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; -use crate::dom::bindings::root::{Dom, DomRoot}; -use crate::dom::bindings::str::USVString; -use crate::dom::globalscope::GlobalScope; -use crate::dom::gpu::{response_async, AsyncWGPUListener}; -use crate::dom::gpudevice::GPUDevice; -use crate::dom::promise::Promise; -use crate::realms::InRealm; -use crate::script_runtime::{CanGc, JSContext}; - -#[derive(JSTraceable, MallocSizeOf)] -pub struct ActiveBufferMapping { - // TODO(sagudev): Use IpcSharedMemory when https://github.com/servo/ipc-channel/pull/356 lands - /// <https://gpuweb.github.io/gpuweb/#active-buffer-mapping-data> - /// <https://gpuweb.github.io/gpuweb/#active-buffer-mapping-views> - pub data: DataBlock, - /// <https://gpuweb.github.io/gpuweb/#active-buffer-mapping-mode> - mode: GPUMapModeFlags, - /// <https://gpuweb.github.io/gpuweb/#active-buffer-mapping-range> - range: Range<u64>, -} - -impl ActiveBufferMapping { - /// <https://gpuweb.github.io/gpuweb/#abstract-opdef-initialize-an-active-buffer-mapping> - pub fn new(mode: GPUMapModeFlags, range: Range<u64>) -> Fallible<Self> { - // Step 1 - let size = range.end - range.start; - // Step 2 - if size > (1 << 53) - 1 { - return Err(Error::Range("Over MAX_SAFE_INTEGER".to_string())); - } - let size: usize = size - .try_into() - .map_err(|_| Error::Range("Over usize".to_string()))?; - Ok(Self { - data: DataBlock::new_zeroed(size), - mode, - range, - }) - } -} - -#[dom_struct] -pub struct GPUBuffer { - reflector_: Reflector, - #[ignore_malloc_size_of = "defined in webgpu"] - #[no_trace] - channel: WebGPU, - label: DomRefCell<USVString>, - #[no_trace] - buffer: WebGPUBuffer, - device: Dom<GPUDevice>, - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-size> - size: GPUSize64, - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-usage> - usage: GPUFlagsConstant, - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-pending_map-slot> - #[ignore_malloc_size_of = "promises are hard"] - pending_map: DomRefCell<Option<Rc<Promise>>>, - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapping-slot> - mapping: DomRefCell<Option<ActiveBufferMapping>>, -} - -impl GPUBuffer { - fn new_inherited( - channel: WebGPU, - buffer: WebGPUBuffer, - device: &GPUDevice, - size: GPUSize64, - usage: GPUFlagsConstant, - mapping: Option<ActiveBufferMapping>, - label: USVString, - ) -> 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), - } - } - - #[allow(clippy::too_many_arguments)] - pub fn new( - global: &GlobalScope, - channel: WebGPU, - buffer: WebGPUBuffer, - device: &GPUDevice, - size: GPUSize64, - usage: GPUFlagsConstant, - mapping: Option<ActiveBufferMapping>, - label: USVString, - ) -> DomRoot<Self> { - reflect_dom_object( - Box::new(GPUBuffer::new_inherited( - channel, buffer, device, size, usage, mapping, label, - )), - global, - ) - } -} - -impl GPUBuffer { - pub fn id(&self) -> WebGPUBuffer { - self.buffer - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer> - pub fn create( - device: &GPUDevice, - descriptor: &GPUBufferDescriptor, - ) -> Fallible<DomRoot<GPUBuffer>> { - let desc = wgt::BufferDescriptor { - label: (&descriptor.parent).into(), - size: descriptor.size as wgt::BufferAddress, - usage: wgt::BufferUsages::from_bits_retain(descriptor.usage), - mapped_at_creation: descriptor.mappedAtCreation, - }; - let id = device.global().wgpu_id_hub().create_buffer_id(); - - device - .channel() - .0 - .send(WebGPURequest::CreateBuffer { - device_id: device.id().0, - buffer_id: id, - descriptor: desc, - }) - .expect("Failed to create WebGPU buffer"); - - let buffer = WebGPUBuffer(id); - let mapping = if descriptor.mappedAtCreation { - Some(ActiveBufferMapping::new( - GPUMapModeConstants::WRITE, - 0..descriptor.size, - )?) - } else { - None - }; - - Ok(GPUBuffer::new( - &device.global(), - device.channel().clone(), - buffer, - device, - descriptor.size, - descriptor.usage, - mapping, - descriptor.parent.label.clone(), - )) - } -} - -impl Drop for GPUBuffer { - fn drop(&mut self) { - self.Destroy() - } -} - -impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer { - #[allow(unsafe_code)] - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap> - fn Unmap(&self) { - // Step 1 - if let Some(promise) = self.pending_map.borrow_mut().take() { - promise.reject_error(Error::Abort); - } - // 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); - } - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy> - 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 - ); - }; - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapasync> - fn MapAsync( - &self, - mode: u32, - offset: GPUSize64, - size: Option<GPUSize64>, - comp: InRealm, - can_gc: CanGc, - ) -> Rc<Promise> { - let promise = Promise::new_in_current_realm(comp, can_gc); - // Step 2 - if self.pending_map.borrow().is_some() { - promise.reject_error(Error::Operation); - return promise; - } - // Step 4 - *self.pending_map.borrow_mut() = Some(promise.clone()); - // Step 5 - let host_map = match mode { - GPUMapModeConstants::READ => HostMap::Read, - GPUMapModeConstants::WRITE => HostMap::Write, - _ => { - self.device - .dispatch_error(webgpu::Error::Validation(String::from( - "Invalid MapModeFlags", - ))); - self.map_failure(&promise); - return promise; - }, - }; - - let sender = response_async(&promise, self); - 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, - }) { - warn!( - "Failed to send BufferMapAsync ({:?}) ({})", - self.buffer.0, e - ); - self.map_failure(&promise); - return promise; - } - // Step 6 - promise - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-getmappedrange> - #[allow(unsafe_code)] - fn GetMappedRange( - &self, - _cx: JSContext, - offset: GPUSize64, - size: Option<GPUSize64>, - ) -> Fallible<ArrayBuffer> { - let range_size = if let Some(s) = size { - s - } else { - self.size.saturating_sub(offset) - }; - // Step 2: validation - let mut mapping = self.mapping.borrow_mut(); - let mapping = mapping.as_mut().ok_or(Error::Operation)?; - - let valid = offset % wgt::MAP_ALIGNMENT == 0 && - range_size % wgt::COPY_BUFFER_ALIGNMENT == 0 && - offset >= mapping.range.start && - offset + range_size <= mapping.range.end; - if !valid { - return Err(Error::Operation); - } - - // Step 4 - // only mapping.range is mapped with mapping.range.start at 0 - // so we need to rebase range to mapped.range - let rebased_offset = (offset - mapping.range.start) as usize; - mapping - .data - .view(rebased_offset..rebased_offset + range_size as usize) - .map(|view| view.array_buffer()) - .map_err(|()| Error::Operation) - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label> - fn Label(&self) -> USVString { - self.label.borrow().clone() - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label> - fn SetLabel(&self, value: USVString) { - *self.label.borrow_mut() = value; - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-size> - fn Size(&self) -> GPUSize64 { - self.size - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-usage> - fn Usage(&self) -> GPUFlagsConstant { - self.usage - } - - /// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapstate> - fn MapState(&self) -> GPUBufferMapState { - // Step 1&2&3 - if self.mapping.borrow().is_some() { - GPUBufferMapState::Mapped - } else if self.pending_map.borrow().is_some() { - GPUBufferMapState::Pending - } else { - GPUBufferMapState::Unmapped - } - } -} - -impl GPUBuffer { - fn map_failure(&self, p: &Rc<Promise>) { - let mut pending_map = self.pending_map.borrow_mut(); - // Step 1 - if pending_map.as_ref() != Some(p) { - assert!(p.is_rejected()); - return; - } - // Step 2 - assert!(p.is_pending()); - // Step 3 - pending_map.take(); - // Step 4 - if self.device.is_lost() { - p.reject_error(Error::Abort); - } else { - p.reject_error(Error::Operation); - } - } - - fn map_success(&self, p: &Rc<Promise>, wgpu_mapping: Mapping) { - let mut pending_map = self.pending_map.borrow_mut(); - - // Step 1 - if pending_map.as_ref() != Some(p) { - assert!(p.is_rejected()); - return; - } - - // Step 2 - assert!(p.is_pending()); - - // Step 4 - let mapping = ActiveBufferMapping::new( - match wgpu_mapping.mode { - HostMap::Read => GPUMapModeConstants::READ, - HostMap::Write => GPUMapModeConstants::WRITE, - }, - wgpu_mapping.range, - ); - - match mapping { - Err(error) => { - *pending_map = None; - p.reject_error(error.clone()); - }, - Ok(mut mapping) => { - // Step 5 - mapping.data.load(&wgpu_mapping.data); - // Step 6 - self.mapping.borrow_mut().replace(mapping); - // Step 7 - pending_map.take(); - p.resolve_native(&()); - }, - } - } -} - -impl AsyncWGPUListener for GPUBuffer { - #[allow(unsafe_code)] - fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, _can_gc: CanGc) { - match response { - WebGPUResponse::BufferMapAsync(Ok(mapping)) => self.map_success(promise, mapping), - WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise), - _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"), - } - } -} |