diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/gpubindgroup.rs | 54 | ||||
-rw-r--r-- | components/script/dom/gpubindgrouplayout.rs | 58 | ||||
-rw-r--r-- | components/script/dom/gpubuffer.rs | 53 | ||||
-rw-r--r-- | components/script/dom/gpucommandencoder.rs | 55 | ||||
-rw-r--r-- | components/script/dom/gpucomputepipeline.rs | 44 | ||||
-rw-r--r-- | components/script/dom/gpuconvert.rs | 48 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 471 | ||||
-rw-r--r-- | components/script/dom/gpupipelinelayout.rs | 52 | ||||
-rw-r--r-- | components/script/dom/gpuqueue.rs | 1 | ||||
-rw-r--r-- | components/script/dom/gpurenderbundleencoder.rs | 59 | ||||
-rw-r--r-- | components/script/dom/gpurenderpipeline.rs | 32 | ||||
-rw-r--r-- | components/script/dom/gpusampler.rs | 55 | ||||
-rw-r--r-- | components/script/dom/gpushadermodule.rs | 41 | ||||
-rw-r--r-- | components/script/dom/gputexture.rs | 57 |
14 files changed, 594 insertions, 486 deletions
diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs index 2c4fa1bd2e8..2aae7174265 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -2,16 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; + use dom_struct::dom_struct; +use webgpu::wgc::binding_model::BindGroupDescriptor; use webgpu::{WebGPU, WebGPUBindGroup, WebGPUDevice, WebGPURequest}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUBindGroupMethods; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUBindGroupDescriptor, GPUBindGroupMethods, +}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; +use crate::dom::gpuconvert::convert_label; +use crate::dom::gpudevice::GPUDevice; #[dom_struct] pub struct GPUBindGroup { @@ -66,6 +73,49 @@ impl GPUBindGroup { pub fn id(&self) -> &WebGPUBindGroup { &self.bind_group } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup> + pub fn create( + device: &GPUDevice, + descriptor: &GPUBindGroupDescriptor, + ) -> DomRoot<GPUBindGroup> { + let entries = descriptor + .entries + .iter() + .map(|bind| bind.into()) + .collect::<Vec<_>>(); + + let desc = BindGroupDescriptor { + label: convert_label(&descriptor.parent), + layout: descriptor.layout.id().0, + entries: Cow::Owned(entries), + }; + + let bind_group_id = device + .global() + .wgpu_id_hub() + .create_bind_group_id(device.id().0.backend()); + device + .channel() + .0 + .send(WebGPURequest::CreateBindGroup { + device_id: device.id().0, + bind_group_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU BindGroup"); + + let bind_group = WebGPUBindGroup(bind_group_id); + + GPUBindGroup::new( + &device.global(), + device.channel().clone(), + bind_group, + device.id(), + &descriptor.layout, + descriptor.parent.label.clone(), + ) + } } impl Drop for GPUBindGroup { diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index 2a4cb199d41..875eff8e3fc 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -2,15 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; + use dom_struct::dom_struct; +use webgpu::wgc::binding_model::BindGroupLayoutDescriptor; use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPURequest}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUBindGroupLayoutMethods; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUBindGroupLayoutDescriptor, GPUBindGroupLayoutMethods, +}; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpuconvert::{convert_bind_group_layout_entry, convert_label}; +use crate::dom::gpudevice::GPUDevice; #[dom_struct] pub struct GPUBindGroupLayout { @@ -58,6 +66,52 @@ impl GPUBindGroupLayout { pub fn id(&self) -> WebGPUBindGroupLayout { self.bind_group_layout } + + /// <https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout> + pub fn create( + device: &GPUDevice, + descriptor: &GPUBindGroupLayoutDescriptor, + ) -> Fallible<DomRoot<GPUBindGroupLayout>> { + let entries = descriptor + .entries + .iter() + .map(|bgle| convert_bind_group_layout_entry(bgle, device)) + .collect::<Fallible<Result<Vec<_>, _>>>()?; + + let desc = match entries { + Ok(entries) => Some(BindGroupLayoutDescriptor { + label: convert_label(&descriptor.parent), + entries: Cow::Owned(entries), + }), + Err(error) => { + device.dispatch_error(error); + None + }, + }; + + let bind_group_layout_id = device + .global() + .wgpu_id_hub() + .create_bind_group_layout_id(device.id().0.backend()); + device + .channel() + .0 + .send(WebGPURequest::CreateBindGroupLayout { + device_id: device.id().0, + bind_group_layout_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU BindGroupLayout"); + + let bgl = WebGPUBindGroupLayout(bind_group_layout_id); + + Ok(GPUBindGroupLayout::new( + &device.global(), + device.channel().clone(), + bgl, + descriptor.parent.label.clone(), + )) + } } impl Drop for GPUBindGroupLayout { diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index a8d8d204163..3b5631bce7c 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -14,14 +14,15 @@ use webgpu::{wgt, Mapping, WebGPU, WebGPUBuffer, WebGPURequest, WebGPUResponse}; use super::bindings::buffer_source::DataBlock; use super::bindings::codegen::Bindings::WebGPUBinding::{ - GPUBufferMapState, GPUFlagsConstant, GPUMapModeFlags, + GPUBufferDescriptor, GPUBufferMapState, GPUFlagsConstant, GPUMapModeFlags, }; +use super::gpuconvert::convert_label; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ GPUBufferMethods, GPUMapModeConstants, GPUSize64, }; use crate::dom::bindings::error::{Error, Fallible}; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; @@ -130,6 +131,54 @@ impl GPUBuffer { pub fn id(&self) -> WebGPUBuffer { self.buffer } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer> + pub fn create( + device: &GPUDevice, + descriptor: &GPUBufferDescriptor, + ) -> Fallible<DomRoot<GPUBuffer>> { + let desc = wgt::BufferDescriptor { + label: convert_label(&descriptor.parent), + size: descriptor.size as wgt::BufferAddress, + usage: wgt::BufferUsages::from_bits_retain(descriptor.usage), + mapped_at_creation: descriptor.mappedAtCreation, + }; + let id = device + .global() + .wgpu_id_hub() + .create_buffer_id(device.id().0.backend()); + + device + .channel() + .0 + .send(WebGPURequest::CreateBuffer { + device_id: device.id().0, + buffer_id: id, + descriptor: desc, + }) + .expect("Failed to create WebGPU buffer"); + + let buffer = WebGPUBuffer(id); + let mapping = if descriptor.mappedAtCreation { + Some(ActiveBufferMapping::new( + GPUMapModeConstants::WRITE, + 0..descriptor.size, + )?) + } else { + None + }; + + Ok(GPUBuffer::new( + &device.global(), + device.channel().clone(), + buffer, + device, + descriptor.size, + descriptor.usage, + mapping, + descriptor.parent.label.clone(), + )) + } } impl Drop for GPUBuffer { diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index ed37fb910e0..6b930932bb7 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -4,15 +4,18 @@ use dom_struct::dom_struct; use webgpu::wgc::command as wgpu_com; -use webgpu::wgt::Color; -use webgpu::{self, wgt, WebGPU, WebGPUComputePass, WebGPURenderPass, WebGPURequest}; +use webgpu::{ + wgt, WebGPU, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePass, WebGPUDevice, + WebGPURenderPass, WebGPURequest, +}; use super::bindings::error::Fallible; use super::gpuconvert::convert_label; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUCommandBufferDescriptor, GPUCommandEncoderMethods, GPUComputePassDescriptor, GPUExtent3D, - GPUImageCopyBuffer, GPUImageCopyTexture, GPURenderPassDescriptor, GPUSize64, + GPUCommandBufferDescriptor, GPUCommandEncoderDescriptor, GPUCommandEncoderMethods, + GPUComputePassDescriptor, GPUExtent3D, GPUImageCopyBuffer, GPUImageCopyTexture, + GPURenderPassDescriptor, GPUSize64, }; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; @@ -33,7 +36,7 @@ pub struct GPUCommandEncoder { channel: WebGPU, label: DomRefCell<USVString>, #[no_trace] - encoder: webgpu::WebGPUCommandEncoder, + encoder: WebGPUCommandEncoder, device: Dom<GPUDevice>, } @@ -41,7 +44,7 @@ impl GPUCommandEncoder { pub fn new_inherited( channel: WebGPU, device: &GPUDevice, - encoder: webgpu::WebGPUCommandEncoder, + encoder: WebGPUCommandEncoder, label: USVString, ) -> Self { Self { @@ -57,7 +60,7 @@ impl GPUCommandEncoder { global: &GlobalScope, channel: WebGPU, device: &GPUDevice, - encoder: webgpu::WebGPUCommandEncoder, + encoder: WebGPUCommandEncoder, label: USVString, ) -> DomRoot<Self> { reflect_dom_object( @@ -70,13 +73,45 @@ impl GPUCommandEncoder { } impl GPUCommandEncoder { - pub fn id(&self) -> webgpu::WebGPUCommandEncoder { + pub fn id(&self) -> WebGPUCommandEncoder { self.encoder } - pub fn device_id(&self) -> webgpu::WebGPUDevice { + pub fn device_id(&self) -> WebGPUDevice { self.device.id() } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder> + pub fn create( + device: &GPUDevice, + descriptor: &GPUCommandEncoderDescriptor, + ) -> DomRoot<GPUCommandEncoder> { + let command_encoder_id = device + .global() + .wgpu_id_hub() + .create_command_encoder_id(device.id().0.backend()); + device + .channel() + .0 + .send(WebGPURequest::CreateCommandEncoder { + device_id: device.id().0, + command_encoder_id, + desc: wgt::CommandEncoderDescriptor { + label: convert_label(&descriptor.parent), + }, + }) + .expect("Failed to create WebGPU command encoder"); + + let encoder = WebGPUCommandEncoder(command_encoder_id); + + GPUCommandEncoder::new( + &device.global(), + device.channel().clone(), + device, + encoder, + descriptor.parent.label.clone(), + ) + } } impl GPUCommandEncoderMethods for GPUCommandEncoder { @@ -283,7 +318,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { }) .expect("Failed to send Finish"); - let buffer = webgpu::WebGPUCommandBuffer(self.encoder.0.into_command_buffer_id()); + let buffer = WebGPUCommandBuffer(self.encoder.0.into_command_buffer_id()); GPUCommandBuffer::new( &self.global(), self.channel.clone(), diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs index 392f111ffa1..bf58302da52 100644 --- a/components/script/dom/gpucomputepipeline.rs +++ b/components/script/dom/gpucomputepipeline.rs @@ -3,16 +3,21 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use dom_struct::dom_struct; -use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPURequest}; +use ipc_channel::ipc::IpcSender; +use webgpu::wgc::pipeline::ComputePipelineDescriptor; +use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPUComputePipeline, WebGPURequest, WebGPUResponse}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUComputePipelineMethods; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUComputePipelineDescriptor, GPUComputePipelineMethods, +}; use crate::dom::bindings::error::Fallible; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; +use crate::dom::gpuconvert::convert_label; use crate::dom::gpudevice::GPUDevice; #[dom_struct] @@ -63,6 +68,41 @@ impl GPUComputePipeline { pub fn id(&self) -> &WebGPUComputePipeline { &self.compute_pipeline } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline> + pub fn create( + device: &GPUDevice, + descriptor: &GPUComputePipelineDescriptor, + async_sender: Option<IpcSender<WebGPUResponse>>, + ) -> WebGPUComputePipeline { + let compute_pipeline_id = device + .global() + .wgpu_id_hub() + .create_compute_pipeline_id(device.id().0.backend()); + + let (layout, implicit_ids, _) = device.get_pipeline_layout_data(&descriptor.parent.layout); + + let desc = ComputePipelineDescriptor { + label: convert_label(&descriptor.parent.parent), + layout, + stage: (&descriptor.compute).into(), + cache: None, + }; + + device + .channel() + .0 + .send(WebGPURequest::CreateComputePipeline { + device_id: device.id().0, + compute_pipeline_id, + descriptor: desc, + implicit_ids, + async_sender, + }) + .expect("Failed to create WebGPU ComputePipeline"); + + WebGPUComputePipeline(compute_pipeline_id) + } } impl GPUComputePipelineMethods for GPUComputePipeline { diff --git a/components/script/dom/gpuconvert.rs b/components/script/dom/gpuconvert.rs index acba9634787..1eb7c9fb977 100644 --- a/components/script/dom/gpuconvert.rs +++ b/components/script/dom/gpuconvert.rs @@ -5,20 +5,23 @@ use std::borrow::Cow; use std::num::NonZeroU64; +use webgpu::wgc::binding_model::{BindGroupEntry, BindingResource, BufferBinding}; use webgpu::wgc::command as wgpu_com; use webgpu::wgc::pipeline::ProgrammableStageDescriptor; use webgpu::wgt::{self, AstcBlock, AstcChannel}; -use super::bindings::codegen::Bindings::WebGPUBinding::GPUProgrammableStage; +use super::bindings::codegen::Bindings::WebGPUBinding::{ + GPUProgrammableStage, GPUTextureDimension, +}; use super::bindings::error::Error; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUAddressMode, GPUBindGroupLayoutEntry, GPUBlendComponent, GPUBlendFactor, GPUBlendOperation, - GPUBufferBindingType, GPUColor, GPUCompareFunction, GPUCullMode, GPUExtent3D, GPUFilterMode, - GPUFrontFace, GPUImageCopyBuffer, GPUImageCopyTexture, GPUImageDataLayout, GPUIndexFormat, - GPULoadOp, GPUObjectDescriptorBase, GPUOrigin3D, GPUPrimitiveState, GPUPrimitiveTopology, - GPUSamplerBindingType, GPUStencilOperation, GPUStorageTextureAccess, GPUStoreOp, - GPUTextureAspect, GPUTextureFormat, GPUTextureSampleType, GPUTextureViewDimension, - GPUVertexFormat, + GPUAddressMode, GPUBindGroupEntry, GPUBindGroupLayoutEntry, GPUBindingResource, + GPUBlendComponent, GPUBlendFactor, GPUBlendOperation, GPUBufferBindingType, GPUColor, + GPUCompareFunction, GPUCullMode, GPUExtent3D, GPUFilterMode, GPUFrontFace, GPUImageCopyBuffer, + GPUImageCopyTexture, GPUImageDataLayout, GPUIndexFormat, GPULoadOp, GPUObjectDescriptorBase, + GPUOrigin3D, GPUPrimitiveState, GPUPrimitiveTopology, GPUSamplerBindingType, + GPUStencilOperation, GPUStorageTextureAccess, GPUStoreOp, GPUTextureAspect, GPUTextureFormat, + GPUTextureSampleType, GPUTextureViewDimension, GPUVertexFormat, }; use crate::dom::bindings::error::Fallible; use crate::dom::types::GPUDevice; @@ -624,3 +627,32 @@ impl<'a> From<&GPUProgrammableStage> for ProgrammableStageDescriptor<'a> { } } } + +impl From<&GPUBindGroupEntry> for BindGroupEntry<'_> { + fn from(entry: &GPUBindGroupEntry) -> Self { + Self { + binding: entry.binding, + resource: match entry.resource { + GPUBindingResource::GPUSampler(ref s) => BindingResource::Sampler(s.id().0), + GPUBindingResource::GPUTextureView(ref t) => BindingResource::TextureView(t.id().0), + GPUBindingResource::GPUBufferBinding(ref b) => { + BindingResource::Buffer(BufferBinding { + buffer_id: b.buffer.id().0, + offset: b.offset, + size: b.size.and_then(wgt::BufferSize::new), + }) + }, + }, + } + } +} + +impl From<GPUTextureDimension> for wgt::TextureDimension { + fn from(dimension: GPUTextureDimension) -> Self { + match dimension { + GPUTextureDimension::_1d => wgt::TextureDimension::D1, + GPUTextureDimension::_2d => wgt::TextureDimension::D2, + GPUTextureDimension::_3d => wgt::TextureDimension::D3, + } + } +} diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 2a531128db4..33daf8217b9 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -11,23 +11,18 @@ use std::rc::Rc; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use webgpu::wgc::id::{BindGroupLayoutId, PipelineLayoutId}; +use webgpu::wgc::pipeline as wgpu_pipe; use webgpu::wgc::pipeline::RenderPipelineDescriptor; -use webgpu::wgc::{ - binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res, -}; -use webgpu::wgt::{BlendComponent, TextureFormat}; +use webgpu::wgt::TextureFormat; use webgpu::{ - self, wgt, PopError, WebGPU, WebGPUComputePipeline, WebGPURenderPipeline, WebGPURequest, + wgt, PopError, WebGPU, WebGPUComputePipeline, WebGPURenderPipeline, WebGPURequest, WebGPUResponse, }; -use super::bindings::codegen::Bindings::WebGPUBinding::{ - GPUMapModeConstants, GPUPipelineErrorReason, GPUTextureFormat, -}; +use super::bindings::codegen::Bindings::WebGPUBinding::{GPUPipelineErrorReason, GPUTextureFormat}; use super::bindings::codegen::UnionTypes::GPUPipelineLayoutOrGPUAutoLayoutMode; use super::bindings::error::Fallible; use super::gpu::AsyncWGPUListener; -use super::gpuconvert::convert_bind_group_layout_entry; use super::gpudevicelostinfo::GPUDeviceLostInfo; use super::gpupipelineerror::GPUPipelineError; use super::gpusupportedlimits::GPUSupportedLimits; @@ -36,12 +31,12 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit; use crate::dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUBindGroupDescriptor, GPUBindGroupLayoutDescriptor, GPUBindingResource, GPUBufferDescriptor, + GPUBindGroupDescriptor, GPUBindGroupLayoutDescriptor, GPUBufferDescriptor, GPUCommandEncoderDescriptor, GPUComputePipelineDescriptor, GPUDeviceLostReason, GPUDeviceMethods, GPUErrorFilter, GPUPipelineLayoutDescriptor, GPURenderBundleEncoderDescriptor, GPURenderPipelineDescriptor, GPUSamplerDescriptor, GPUShaderModuleDescriptor, GPUSupportedLimitsMethods, GPUTextureDescriptor, - GPUTextureDimension, GPUUncapturedErrorEventInit, GPUVertexStepMode, + GPUUncapturedErrorEventInit, GPUVertexStepMode, }; use crate::dom::bindings::error::Error; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; @@ -54,7 +49,7 @@ use crate::dom::gpu::response_async; use crate::dom::gpuadapter::GPUAdapter; use crate::dom::gpubindgroup::GPUBindGroup; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; -use crate::dom::gpubuffer::{ActiveBufferMapping, GPUBuffer}; +use crate::dom::gpubuffer::GPUBuffer; use crate::dom::gpucommandencoder::GPUCommandEncoder; use crate::dom::gpucomputepipeline::GPUComputePipeline; use crate::dom::gpuconvert::convert_label; @@ -211,7 +206,7 @@ impl GPUDevice { self.lost_promise.borrow().is_fulfilled() } - fn get_pipeline_layout_data( + pub fn get_pipeline_layout_data( &self, layout: &GPUPipelineLayoutOrGPUAutoLayoutMode, ) -> ( @@ -241,7 +236,7 @@ impl GPUDevice { } } - fn parse_render_pipeline<'a>( + pub fn parse_render_pipeline<'a>( &self, descriptor: &GPURenderPipelineDescriptor, ) -> Fallible<( @@ -401,46 +396,7 @@ impl GPUDeviceMethods for GPUDevice { /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer> fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> Fallible<DomRoot<GPUBuffer>> { - let desc = wgpu_res::BufferDescriptor { - label: convert_label(&descriptor.parent), - size: descriptor.size as wgt::BufferAddress, - usage: wgt::BufferUsages::from_bits_retain(descriptor.usage), - mapped_at_creation: descriptor.mappedAtCreation, - }; - let id = self - .global() - .wgpu_id_hub() - .create_buffer_id(self.device.0.backend()); - - self.channel - .0 - .send(WebGPURequest::CreateBuffer { - device_id: self.device.0, - buffer_id: id, - descriptor: desc, - }) - .expect("Failed to create WebGPU buffer"); - - let buffer = webgpu::WebGPUBuffer(id); - let mapping = if descriptor.mappedAtCreation { - Some(ActiveBufferMapping::new( - GPUMapModeConstants::WRITE, - 0..descriptor.size, - )?) - } else { - None - }; - - Ok(GPUBuffer::new( - &self.global(), - self.channel.clone(), - buffer, - self, - descriptor.size, - descriptor.usage, - mapping, - descriptor.parent.label.clone(), - )) + GPUBuffer::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout> @@ -449,44 +405,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUBindGroupLayoutDescriptor, ) -> Fallible<DomRoot<GPUBindGroupLayout>> { - let entries = descriptor - .entries - .iter() - .map(|bgle| convert_bind_group_layout_entry(bgle, &self)) - .collect::<Fallible<Result<Vec<_>, _>>>()?; - - let desc = match entries { - Ok(entries) => Some(wgpu_bind::BindGroupLayoutDescriptor { - label: convert_label(&descriptor.parent), - entries: Cow::Owned(entries), - }), - Err(error) => { - self.dispatch_error(error); - None - }, - }; - - let bind_group_layout_id = self - .global() - .wgpu_id_hub() - .create_bind_group_layout_id(self.device.0.backend()); - self.channel - .0 - .send(WebGPURequest::CreateBindGroupLayout { - device_id: self.device.0, - bind_group_layout_id, - descriptor: desc, - }) - .expect("Failed to create WebGPU BindGroupLayout"); - - let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); - - Ok(GPUBindGroupLayout::new( - &self.global(), - self.channel.clone(), - bgl, - descriptor.parent.label.clone(), - )) + GPUBindGroupLayout::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout> @@ -494,100 +413,12 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUPipelineLayoutDescriptor, ) -> DomRoot<GPUPipelineLayout> { - let desc = wgpu_bind::PipelineLayoutDescriptor { - label: convert_label(&descriptor.parent), - bind_group_layouts: Cow::Owned( - descriptor - .bindGroupLayouts - .iter() - .map(|each| each.id().0) - .collect::<Vec<_>>(), - ), - push_constant_ranges: Cow::Owned(vec![]), - }; - - let pipeline_layout_id = self - .global() - .wgpu_id_hub() - .create_pipeline_layout_id(self.device.0.backend()); - self.channel - .0 - .send(WebGPURequest::CreatePipelineLayout { - device_id: self.device.0, - pipeline_layout_id, - descriptor: desc, - }) - .expect("Failed to create WebGPU PipelineLayout"); - - let bgls = descriptor - .bindGroupLayouts - .iter() - .map(|each| each.id()) - .collect::<Vec<_>>(); - let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id); - GPUPipelineLayout::new( - &self.global(), - self.channel.clone(), - pipeline_layout, - descriptor.parent.label.clone(), - bgls, - ) + GPUPipelineLayout::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup> fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot<GPUBindGroup> { - let entries = descriptor - .entries - .iter() - .map(|bind| wgpu_bind::BindGroupEntry { - binding: bind.binding, - resource: match bind.resource { - GPUBindingResource::GPUSampler(ref s) => { - wgpu_bind::BindingResource::Sampler(s.id().0) - }, - GPUBindingResource::GPUTextureView(ref t) => { - wgpu_bind::BindingResource::TextureView(t.id().0) - }, - GPUBindingResource::GPUBufferBinding(ref b) => { - wgpu_bind::BindingResource::Buffer(wgpu_bind::BufferBinding { - buffer_id: b.buffer.id().0, - offset: b.offset, - size: b.size.and_then(wgt::BufferSize::new), - }) - }, - }, - }) - .collect::<Vec<_>>(); - - let desc = wgpu_bind::BindGroupDescriptor { - label: convert_label(&descriptor.parent), - layout: descriptor.layout.id().0, - entries: Cow::Owned(entries), - }; - - let bind_group_id = self - .global() - .wgpu_id_hub() - .create_bind_group_id(self.device.0.backend()); - self.channel - .0 - .send(WebGPURequest::CreateBindGroup { - device_id: self.device.0, - bind_group_id, - descriptor: desc, - }) - .expect("Failed to create WebGPU BindGroup"); - - let bind_group = webgpu::WebGPUBindGroup(bind_group_id); - - GPUBindGroup::new( - &self.global(), - self.channel.clone(), - bind_group, - self.device, - &descriptor.layout, - descriptor.parent.label.clone(), - ) + GPUBindGroup::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule> @@ -596,30 +427,7 @@ impl GPUDeviceMethods for GPUDevice { descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>, comp: InRealm, ) -> DomRoot<GPUShaderModule> { - let program_id = self - .global() - .wgpu_id_hub() - .create_shader_module_id(self.device.0.backend()); - let promise = Promise::new_in_current_realm(comp); - let shader_module = GPUShaderModule::new( - &self.global(), - self.channel.clone(), - webgpu::WebGPUShaderModule(program_id), - descriptor.parent.label.clone(), - promise.clone(), - ); - let sender = response_async(&promise, &*shader_module); - self.channel - .0 - .send(WebGPURequest::CreateShaderModule { - device_id: self.device.0, - program_id, - program: descriptor.code.0.clone(), - label: None, - sender, - }) - .expect("Failed to create WebGPU ShaderModule"); - shader_module + GPUShaderModule::create(self, descriptor, comp) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline> @@ -627,32 +435,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUComputePipelineDescriptor, ) -> DomRoot<GPUComputePipeline> { - let compute_pipeline_id = self - .global() - .wgpu_id_hub() - .create_compute_pipeline_id(self.device.0.backend()); - - let (layout, implicit_ids, _) = self.get_pipeline_layout_data(&descriptor.parent.layout); - - let desc = wgpu_pipe::ComputePipelineDescriptor { - label: convert_label(&descriptor.parent.parent), - layout, - stage: (&descriptor.compute).into(), - cache: None, - }; - - self.channel - .0 - .send(WebGPURequest::CreateComputePipeline { - device_id: self.device.0, - compute_pipeline_id, - descriptor: desc, - implicit_ids, - async_sender: None, - }) - .expect("Failed to create WebGPU ComputePipeline"); - - let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); + let compute_pipeline = GPUComputePipeline::create(self, descriptor, None); GPUComputePipeline::new( &self.global(), compute_pipeline, @@ -669,30 +452,7 @@ impl GPUDeviceMethods for GPUDevice { ) -> Rc<Promise> { let promise = Promise::new_in_current_realm(comp); let sender = response_async(&promise, self); - let compute_pipeline_id = self - .global() - .wgpu_id_hub() - .create_compute_pipeline_id(self.device.0.backend()); - - let (layout, implicit_ids, _) = self.get_pipeline_layout_data(&descriptor.parent.layout); - - let desc = wgpu_pipe::ComputePipelineDescriptor { - label: convert_label(&descriptor.parent.parent), - layout, - stage: (&descriptor.compute).into(), - cache: None, - }; - - self.channel - .0 - .send(WebGPURequest::CreateComputePipeline { - device_id: self.device.0, - compute_pipeline_id, - descriptor: desc, - implicit_ids, - async_sender: Some(sender), - }) - .expect("Failed to create WebGPU ComputePipeline"); + GPUComputePipeline::create(self, descriptor, Some(sender)); promise } @@ -701,130 +461,17 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUCommandEncoderDescriptor, ) -> DomRoot<GPUCommandEncoder> { - let command_encoder_id = self - .global() - .wgpu_id_hub() - .create_command_encoder_id(self.device.0.backend()); - self.channel - .0 - .send(WebGPURequest::CreateCommandEncoder { - device_id: self.device.0, - command_encoder_id, - desc: wgt::CommandEncoderDescriptor { - label: convert_label(&descriptor.parent), - }, - }) - .expect("Failed to create WebGPU command encoder"); - - let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id); - - GPUCommandEncoder::new( - &self.global(), - self.channel.clone(), - self, - encoder, - descriptor.parent.label.clone(), - ) + GPUCommandEncoder::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture> fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> Fallible<DomRoot<GPUTexture>> { - let size = (&descriptor.size).try_into()?; - let desc = wgpu_res::TextureDescriptor { - label: convert_label(&descriptor.parent), - size, - mip_level_count: descriptor.mipLevelCount, - sample_count: descriptor.sampleCount, - dimension: match descriptor.dimension { - GPUTextureDimension::_1d => wgt::TextureDimension::D1, - GPUTextureDimension::_2d => wgt::TextureDimension::D2, - GPUTextureDimension::_3d => wgt::TextureDimension::D3, - }, - format: self.validate_texture_format_required_features(&descriptor.format)?, - usage: wgt::TextureUsages::from_bits_retain(descriptor.usage), - view_formats: descriptor - .viewFormats - .iter() - .map(|tf| self.validate_texture_format_required_features(tf)) - .collect::<Fallible<_>>()?, - }; - - let texture_id = self - .global() - .wgpu_id_hub() - .create_texture_id(self.device.0.backend()); - - self.channel - .0 - .send(WebGPURequest::CreateTexture { - device_id: self.device.0, - texture_id, - descriptor: desc, - }) - .expect("Failed to create WebGPU Texture"); - - let texture = webgpu::WebGPUTexture(texture_id); - - Ok(GPUTexture::new( - &self.global(), - texture, - self, - self.channel.clone(), - size, - descriptor.mipLevelCount, - descriptor.sampleCount, - descriptor.dimension, - descriptor.format, - descriptor.usage, - descriptor.parent.label.clone(), - )) + GPUTexture::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler> fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> { - let sampler_id = self - .global() - .wgpu_id_hub() - .create_sampler_id(self.device.0.backend()); - let compare_enable = descriptor.compare.is_some(); - let desc = wgpu_res::SamplerDescriptor { - label: convert_label(&descriptor.parent), - address_modes: [ - descriptor.addressModeU.into(), - descriptor.addressModeV.into(), - descriptor.addressModeW.into(), - ], - mag_filter: descriptor.magFilter.into(), - min_filter: descriptor.minFilter.into(), - mipmap_filter: descriptor.mipmapFilter.into(), - lod_min_clamp: *descriptor.lodMinClamp, - lod_max_clamp: *descriptor.lodMaxClamp, - compare: descriptor - .compare - .map(|gpu_compare_function| gpu_compare_function.into()), - anisotropy_clamp: 1, - border_color: None, - }; - - self.channel - .0 - .send(WebGPURequest::CreateSampler { - device_id: self.device.0, - sampler_id, - descriptor: desc, - }) - .expect("Failed to create WebGPU sampler"); - - let sampler = webgpu::WebGPUSampler(sampler_id); - - GPUSampler::new( - &self.global(), - self.channel.clone(), - self.device, - compare_enable, - sampler, - descriptor.parent.label.clone(), - ) + GPUSampler::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline> @@ -833,25 +480,7 @@ impl GPUDeviceMethods for GPUDevice { descriptor: &GPURenderPipelineDescriptor, ) -> Fallible<DomRoot<GPURenderPipeline>> { let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor)?; - - let render_pipeline_id = self - .global() - .wgpu_id_hub() - .create_render_pipeline_id(self.device.0.backend()); - - self.channel - .0 - .send(WebGPURequest::CreateRenderPipeline { - device_id: self.device.0, - render_pipeline_id, - descriptor: desc, - implicit_ids, - async_sender: None, - }) - .expect("Failed to create WebGPU render pipeline"); - - let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); - + let render_pipeline = GPURenderPipeline::create(self, implicit_ids, desc, None)?; Ok(GPURenderPipeline::new( &self.global(), render_pipeline, @@ -867,26 +496,9 @@ impl GPUDeviceMethods for GPUDevice { comp: InRealm, ) -> Fallible<Rc<Promise>> { let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor)?; - let promise = Promise::new_in_current_realm(comp); let sender = response_async(&promise, self); - - let render_pipeline_id = self - .global() - .wgpu_id_hub() - .create_render_pipeline_id(self.device.0.backend()); - - self.channel - .0 - .send(WebGPURequest::CreateRenderPipeline { - device_id: self.device.0, - render_pipeline_id, - descriptor: desc, - implicit_ids, - async_sender: Some(sender), - }) - .expect("Failed to create WebGPU render pipeline"); - + GPURenderPipeline::create(self, implicit_ids, desc, Some(sender))?; Ok(promise) } @@ -895,46 +507,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPURenderBundleEncoderDescriptor, ) -> Fallible<DomRoot<GPURenderBundleEncoder>> { - let desc = wgpu_com::RenderBundleEncoderDescriptor { - label: convert_label(&descriptor.parent.parent), - color_formats: Cow::Owned( - descriptor - .parent - .colorFormats - .iter() - .map(|format| { - self.validate_texture_format_required_features(format) - .map(|f| Some(f)) - }) - .collect::<Fallible<Vec<_>>>()?, - ), - depth_stencil: descriptor - .parent - .depthStencilFormat - .map(|dsf| { - self.validate_texture_format_required_features(&dsf) - .map(|format| wgt::RenderBundleDepthStencil { - format, - depth_read_only: descriptor.depthReadOnly, - stencil_read_only: descriptor.stencilReadOnly, - }) - }) - .transpose()?, - sample_count: descriptor.parent.sampleCount, - multiview: None, - }; - - // Handle error gracefully - let render_bundle_encoder = - wgpu_com::RenderBundleEncoder::new(&desc, self.device.0, None).unwrap(); - - Ok(GPURenderBundleEncoder::new( - &self.global(), - render_bundle_encoder, - self, - self.channel.clone(), - descriptor.parent.parent.label.clone(), - )) + GPURenderBundleEncoder::create(self, descriptor) } /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope> diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index c2554f3b882..00d7e4a0cec 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -2,15 +2,22 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; + use dom_struct::dom_struct; +use webgpu::wgc::binding_model::PipelineLayoutDescriptor; use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPUPipelineLayout, WebGPURequest}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUPipelineLayoutMethods; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUPipelineLayoutDescriptor, GPUPipelineLayoutMethods, +}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpuconvert::convert_label; +use crate::dom::gpudevice::GPUDevice; #[dom_struct] pub struct GPUPipelineLayout { @@ -68,6 +75,47 @@ impl GPUPipelineLayout { pub fn bind_group_layouts(&self) -> Vec<WebGPUBindGroupLayout> { self.bind_group_layouts.clone() } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout> + pub fn create( + device: &GPUDevice, + descriptor: &GPUPipelineLayoutDescriptor, + ) -> DomRoot<GPUPipelineLayout> { + let bgls = descriptor + .bindGroupLayouts + .iter() + .map(|each| each.id()) + .collect::<Vec<_>>(); + + let desc = PipelineLayoutDescriptor { + label: convert_label(&descriptor.parent), + bind_group_layouts: Cow::Owned(bgls.iter().map(|l| l.0).collect::<Vec<_>>()), + push_constant_ranges: Cow::Owned(vec![]), + }; + + let pipeline_layout_id = device + .global() + .wgpu_id_hub() + .create_pipeline_layout_id(device.id().0.backend()); + device + .channel() + .0 + .send(WebGPURequest::CreatePipelineLayout { + device_id: device.id().0, + pipeline_layout_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU PipelineLayout"); + + let pipeline_layout = WebGPUPipelineLayout(pipeline_layout_id); + GPUPipelineLayout::new( + &device.global(), + device.channel().clone(), + pipeline_layout, + descriptor.parent.label.clone(), + bgls, + ) + } } impl GPUPipelineLayoutMethods for GPUPipelineLayout { diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs index 76ef9d5b475..a82e68dcf8f 100644 --- a/components/script/dom/gpuqueue.rs +++ b/components/script/dom/gpuqueue.rs @@ -6,7 +6,6 @@ use std::rc::Rc; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSharedMemory; -use webgpu::wgt::Extent3d; use webgpu::{wgt, WebGPU, WebGPUQueue, WebGPURequest, WebGPUResponse}; use super::bindings::codegen::Bindings::WebGPUBinding::{GPUImageCopyTexture, GPUImageDataLayout}; diff --git a/components/script/dom/gpurenderbundleencoder.rs b/components/script/dom/gpurenderbundleencoder.rs index 2a4d8c7bfaa..483e3e5ef32 100644 --- a/components/script/dom/gpurenderbundleencoder.rs +++ b/components/script/dom/gpurenderbundleencoder.rs @@ -2,15 +2,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; + use dom_struct::dom_struct; -use webgpu::wgc::command::{bundle_ffi as wgpu_bundle, RenderBundleEncoder}; +use webgpu::wgc::command::{ + bundle_ffi as wgpu_bundle, RenderBundleEncoder, RenderBundleEncoderDescriptor, +}; use webgpu::{wgt, WebGPU, WebGPURenderBundle, WebGPURequest}; use super::bindings::codegen::Bindings::WebGPUBinding::GPUIndexFormat; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPURenderBundleDescriptor, GPURenderBundleEncoderMethods, + GPURenderBundleDescriptor, GPURenderBundleEncoderDescriptor, GPURenderBundleEncoderMethods, }; +use crate::dom::bindings::import::module::Fallible; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::USVString; @@ -70,6 +75,56 @@ impl GPURenderBundleEncoder { } } +impl GPURenderBundleEncoder { + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderbundleencoder> + pub fn create( + device: &GPUDevice, + descriptor: &GPURenderBundleEncoderDescriptor, + ) -> Fallible<DomRoot<GPURenderBundleEncoder>> { + let desc = RenderBundleEncoderDescriptor { + label: convert_label(&descriptor.parent.parent), + color_formats: Cow::Owned( + descriptor + .parent + .colorFormats + .iter() + .map(|format| { + device + .validate_texture_format_required_features(format) + .map(|f| Some(f)) + }) + .collect::<Fallible<Vec<_>>>()?, + ), + depth_stencil: descriptor + .parent + .depthStencilFormat + .map(|dsf| { + device + .validate_texture_format_required_features(&dsf) + .map(|format| wgt::RenderBundleDepthStencil { + format, + depth_read_only: descriptor.depthReadOnly, + stencil_read_only: descriptor.stencilReadOnly, + }) + }) + .transpose()?, + sample_count: descriptor.parent.sampleCount, + multiview: None, + }; + + // Handle error gracefully + let render_bundle_encoder = RenderBundleEncoder::new(&desc, device.id().0, None).unwrap(); + + Ok(GPURenderBundleEncoder::new( + &device.global(), + render_bundle_encoder, + device, + device.channel().clone(), + descriptor.parent.parent.label.clone(), + )) + } +} + impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder { /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label> fn Label(&self) -> USVString { diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs index 9b4e64198ab..c0e9506835b 100644 --- a/components/script/dom/gpurenderpipeline.rs +++ b/components/script/dom/gpurenderpipeline.rs @@ -3,7 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use dom_struct::dom_struct; -use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPURenderPipeline, WebGPURequest}; +use ipc_channel::ipc::IpcSender; +use webgpu::wgc::id::{BindGroupLayoutId, PipelineLayoutId}; +use webgpu::wgc::pipeline::RenderPipelineDescriptor; +use webgpu::{WebGPU, WebGPUBindGroupLayout, WebGPURenderPipeline, WebGPURequest, WebGPUResponse}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPURenderPipelineMethods; @@ -63,6 +66,33 @@ impl GPURenderPipeline { pub fn id(&self) -> WebGPURenderPipeline { self.render_pipeline } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline> + pub fn create( + device: &GPUDevice, + implicit_ids: Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>, + descriptor: RenderPipelineDescriptor<'static>, + async_sender: Option<IpcSender<WebGPUResponse>>, + ) -> Fallible<WebGPURenderPipeline> { + let render_pipeline_id = device + .global() + .wgpu_id_hub() + .create_render_pipeline_id(device.id().0.backend()); + + device + .channel() + .0 + .send(WebGPURequest::CreateRenderPipeline { + device_id: device.id().0, + render_pipeline_id, + descriptor, + implicit_ids, + async_sender, + }) + .expect("Failed to create WebGPU render pipeline"); + + Ok(WebGPURenderPipeline(render_pipeline_id)) + } } impl GPURenderPipelineMethods for GPURenderPipeline { diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs index 5a7ce54814d..874d907e069 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -3,14 +3,19 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use dom_struct::dom_struct; +use webgpu::wgc::resource::SamplerDescriptor; use webgpu::{WebGPU, WebGPUDevice, WebGPURequest, WebGPUSampler}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUSamplerMethods; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUSamplerDescriptor, GPUSamplerMethods, +}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpuconvert::convert_label; +use crate::dom::gpudevice::GPUDevice; #[dom_struct] pub struct GPUSampler { @@ -69,6 +74,52 @@ impl GPUSampler { pub fn id(&self) -> WebGPUSampler { self.sampler } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler> + pub fn create(device: &GPUDevice, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> { + let sampler_id = device + .global() + .wgpu_id_hub() + .create_sampler_id(device.id().0.backend()); + let compare_enable = descriptor.compare.is_some(); + let desc = SamplerDescriptor { + label: convert_label(&descriptor.parent), + address_modes: [ + descriptor.addressModeU.into(), + descriptor.addressModeV.into(), + descriptor.addressModeW.into(), + ], + mag_filter: descriptor.magFilter.into(), + min_filter: descriptor.minFilter.into(), + mipmap_filter: descriptor.mipmapFilter.into(), + lod_min_clamp: *descriptor.lodMinClamp, + lod_max_clamp: *descriptor.lodMaxClamp, + compare: descriptor.compare.map(Into::into), + anisotropy_clamp: 1, + border_color: None, + }; + + device + .channel() + .0 + .send(WebGPURequest::CreateSampler { + device_id: device.id().0, + sampler_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU sampler"); + + let sampler = WebGPUSampler(sampler_id); + + GPUSampler::new( + &device.global(), + device.channel().clone(), + device.id(), + compare_enable, + sampler, + descriptor.parent.label.clone(), + ) + } } impl GPUSamplerMethods for GPUSampler { diff --git a/components/script/dom/gpushadermodule.rs b/components/script/dom/gpushadermodule.rs index f7af6360673..f245765b36a 100644 --- a/components/script/dom/gpushadermodule.rs +++ b/components/script/dom/gpushadermodule.rs @@ -10,12 +10,18 @@ use webgpu::{WebGPU, WebGPURequest, WebGPUResponse, WebGPUShaderModule}; use super::gpu::AsyncWGPUListener; use super::gpucompilationinfo::GPUCompilationInfo; use super::promise::Promise; +use super::types::GPUDevice; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUShaderModuleMethods; +use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ + GPUShaderModuleDescriptor, GPUShaderModuleMethods, +}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::USVString; +use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpu::response_async; +use crate::realms::InRealm; #[dom_struct] pub struct GPUShaderModule { @@ -69,6 +75,39 @@ impl GPUShaderModule { pub fn id(&self) -> WebGPUShaderModule { self.shader_module } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule> + pub fn create( + device: &GPUDevice, + descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>, + comp: InRealm, + ) -> DomRoot<GPUShaderModule> { + let program_id = device + .global() + .wgpu_id_hub() + .create_shader_module_id(device.id().0.backend()); + let promise = Promise::new_in_current_realm(comp); + let shader_module = GPUShaderModule::new( + &device.global(), + device.channel().clone(), + WebGPUShaderModule(program_id), + descriptor.parent.label.clone(), + promise.clone(), + ); + let sender = response_async(&promise, &*shader_module); + device + .channel() + .0 + .send(WebGPURequest::CreateShaderModule { + device_id: device.id().0, + program_id, + program: descriptor.code.0.clone(), + label: None, + sender, + }) + .expect("Failed to create WebGPU ShaderModule"); + shader_module + } } impl GPUShaderModuleMethods for GPUShaderModule { diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index af063b8ae3d..7f0d64e9336 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -12,8 +12,8 @@ use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView}; use super::bindings::error::Fallible; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ - GPUTextureAspect, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods, - GPUTextureViewDescriptor, + GPUTextureAspect, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat, + GPUTextureMethods, GPUTextureViewDescriptor, }; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; @@ -128,6 +128,59 @@ impl GPUTexture { pub fn id(&self) -> WebGPUTexture { self.texture } + + /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture> + pub fn create( + device: &GPUDevice, + descriptor: &GPUTextureDescriptor, + ) -> Fallible<DomRoot<GPUTexture>> { + let size = (&descriptor.size).try_into()?; + let desc = wgt::TextureDescriptor { + label: convert_label(&descriptor.parent), + size, + mip_level_count: descriptor.mipLevelCount, + sample_count: descriptor.sampleCount, + dimension: descriptor.dimension.into(), + format: device.validate_texture_format_required_features(&descriptor.format)?, + usage: wgt::TextureUsages::from_bits_retain(descriptor.usage), + view_formats: descriptor + .viewFormats + .iter() + .map(|tf| device.validate_texture_format_required_features(tf)) + .collect::<Fallible<_>>()?, + }; + + let texture_id = device + .global() + .wgpu_id_hub() + .create_texture_id(device.id().0.backend()); + + device + .channel() + .0 + .send(WebGPURequest::CreateTexture { + device_id: device.id().0, + texture_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU Texture"); + + let texture = WebGPUTexture(texture_id); + + Ok(GPUTexture::new( + &device.global(), + texture, + device, + device.channel().clone(), + size, + descriptor.mipLevelCount, + descriptor.sampleCount, + descriptor.dimension, + descriptor.format, + descriptor.usage, + descriptor.parent.label.clone(), + )) + } } impl GPUTextureMethods for GPUTexture { |