diff options
Diffstat (limited to 'components/script/dom/gpudevice.rs')
-rw-r--r-- | components/script/dom/gpudevice.rs | 164 |
1 files changed, 161 insertions, 3 deletions
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index d04ae97483a..81974735b55 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -2,19 +2,30 @@ * 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/. */ +#![allow(unsafe_code)] + use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods}; -use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::gpuadapter::GPUAdapter; +use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; +use crate::dom::window::Window; use crate::script_runtime::JSContext as SafeJSContext; use dom_struct::dom_struct; +use ipc_channel::ipc; use js::jsapi::{Heap, JSObject}; -use std::ptr::NonNull; -use webgpu::WebGPUDevice; +use js::jsval::{JSVal, ObjectValue, UndefinedValue}; +use js::typedarray::{ArrayBuffer, CreateWith}; +use std::ptr::{self, NonNull}; +use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage}; +use webgpu::{WebGPUBuffer, WebGPUDevice, WebGPURequest}; #[dom_struct] pub struct GPUDevice { @@ -63,6 +74,68 @@ impl GPUDevice { } } +impl GPUDevice { + unsafe fn resolve_create_buffer_mapped( + &self, + cx: SafeJSContext, + channel: ipc_channel::ipc::IpcSender<WebGPURequest>, + gpu_buffer: WebGPUBuffer, + array_buffer: Vec<u8>, + descriptor: BufferDescriptor, + valid: bool, + ) -> Vec<JSVal> { + rooted!(in(*cx) let mut js_array_buffer = ptr::null_mut::<JSObject>()); + let mut out = Vec::new(); + assert!(ArrayBuffer::create( + *cx, + CreateWith::Slice(array_buffer.as_slice()), + js_array_buffer.handle_mut(), + ) + .is_ok()); + + let buff = GPUBuffer::new( + &self.global(), + channel, + gpu_buffer, + self.device, + GPUBufferState::Mapped, + descriptor.size, + descriptor.usage.bits(), + valid, + ); + out.push(ObjectValue(buff.reflector().get_jsobject().get())); + out.push(ObjectValue(js_array_buffer.get())); + out + } + + fn validate_buffer_descriptor( + &self, + descriptor: &GPUBufferDescriptor, + ) -> (bool, BufferDescriptor) { + // TODO: Record a validation error in the current scope if the descriptor is invalid. + let wgpu_usage = BufferUsage::from_bits(descriptor.usage); + let valid = wgpu_usage.is_some() && descriptor.size > 0; + + if valid { + ( + true, + BufferDescriptor { + size: descriptor.size, + usage: wgpu_usage.unwrap(), + }, + ) + } else { + ( + false, + BufferDescriptor { + size: 0, + usage: BufferUsage::STORAGE, + }, + ) + } + } +} + impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-adapter fn Adapter(&self) -> DomRoot<GPUAdapter> { @@ -88,4 +161,89 @@ impl GPUDeviceMethods for GPUDevice { fn SetLabel(&self, value: Option<DOMString>) { *self.label.borrow_mut() = value; } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer + fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> { + let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); + let channel; + let (sender, receiver) = ipc::channel().unwrap(); + if let Some(window) = self.global().downcast::<Window>() { + let id = window.Navigator().create_buffer_id(self.device.0.backend()); + match window.webgpu_channel() { + Some(thread) => { + channel = thread.0.clone(); + thread + .0 + .send(WebGPURequest::CreateBuffer( + sender, + self.device, + id, + wgpu_descriptor, + )) + .unwrap(); + }, + None => unimplemented!(), + } + } else { + unimplemented!() + }; + + let buffer = receiver.recv().unwrap(); + + GPUBuffer::new( + &self.global(), + channel, + buffer, + self.device, + GPUBufferState::Unmapped, + descriptor.size, + descriptor.usage, + valid, + ) + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffermapped + fn CreateBufferMapped( + &self, + cx: SafeJSContext, + descriptor: &GPUBufferDescriptor, + ) -> Vec<JSVal> { + let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); + let channel; + let (sender, receiver) = ipc::channel().unwrap(); + rooted!(in(*cx) let js_val = UndefinedValue()); + if let Some(window) = self.global().downcast::<Window>() { + let id = window.Navigator().create_buffer_id(self.device.0.backend()); + match window.webgpu_channel() { + Some(thread) => { + channel = thread.0.clone(); + thread + .0 + .send(WebGPURequest::CreateBufferMapped( + sender, + self.device, + id, + wgpu_descriptor.clone(), + )) + .unwrap() + }, + None => return vec![js_val.get()], + } + } else { + return vec![js_val.get()]; + }; + + let (buffer, array_buffer) = receiver.recv().unwrap(); + + unsafe { + self.resolve_create_buffer_mapped( + cx, + channel, + buffer, + array_buffer, + wgpu_descriptor, + valid, + ) + } + } } |