aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/gpubuffer.rs
diff options
context:
space:
mode:
authorTaym Haddadi <haddadi.taym@gmail.com>2024-02-13 08:58:48 +0100
committerGitHub <noreply@github.com>2024-02-13 07:58:48 +0000
commit9be989146d5b958cafcc930385e63595a885cb20 (patch)
tree6001d262d8f3b79618c867685281d9c32a22665b /components/script/dom/gpubuffer.rs
parente6baa26ff8bcf44f22fce2f4be70a42e037e9e3b (diff)
downloadservo-9be989146d5b958cafcc930385e63595a885cb20.tar.gz
servo-9be989146d5b958cafcc930385e63595a885cb20.zip
WebIDL: Use `ArrayBuffer` instead of raw `JSObject` in bindings (#31202)
* WebIDL: Use ArrayBuffer instead of raw JSObject in bindings Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Convert GPUBufferMapInfo mapping to Arc<Mutex> * Remove #[allow(unsafe_code)] from GPUBuffer * Add doc comments * Implement trace for Arc<Mutex<Vec<T>>> Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Use #[no_trace] for GPUBufferMapInfo.mapping * Make create_new_external_array_buffer generic Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Address review comments * Remove HeapTypedArray::new and avoid cloning Arc Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Use expect for GetMappedRange and ReadAsArrayBuffer Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Use doc comments for FileReaderSyncMethods Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Return for Error::JsFailed GetMappedRange and ReadAsArrayBuffer Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Fix detached_internal implementation and comments Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * format code Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> * Update expectations --------- Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com> Co-authored-by: sagudev <16504129+sagudev@users.noreply.github.com>
Diffstat (limited to 'components/script/dom/gpubuffer.rs')
-rw-r--r--components/script/dom/gpubuffer.rs75
1 files changed, 38 insertions, 37 deletions
diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs
index 8c7a268fa30..6031778179c 100644
--- a/components/script/dom/gpubuffer.rs
+++ b/components/script/dom/gpubuffer.rs
@@ -2,20 +2,20 @@
* 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::cell::{Cell, RefCell};
-use std::ffi::c_void;
+use std::cell::Cell;
use std::ops::Range;
-use std::ptr::NonNull;
use std::rc::Rc;
use std::string::String;
+use std::sync::{Arc, Mutex};
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSharedMemory;
-use js::jsapi::{DetachArrayBuffer, Heap, JSObject, NewExternalArrayBuffer};
+use js::typedarray::{ArrayBuffer, ArrayBufferU8};
use webgpu::identity::WebGPUOpResult;
use webgpu::wgpu::device::HostMap;
use webgpu::{WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
+use super::bindings::typedarrays::{create_new_external_array_buffer, HeapTypedArray};
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
GPUBufferMethods, GPUMapModeConstants, GPUSize64,
@@ -46,12 +46,15 @@ pub enum GPUBufferState {
#[derive(JSTraceable, MallocSizeOf)]
pub struct GPUBufferMapInfo {
- #[ignore_malloc_size_of = "Rc"]
- pub mapping: Rc<RefCell<Vec<u8>>>,
+ #[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
+ /// The `mapping` is wrapped in an `Arc` to ensure thread safety.
+ /// This is necessary for integration with the SpiderMonkey engine,
+ pub mapping: Arc<Mutex<Vec<u8>>>,
pub mapping_range: Range<u64>,
pub mapped_ranges: Vec<Range<u64>>,
#[ignore_malloc_size_of = "defined in mozjs"]
- pub js_buffers: Vec<Box<Heap<*mut JSObject>>>,
+ pub js_buffers: Vec<HeapTypedArray<ArrayBufferU8>>,
pub map_mode: Option<u32>,
}
@@ -95,7 +98,6 @@ impl GPUBuffer {
}
}
- #[allow(unsafe_code)]
pub fn new(
global: &GlobalScope,
channel: WebGPU,
@@ -134,7 +136,6 @@ impl Drop for GPUBuffer {
}
impl GPUBufferMethods for GPUBuffer {
- #[allow(unsafe_code)]
/// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap>
fn Unmap(&self) -> Fallible<()> {
let cx = GlobalScope::get_cx();
@@ -147,16 +148,18 @@ impl GPUBufferMethods for GPUBuffer {
// Step 3
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
let mut info = self.map_info.borrow_mut();
- let m_info = info.as_mut().unwrap();
+ let m_info = if let Some(m_info) = info.as_mut() {
+ m_info
+ } else {
+ return Err(Error::Operation);
+ };
let m_range = m_info.mapping_range.clone();
if let Err(e) = self.channel.0.send((
self.device.use_current_scope(),
WebGPURequest::UnmapBuffer {
buffer_id: self.id().0,
device_id: self.device.id().0,
- array_buffer: IpcSharedMemory::from_bytes(
- m_info.mapping.borrow().as_slice(),
- ),
+ array_buffer: IpcSharedMemory::from_bytes(&*m_info.mapping.lock().unwrap()),
is_map_read: m_info.map_mode == Some(GPUMapModeConstants::READ),
offset: m_range.start,
size: m_range.end - m_range.start,
@@ -165,8 +168,8 @@ impl GPUBufferMethods for GPUBuffer {
warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e);
}
// Step 3.3
- m_info.js_buffers.drain(..).for_each(|obj| unsafe {
- DetachArrayBuffer(*cx, obj.handle());
+ m_info.js_buffers.drain(..).for_each(|obj| {
+ obj.detach_internal(cx);
});
},
// Step 2
@@ -205,7 +208,6 @@ impl GPUBufferMethods for GPUBuffer {
Ok(())
}
- #[allow(unsafe_code)]
/// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapasync-offset-size>
fn MapAsync(
&self,
@@ -268,7 +270,7 @@ impl GPUBufferMethods for GPUBuffer {
self.state.set(GPUBufferState::MappingPending);
*self.map_info.borrow_mut() = Some(GPUBufferMapInfo {
- mapping: Rc::new(RefCell::new(Vec::with_capacity(0))),
+ mapping: Arc::new(Mutex::new(Vec::with_capacity(0))),
mapping_range: map_range,
mapped_ranges: Vec::new(),
js_buffers: Vec::new(),
@@ -279,13 +281,12 @@ impl GPUBufferMethods for GPUBuffer {
}
/// <https://gpuweb.github.io/gpuweb/#dom-gpubuffer-getmappedrange>
- #[allow(unsafe_code)]
fn GetMappedRange(
&self,
cx: JSContext,
offset: GPUSize64,
size: Option<GPUSize64>,
- ) -> Fallible<NonNull<JSObject>> {
+ ) -> Fallible<ArrayBuffer> {
let range_size = if let Some(s) = size {
s
} else if offset >= self.size {
@@ -295,8 +296,11 @@ impl GPUBufferMethods for GPUBuffer {
};
let m_end = offset + range_size;
let mut info = self.map_info.borrow_mut();
- let m_info = info.as_mut().unwrap();
-
+ let m_info = if let Some(m_info) = info.as_mut() {
+ m_info
+ } else {
+ return Err(Error::Operation);
+ };
let mut valid = match self.state.get() {
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => true,
_ => false,
@@ -313,24 +317,20 @@ impl GPUBufferMethods for GPUBuffer {
return Err(Error::Operation);
}
- unsafe extern "C" fn free_func(_contents: *mut c_void, free_user_data: *mut c_void) {
- let _ = Rc::from_raw(free_user_data as _);
- }
+ let heap_typed_array = create_new_external_array_buffer::<ArrayBufferU8>(
+ cx,
+ Arc::clone(&m_info.mapping),
+ offset as usize,
+ range_size as usize,
+ m_end as usize,
+ );
- let array_buffer = unsafe {
- NewExternalArrayBuffer(
- *cx,
- 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 _,
- )
- };
+ let result = heap_typed_array.get_internal().map_err(|_| Error::JSFailed);
m_info.mapped_ranges.push(offset..m_end);
- m_info.js_buffers.push(Heap::boxed(array_buffer));
+ m_info.js_buffers.push(heap_typed_array);
- Ok(NonNull::new(array_buffer).unwrap())
+ result
}
/// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
@@ -345,7 +345,6 @@ impl GPUBufferMethods for GPUBuffer {
}
impl AsyncWGPUListener for GPUBuffer {
- #[allow(unsafe_code)]
fn handle_response(&self, response: Option<WebGPUResponseResult>, promise: &Rc<Promise>) {
match response {
Some(response) => match response {
@@ -356,7 +355,9 @@ impl AsyncWGPUListener for GPUBuffer {
.as_mut()
.unwrap()
.mapping
- .borrow_mut() = bytes.to_vec();
+ .lock()
+ .unwrap()
+ .as_mut() = bytes.to_vec();
promise.resolve_native(&());
self.state.set(GPUBufferState::Mapped);
},