aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/gpudevice.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/gpudevice.rs')
-rw-r--r--components/script/dom/gpudevice.rs164
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,
+ )
+ }
+ }
}