diff options
author | Kunal Mohan <kunalmohan99@gmail.com> | 2020-07-21 16:16:12 +0530 |
---|---|---|
committer | Kunal Mohan <kunalmohan99@gmail.com> | 2020-07-21 21:00:23 +0530 |
commit | 5285c07f1f00bba0a10b3a91d35b806d2bf73e93 (patch) | |
tree | cb8361db9aaa44de6b61f0560b8980f2e0930db0 /components/script/dom/gpucommandencoder.rs | |
parent | 132d8b46014eb3a1db7721b603d5b994c95e8d5e (diff) | |
download | servo-5285c07f1f00bba0a10b3a91d35b806d2bf73e93.tar.gz servo-5285c07f1f00bba0a10b3a91d35b806d2bf73e93.zip |
Implement GPUCommandEncoder.copy commands
Diffstat (limited to 'components/script/dom/gpucommandencoder.rs')
-rw-r--r-- | components/script/dom/gpucommandencoder.rs | 200 |
1 files changed, 166 insertions, 34 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, + } +} |