aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/gpuqueue.rs
diff options
context:
space:
mode:
authorKunal Mohan <kunalmohan99@gmail.com>2020-07-04 13:29:23 +0530
committerKunal Mohan <kunalmohan99@gmail.com>2020-07-04 21:49:32 +0530
commitfae66089fac0a08d609c567609c960844922878a (patch)
treed248ffaf56dd4b24a0e7de596a8b3fe26081b413 /components/script/dom/gpuqueue.rs
parent8ef7f245419bc7968a970f6e992f8760a6bedc97 (diff)
downloadservo-fae66089fac0a08d609c567609c960844922878a.tar.gz
servo-fae66089fac0a08d609c567609c960844922878a.zip
Implement GPUQueue.writeBuffer and GPUQueue.writeTexture
Diffstat (limited to 'components/script/dom/gpuqueue.rs')
-rw-r--r--components/script/dom/gpuqueue.rs114
1 files changed, 112 insertions, 2 deletions
diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs
index fa79dc6fd44..275d3144266 100644
--- a/components/script/dom/gpuqueue.rs
+++ b/components/script/dom/gpuqueue.rs
@@ -3,15 +3,24 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUSize64;
use crate::dom::bindings::codegen::Bindings::GPUQueueBinding::GPUQueueMethods;
+use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{
+ GPUExtent3D, GPUOrigin3D, GPUTextureCopyView, GPUTextureDataLayout,
+};
+use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
-use crate::dom::gpubuffer::GPUBufferState;
+use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpucommandbuffer::GPUCommandBuffer;
+use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt};
use dom_struct::dom_struct;
-use webgpu::{WebGPU, WebGPUQueue, WebGPURequest};
+use ipc_channel::ipc::IpcSharedMemory;
+use js::rust::CustomAutoRooterGuard;
+use js::typedarray::ArrayBuffer;
+use webgpu::{wgpu::command as wgpu_com, wgt, WebGPU, WebGPUQueue, WebGPURequest};
#[dom_struct]
pub struct GPUQueue {
@@ -69,4 +78,105 @@ impl GPUQueueMethods for GPUQueue {
})
.unwrap();
}
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpuqueue-writebuffer
+ #[allow(unsafe_code)]
+ fn WriteBuffer(
+ &self,
+ buffer: &GPUBuffer,
+ buffer_offset: GPUSize64,
+ data: CustomAutoRooterGuard<ArrayBuffer>,
+ data_offset: GPUSize64,
+ size: Option<GPUSize64>,
+ ) -> Fallible<()> {
+ let bytes = data.to_vec();
+ let content_size = if let Some(s) = size {
+ s
+ } else {
+ bytes.len() as GPUSize64 - data_offset
+ };
+ let valid = data_offset + content_size <= bytes.len() as u64 &&
+ buffer.state() == GPUBufferState::Unmapped &&
+ content_size % wgt::COPY_BUFFER_ALIGNMENT == 0 &&
+ buffer_offset % wgt::COPY_BUFFER_ALIGNMENT == 0 &&
+ buffer.is_valid();
+
+ if !valid {
+ return Err(Error::Operation);
+ }
+
+ let final_data = IpcSharedMemory::from_bytes(
+ &bytes[data_offset as usize..(data_offset + content_size) as usize],
+ );
+ if let Err(e) = self.channel.0.send(WebGPURequest::WriteBuffer {
+ queue_id: self.queue.0,
+ buffer_id: buffer.id().0,
+ buffer_offset,
+ data: final_data,
+ }) {
+ warn!("Failed to send WriteBuffer({:?}) ({})", buffer.id(), e);
+ return Err(Error::Operation);
+ }
+
+ Ok(())
+ }
+
+ /// https://gpuweb.github.io/gpuweb/#dom-gpuqueue-writetexture
+ fn WriteTexture(
+ &self,
+ destination: &GPUTextureCopyView,
+ data: CustomAutoRooterGuard<ArrayBuffer>,
+ data_layout: &GPUTextureDataLayout,
+ size: GPUExtent3D,
+ ) -> Fallible<()> {
+ let bytes = data.to_vec();
+ let valid = data_layout.offset <= data.len() as u64 && destination.texture.is_valid();
+
+ if !valid {
+ return Err(Error::Operation);
+ }
+
+ let texture_cv = wgpu_com::TextureCopyView {
+ texture: destination.texture.id().0,
+ mip_level: destination.mipLevel,
+ origin: match destination.origin {
+ GPUOrigin3D::RangeEnforcedUnsignedLongSequence(ref v) => wgt::Origin3d {
+ x: v[0],
+ y: v[1],
+ z: v[2],
+ },
+ GPUOrigin3D::GPUOrigin3DDict(ref d) => wgt::Origin3d {
+ x: d.x,
+ y: d.y,
+ z: d.z,
+ },
+ },
+ };
+
+ let texture_layout = wgt::TextureDataLayout {
+ offset: data_layout.offset as wgt::BufferAddress,
+ bytes_per_row: data_layout.bytesPerRow,
+ rows_per_image: data_layout.rowsPerImage,
+ };
+
+ let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size));
+ let final_data = IpcSharedMemory::from_bytes(&bytes);
+
+ if let Err(e) = self.channel.0.send(WebGPURequest::WriteTexture {
+ queue_id: self.queue.0,
+ texture_cv,
+ data_layout: texture_layout,
+ size: write_size,
+ data: final_data,
+ }) {
+ warn!(
+ "Failed to send WriteTexture({:?}) ({})",
+ destination.texture.id().0,
+ e
+ );
+ return Err(Error::Operation);
+ }
+
+ Ok(())
+ }
}