diff options
-rw-r--r-- | components/script/dom/gpucommandencoder.rs | 200 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 12 | ||||
-rw-r--r-- | components/script/dom/gpuqueue.rs | 35 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUCommandEncoder.webidl | 68 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUTexture.webidl | 19 | ||||
-rw-r--r-- | components/webgpu/lib.rs | 60 |
6 files changed, 292 insertions, 102 deletions
diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index 5633d16f611..36b24b6b14e 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -5,12 +5,15 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUSize64; use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::{ - GPUCommandBufferDescriptor, GPUCommandEncoderMethods, GPUComputePassDescriptor, - GPURenderPassDescriptor, GPUStencilLoadValue, GPUStoreOp, + GPUBufferCopyView, GPUCommandBufferDescriptor, GPUCommandEncoderMethods, + GPUComputePassDescriptor, GPUOrigin3D, GPURenderPassDescriptor, GPUStencilLoadValue, + GPUStoreOp, GPUTextureCopyView, GPUTextureDataLayout, }; +use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D; use crate::dom::bindings::codegen::UnionTypes::{ GPULoadOpOrDoubleSequenceOrGPUColorDict as GPUColorLoad, GPULoadOpOrFloat, }; +use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::DomRoot; @@ -19,14 +22,12 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::gpubuffer::GPUBuffer; use crate::dom::gpucommandbuffer::GPUCommandBuffer; use crate::dom::gpucomputepassencoder::GPUComputePassEncoder; +use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt}; use crate::dom::gpurenderpassencoder::GPURenderPassEncoder; use dom_struct::dom_struct; use std::cell::Cell; use std::collections::HashSet; -use webgpu::wgpu::command::{ - ColorAttachmentDescriptor, DepthStencilAttachmentDescriptor, LoadOp, PassChannel, RenderPass, - RenderPassDescriptor, StoreOp, -}; +use webgpu::wgpu::command as wgpu_com; use webgpu::{self, wgt, WebGPU, WebGPUDevice, WebGPURequest}; // https://gpuweb.github.io/gpuweb/#enumdef-encoder-state @@ -139,18 +140,25 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { .iter() .map(|color| { let (load_op, clear_value) = match color.loadValue { - GPUColorLoad::GPULoadOp(_) => (LoadOp::Load, wgt::Color::TRANSPARENT), - GPUColorLoad::DoubleSequence(ref s) => ( - LoadOp::Clear, - wgt::Color { - r: *s[0], - g: *s[1], - b: *s[2], - a: *s[3], - }, - ), + GPUColorLoad::GPULoadOp(_) => (wgpu_com::LoadOp::Load, wgt::Color::TRANSPARENT), + GPUColorLoad::DoubleSequence(ref s) => { + let mut w = s.clone(); + if w.len() < 3 { + w.resize(3, Finite::wrap(0.0f64)); + } + w.resize(4, Finite::wrap(1.0f64)); + ( + wgpu_com::LoadOp::Clear, + wgt::Color { + r: *w[0], + g: *w[1], + b: *w[2], + a: *w[3], + }, + ) + }, GPUColorLoad::GPUColorDict(ref d) => ( - LoadOp::Clear, + wgpu_com::LoadOp::Clear, wgt::Color { r: *d.r, g: *d.g, @@ -159,16 +167,16 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { }, ), }; - let channel = PassChannel { + let channel = wgpu_com::PassChannel { load_op, store_op: match color.storeOp { - GPUStoreOp::Store => StoreOp::Store, - GPUStoreOp::Clear => StoreOp::Clear, + GPUStoreOp::Store => wgpu_com::StoreOp::Store, + GPUStoreOp::Clear => wgpu_com::StoreOp::Clear, }, clear_value, read_only: false, }; - ColorAttachmentDescriptor { + wgpu_com::ColorAttachmentDescriptor { attachment: color.attachment.id().0, resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0), channel, @@ -178,44 +186,44 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { let depth_stencil = descriptor.depthStencilAttachment.as_ref().map(|depth| { let (depth_load_op, clear_depth) = match depth.depthLoadValue { - GPULoadOpOrFloat::GPULoadOp(_) => (LoadOp::Load, 0.0f32), - GPULoadOpOrFloat::Float(f) => (LoadOp::Clear, *f), + GPULoadOpOrFloat::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0.0f32), + GPULoadOpOrFloat::Float(f) => (wgpu_com::LoadOp::Clear, *f), }; let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue { - GPUStencilLoadValue::GPULoadOp(_) => (LoadOp::Load, 0u32), - GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (LoadOp::Clear, l), + GPUStencilLoadValue::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0u32), + GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (wgpu_com::LoadOp::Clear, l), }; - let depth_channel = PassChannel { + let depth_channel = wgpu_com::PassChannel { load_op: depth_load_op, store_op: match depth.depthStoreOp { - GPUStoreOp::Store => StoreOp::Store, - GPUStoreOp::Clear => StoreOp::Clear, + GPUStoreOp::Store => wgpu_com::StoreOp::Store, + GPUStoreOp::Clear => wgpu_com::StoreOp::Clear, }, clear_value: clear_depth, read_only: depth.depthReadOnly, }; - let stencil_channel = PassChannel { + let stencil_channel = wgpu_com::PassChannel { load_op: stencil_load_op, store_op: match depth.stencilStoreOp { - GPUStoreOp::Store => StoreOp::Store, - GPUStoreOp::Clear => StoreOp::Clear, + GPUStoreOp::Store => wgpu_com::StoreOp::Store, + GPUStoreOp::Clear => wgpu_com::StoreOp::Clear, }, clear_value: clear_stencil, read_only: depth.stencilReadOnly, }; - DepthStencilAttachmentDescriptor { + wgpu_com::DepthStencilAttachmentDescriptor { attachment: depth.attachment.id().0, depth: depth_channel, stencil: stencil_channel, } }); - let desc = RenderPassDescriptor { + let desc = wgpu_com::RenderPassDescriptor { color_attachments: colors.as_slice(), depth_stencil_attachment: depth_stencil.as_ref(), }; - let render_pass = RenderPass::new(self.encoder.0, desc); + let render_pass = wgpu_com::RenderPass::new(self.encoder.0, desc); GPURenderPassEncoder::new(&self.global(), self.channel.clone(), render_pass, &self) } @@ -254,6 +262,92 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { .expect("Failed to send CopyBufferToBuffer"); } + /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertotexture + fn CopyBufferToTexture( + &self, + source: &GPUBufferCopyView, + destination: &GPUTextureCopyView, + copy_size: GPUExtent3D, + ) { + let valid = *self.state.borrow() == GPUCommandEncoderState::Open; + + if !valid { + // TODO: Record an error in the current scope. + self.valid.set(false); + return; + } + + self.buffers + .borrow_mut() + .insert(DomRoot::from_ref(&*source.buffer)); + + self.channel + .0 + .send(WebGPURequest::CopyBufferToTexture { + command_encoder_id: self.encoder.0, + source: convert_buffer_cv(source), + destination: convert_texture_cv(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) + .expect("Failed to send CopyBufferToTexture"); + } + + /// https://gpuweb.github.io/gpuweb/#GPUCommandEncoder-copyTextureToBuffer + fn CopyTextureToBuffer( + &self, + source: &GPUTextureCopyView, + destination: &GPUBufferCopyView, + copy_size: GPUExtent3D, + ) { + let valid = *self.state.borrow() == GPUCommandEncoderState::Open; + + if !valid { + // TODO: Record an error in the current scope. + self.valid.set(false); + return; + } + + self.buffers + .borrow_mut() + .insert(DomRoot::from_ref(&*destination.buffer)); + + self.channel + .0 + .send(WebGPURequest::CopyTextureToBuffer { + command_encoder_id: self.encoder.0, + source: convert_texture_cv(source), + destination: convert_buffer_cv(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) + .expect("Failed to send CopyTextureToBuffer"); + } + + /// https://gpuweb.github.io/gpuweb/#GPUCommandEncoder-copyTextureToTexture + fn CopyTextureToTexture( + &self, + source: &GPUTextureCopyView, + destination: &GPUTextureCopyView, + copy_size: GPUExtent3D, + ) { + let valid = *self.state.borrow() == GPUCommandEncoderState::Open; + + if !valid { + // TODO: Record an error in the current scope. + self.valid.set(false); + return; + } + + self.channel + .0 + .send(WebGPURequest::CopyTextureToTexture { + command_encoder_id: self.encoder.0, + source: convert_texture_cv(source), + destination: convert_texture_cv(destination), + copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(©_size)), + }) + .expect("Failed to send CopyTextureToTexture"); + } + /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish fn Finish(&self, _descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> { self.channel @@ -275,3 +369,41 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { ) } } + +fn convert_buffer_cv(buffer_cv: &GPUBufferCopyView) -> wgpu_com::BufferCopyView { + wgpu_com::BufferCopyView { + buffer: buffer_cv.buffer.id().0, + layout: convert_texture_data_layout(&buffer_cv.parent), + } +} + +pub fn convert_texture_cv(texture_cv: &GPUTextureCopyView) -> wgpu_com::TextureCopyView { + wgpu_com::TextureCopyView { + texture: texture_cv.texture.id().0, + mip_level: texture_cv.mipLevel, + origin: match texture_cv.origin { + GPUOrigin3D::RangeEnforcedUnsignedLongSequence(ref v) => { + let mut w = v.clone(); + w.resize(3, 0); + wgt::Origin3d { + x: w[0], + y: w[1], + z: w[2], + } + }, + GPUOrigin3D::GPUOrigin3DDict(ref d) => wgt::Origin3d { + x: d.x, + y: d.y, + z: d.z, + }, + }, + } +} + +pub fn convert_texture_data_layout(data_layout: &GPUTextureDataLayout) -> wgt::TextureDataLayout { + wgt::TextureDataLayout { + offset: data_layout.offset as wgt::BufferAddress, + bytes_per_row: data_layout.bytesPerRow, + rows_per_image: data_layout.rowsPerImage, + } +} diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 2a3ffad48d9..d7640b5dd37 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -1065,10 +1065,14 @@ pub fn convert_texture_size_to_dict(size: &GPUExtent3D) -> GPUExtent3DDict { height: dict.height, depth: dict.depth, }, - GPUExtent3D::RangeEnforcedUnsignedLongSequence(ref v) => GPUExtent3DDict { - width: v[0], - height: v[1], - depth: v[2], + GPUExtent3D::RangeEnforcedUnsignedLongSequence(ref v) => { + let mut w = v.clone(); + w.resize(3, 1); + GPUExtent3DDict { + width: w[0], + height: w[1], + depth: w[2], + } }, } } diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs index c2632dfce1e..e04471ebb34 100644 --- a/components/script/dom/gpuqueue.rs +++ b/components/script/dom/gpuqueue.rs @@ -4,10 +4,11 @@ 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::codegen::Bindings::GPUCommandEncoderBinding::{ + GPUTextureCopyView, GPUTextureDataLayout, }; +use crate::dom::bindings::codegen::Bindings::GPUQueueBinding::GPUQueueMethods; +use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::DomRoot; @@ -15,12 +16,13 @@ use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::gpucommandbuffer::GPUCommandBuffer; +use crate::dom::gpucommandencoder::{convert_texture_cv, convert_texture_data_layout}; use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt}; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; use js::rust::CustomAutoRooterGuard; use js::typedarray::ArrayBuffer; -use webgpu::{wgpu::command as wgpu_com, wgt, WebGPU, WebGPUQueue, WebGPURequest}; +use webgpu::{wgt, WebGPU, WebGPUQueue, WebGPURequest}; #[dom_struct] pub struct GPUQueue { @@ -135,29 +137,8 @@ impl GPUQueueMethods for GPUQueue { 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 texture_cv = convert_texture_cv(destination); + let texture_layout = convert_texture_data_layout(data_layout); let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size)); let final_data = IpcSharedMemory::from_bytes(&bytes); diff --git a/components/script/dom/webidls/GPUCommandEncoder.webidl b/components/script/dom/webidls/GPUCommandEncoder.webidl index 6892c5393af..00a8e1ad537 100644 --- a/components/script/dom/webidls/GPUCommandEncoder.webidl +++ b/components/script/dom/webidls/GPUCommandEncoder.webidl @@ -15,24 +15,33 @@ interface GPUCommandEncoder { GPUSize64 destinationOffset, GPUSize64 size); - // void copyBufferToTexture( - // GPUBufferCopyView source, - // GPUTextureCopyView destination, - // GPUExtent3D copySize); - - // void copyTextureToBuffer( - // GPUTextureCopyView source, - // GPUBufferCopyView destination, - // GPUExtent3D copySize); - - // void copyTextureToTexture( - // GPUTextureCopyView source, - // GPUTextureCopyView destination, - // GPUExtent3D copySize); - - // void pushDebugGroup(DOMString groupLabel); - // void popDebugGroup(); - // void insertDebugMarker(DOMString markerLabel); + void copyBufferToTexture( + GPUBufferCopyView source, + GPUTextureCopyView destination, + GPUExtent3D copySize); + + void copyTextureToBuffer( + GPUTextureCopyView source, + GPUBufferCopyView destination, + GPUExtent3D copySize); + + void copyTextureToTexture( + GPUTextureCopyView source, + GPUTextureCopyView destination, + GPUExtent3D copySize); + + //void pushDebugGroup(USVString groupLabel); + //void popDebugGroup(); + //void insertDebugMarker(USVString markerLabel); + + //void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); + + //void resolveQuerySet( + // GPUQuerySet querySet, + // GPUSize32 firstQuery, + // GPUSize32 queryCount, + // GPUBuffer destination, + // GPUSize64 destinationOffset); GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {}); }; @@ -88,3 +97,26 @@ dictionary GPUColorDict { required double a; }; typedef (sequence<double> or GPUColorDict) GPUColor; + +dictionary GPUTextureDataLayout { + GPUSize64 offset = 0; + required GPUSize32 bytesPerRow; + GPUSize32 rowsPerImage = 0; +}; + +dictionary GPUBufferCopyView : GPUTextureDataLayout { + required GPUBuffer buffer; +}; + +dictionary GPUTextureCopyView { + required GPUTexture texture; + GPUIntegerCoordinate mipLevel = 0; + GPUOrigin3D origin = {}; +}; + +dictionary GPUOrigin3DDict { + GPUIntegerCoordinate x = 0; + GPUIntegerCoordinate y = 0; + GPUIntegerCoordinate z = 0; +}; +typedef (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict) GPUOrigin3D; diff --git a/components/script/dom/webidls/GPUTexture.webidl b/components/script/dom/webidls/GPUTexture.webidl index 840b0f17609..1058e69d1d4 100644 --- a/components/script/dom/webidls/GPUTexture.webidl +++ b/components/script/dom/webidls/GPUTexture.webidl @@ -92,22 +92,3 @@ 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 9980f5a003a..747e25eb7be 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -81,6 +81,24 @@ pub enum WebGPURequest { destination_offset: wgt::BufferAddress, size: wgt::BufferAddress, }, + CopyBufferToTexture { + command_encoder_id: id::CommandEncoderId, + source: BufferCopyView, + destination: TextureCopyView, + copy_size: wgt::Extent3d, + }, + CopyTextureToBuffer { + command_encoder_id: id::CommandEncoderId, + source: TextureCopyView, + destination: BufferCopyView, + copy_size: wgt::Extent3d, + }, + CopyTextureToTexture { + command_encoder_id: id::CommandEncoderId, + source: TextureCopyView, + destination: TextureCopyView, + copy_size: wgt::Extent3d, + }, CreateBindGroup { device_id: id::DeviceId, // TODO: Consider using NonZeroU64 to reduce enum size @@ -454,6 +472,48 @@ impl<'a> WGPU<'a> { size )); }, + WebGPURequest::CopyBufferToTexture { + command_encoder_id, + source, + destination, + copy_size, + } => { + let global = &self.global; + let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_texture( + command_encoder_id, + &source, + &destination, + ©_size + )); + }, + WebGPURequest::CopyTextureToBuffer { + command_encoder_id, + source, + destination, + copy_size, + } => { + let global = &self.global; + let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_buffer( + command_encoder_id, + &source, + &destination, + ©_size + )); + }, + WebGPURequest::CopyTextureToTexture { + command_encoder_id, + source, + destination, + copy_size, + } => { + let global = &self.global; + let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_texture( + command_encoder_id, + &source, + &destination, + ©_size + )); + }, WebGPURequest::CreateBindGroup { device_id, scope_id, |