diff options
author | Kunal Mohan <kunalmohan99@gmail.com> | 2020-07-04 13:29:23 +0530 |
---|---|---|
committer | Kunal Mohan <kunalmohan99@gmail.com> | 2020-07-04 21:49:32 +0530 |
commit | fae66089fac0a08d609c567609c960844922878a (patch) | |
tree | d248ffaf56dd4b24a0e7de596a8b3fe26081b413 /components/script/dom/gpuqueue.rs | |
parent | 8ef7f245419bc7968a970f6e992f8760a6bedc97 (diff) | |
download | servo-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.rs | 114 |
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(()) + } } |