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 | |
parent | 8ef7f245419bc7968a970f6e992f8760a6bedc97 (diff) | |
download | servo-fae66089fac0a08d609c567609c960844922878a.tar.gz servo-fae66089fac0a08d609c567609c960844922878a.zip |
Implement GPUQueue.writeBuffer and GPUQueue.writeTexture
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/gpudevice.rs | 4 | ||||
-rw-r--r-- | components/script/dom/gpuqueue.rs | 114 | ||||
-rw-r--r-- | components/script/dom/gputexture.rs | 4 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUBuffer.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUQueue.webidl | 25 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUTexture.webidl | 19 | ||||
-rw-r--r-- | components/webgpu/lib.rs | 43 |
7 files changed, 199 insertions, 12 deletions
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index d5250f1230f..c5e5803f7e6 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -874,7 +874,7 @@ pub fn convert_texture_view_dimension( } } -fn convert_texture_size_to_dict(size: &GPUExtent3D) -> GPUExtent3DDict { +pub fn convert_texture_size_to_dict(size: &GPUExtent3D) -> GPUExtent3DDict { match *size { GPUExtent3D::GPUExtent3DDict(ref dict) => GPUExtent3DDict { width: dict.width, @@ -889,7 +889,7 @@ fn convert_texture_size_to_dict(size: &GPUExtent3D) -> GPUExtent3DDict { } } -fn convert_texture_size_to_wgt(size: &GPUExtent3DDict) -> wgt::Extent3d { +pub fn convert_texture_size_to_wgt(size: &GPUExtent3DDict) -> wgt::Extent3d { wgt::Extent3d { width: size.width, height: size.height, 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(()) + } } diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 6bf4892887a..0dbb3022291 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -107,6 +107,10 @@ impl GPUTexture { pub fn id(&self) -> WebGPUTexture { self.texture } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } } impl GPUTextureMethods for GPUTexture { diff --git a/components/script/dom/webidls/GPUBuffer.webidl b/components/script/dom/webidls/GPUBuffer.webidl index 4611b26c3ae..dc6936a60bf 100644 --- a/components/script/dom/webidls/GPUBuffer.webidl +++ b/components/script/dom/webidls/GPUBuffer.webidl @@ -20,5 +20,3 @@ dictionary GPUBufferDescriptor : GPUObjectDescriptorBase { }; typedef unsigned long long GPUSize64; - -typedef sequence<any> GPUMappedBuffer; diff --git a/components/script/dom/webidls/GPUQueue.webidl b/components/script/dom/webidls/GPUQueue.webidl index a1fdb9aa882..b1046093591 100644 --- a/components/script/dom/webidls/GPUQueue.webidl +++ b/components/script/dom/webidls/GPUQueue.webidl @@ -7,12 +7,25 @@ interface GPUQueue { void submit(sequence<GPUCommandBuffer> commandBuffers); - // GPUFence createFence(optional GPUFenceDescriptor descriptor = {}); - // void signal(GPUFence fence, unsigned long long signalValue); + //GPUFence createFence(optional GPUFenceDescriptor descriptor = {}); + //void signal(GPUFence fence, GPUFenceValue signalValue); - // void copyImageBitmapToTexture( - // GPUImageBitmapCopyView source, - // GPUTextureCopyView destination, - // GPUExtent3D copySize); + [Throws] void writeBuffer( + GPUBuffer buffer, + GPUSize64 bufferOffset, + /*[AllowShared]*/ ArrayBuffer data, + optional GPUSize64 dataOffset = 0, + optional GPUSize64 size); + + [Throws] void writeTexture( + GPUTextureCopyView destination, + /*[AllowShared]*/ ArrayBuffer data, + GPUTextureDataLayout dataLayout, + GPUExtent3D size); + + //void copyImageBitmapToTexture( + // GPUImageBitmapCopyView source, + // GPUTextureCopyView destination, + // GPUExtent3D copySize); }; GPUQueue includes GPUObjectBase; diff --git a/components/script/dom/webidls/GPUTexture.webidl b/components/script/dom/webidls/GPUTexture.webidl index 1058e69d1d4..840b0f17609 100644 --- a/components/script/dom/webidls/GPUTexture.webidl +++ b/components/script/dom/webidls/GPUTexture.webidl @@ -92,3 +92,22 @@ dictionary GPUExtent3DDict { }; typedef [EnforceRange] unsigned long GPUIntegerCoordinate; typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D; + +dictionary GPUTextureCopyView { + required GPUTexture texture; + GPUIntegerCoordinate mipLevel = 0; + GPUOrigin3D origin = {}; +}; + +dictionary GPUTextureDataLayout { + GPUSize64 offset = 0; + required GPUSize32 bytesPerRow; + GPUSize32 rowsPerImage = 0; +}; + +dictionary GPUOrigin3DDict { + GPUIntegerCoordinate x = 0; + GPUIntegerCoordinate y = 0; + GPUIntegerCoordinate z = 0; +}; +typedef (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict) GPUOrigin3D; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index a78c78743a3..5fa867901cd 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -208,6 +208,19 @@ pub enum WebGPURequest { external_id: u64, buffer_size: usize, }, + WriteBuffer { + queue_id: id::QueueId, + buffer_id: id::BufferId, + buffer_offset: u64, + data: IpcSharedMemory, + }, + WriteTexture { + queue_id: id::QueueId, + texture_cv: TextureCopyView, + data_layout: wgt::TextureDataLayout, + size: wgt::Extent3d, + data: IpcSharedMemory, + }, } #[derive(Debug, Deserialize, Serialize)] @@ -1023,6 +1036,36 @@ impl<'a> WGPU<'a> { gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); self.present_buffer_maps.remove(&buffer_id); }, + WebGPURequest::WriteBuffer { + queue_id, + buffer_id, + buffer_offset, + data, + } => { + let global = &self.global; + gfx_select!(queue_id => global.queue_write_buffer( + queue_id, + buffer_id, + buffer_offset as wgt::BufferAddress, + &data + )); + }, + WebGPURequest::WriteTexture { + queue_id, + texture_cv, + data_layout, + size, + data, + } => { + let global = &self.global; + gfx_select!(queue_id => global.queue_write_texture( + queue_id, + &texture_cv, + &data, + &data_layout, + &size + )); + }, } } } |