aboutsummaryrefslogtreecommitdiffstats
path: root/components
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
parent8ef7f245419bc7968a970f6e992f8760a6bedc97 (diff)
downloadservo-fae66089fac0a08d609c567609c960844922878a.tar.gz
servo-fae66089fac0a08d609c567609c960844922878a.zip
Implement GPUQueue.writeBuffer and GPUQueue.writeTexture
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/gpudevice.rs4
-rw-r--r--components/script/dom/gpuqueue.rs114
-rw-r--r--components/script/dom/gputexture.rs4
-rw-r--r--components/script/dom/webidls/GPUBuffer.webidl2
-rw-r--r--components/script/dom/webidls/GPUQueue.webidl25
-rw-r--r--components/script/dom/webidls/GPUTexture.webidl19
-rw-r--r--components/webgpu/lib.rs43
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
+ ));
+ },
}
}
}