diff options
Diffstat (limited to 'components/shared/webgpu')
-rw-r--r-- | components/shared/webgpu/Cargo.toml | 22 | ||||
-rw-r--r-- | components/shared/webgpu/error.rs | 97 | ||||
-rw-r--r-- | components/shared/webgpu/ids.rs | 53 | ||||
-rw-r--r-- | components/shared/webgpu/lib.rs | 144 | ||||
-rw-r--r-- | components/shared/webgpu/messages/mod.rs | 11 | ||||
-rw-r--r-- | components/shared/webgpu/messages/recv.rs | 338 | ||||
-rw-r--r-- | components/shared/webgpu/messages/to_dom.rs | 16 | ||||
-rw-r--r-- | components/shared/webgpu/messages/to_script.rs | 54 | ||||
-rw-r--r-- | components/shared/webgpu/render_commands.rs | 155 |
9 files changed, 890 insertions, 0 deletions
diff --git a/components/shared/webgpu/Cargo.toml b/components/shared/webgpu/Cargo.toml new file mode 100644 index 00000000000..8b38af1fa6d --- /dev/null +++ b/components/shared/webgpu/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "webgpu_traits" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +publish.workspace = true +rust-version.workspace = true + +[lib] +name = "webgpu_traits" +path = "lib.rs" + +[dependencies] +arrayvec = { workspace = true } +base = { workspace = true } +ipc-channel = { workspace = true } +malloc_size_of = { workspace = true } +serde = { workspace = true } +webrender_api = { workspace = true } +wgpu-core = { workspace = true } +wgpu-types = { workspace = true } diff --git a/components/shared/webgpu/error.rs b/components/shared/webgpu/error.rs new file mode 100644 index 00000000000..4669a605840 --- /dev/null +++ b/components/shared/webgpu/error.rs @@ -0,0 +1,97 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +//! Error scopes and GPUError types + +use std::fmt; + +use serde::{Deserialize, Serialize}; +use wgpu_core::device::DeviceError; + +/// <https://www.w3.org/TR/webgpu/#gpu-error-scope> +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct ErrorScope { + pub errors: Vec<Error>, + pub filter: ErrorFilter, +} + +impl ErrorScope { + pub fn new(filter: ErrorFilter) -> Self { + Self { + filter, + errors: Vec::new(), + } + } +} + +/// <https://www.w3.org/TR/webgpu/#enumdef-gpuerrorfilter> +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub enum ErrorFilter { + Validation, + OutOfMemory, + Internal, +} + +/// <https://www.w3.org/TR/webgpu/#gpuerror> +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub enum Error { + Validation(String), + OutOfMemory(String), + Internal(String), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.message()) + } +} + +impl Error { + pub fn filter(&self) -> ErrorFilter { + match self { + Error::Validation(_) => ErrorFilter::Validation, + Error::OutOfMemory(_) => ErrorFilter::OutOfMemory, + Error::Internal(_) => ErrorFilter::Internal, + } + } + + pub fn message(&self) -> &str { + match self { + Error::Validation(m) => m, + Error::OutOfMemory(m) => m, + Error::Internal(m) => m, + } + } + + // TODO: labels + // based on https://github.com/gfx-rs/wgpu/blob/trunk/wgpu/src/backend/wgpu_core.rs#L289 + pub fn from_error<E: std::error::Error + 'static>(error: E) -> Self { + let mut source_opt: Option<&(dyn std::error::Error + 'static)> = Some(&error); + while let Some(source) = source_opt { + if let Some(DeviceError::OutOfMemory) = source.downcast_ref::<DeviceError>() { + return Self::OutOfMemory(error.to_string()); + } + source_opt = source.source(); + } + // TODO: This hack is needed because there are + // multiple OutOfMemory error variant in wgpu-core + // and even upstream does not handle them correctly + if format!("{error:?}").contains("OutOfMemory") { + return Self::OutOfMemory(error.to_string()); + } + Self::Validation(error.to_string()) + } +} + +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub enum PopError { + Lost, + Empty, +} diff --git a/components/shared/webgpu/ids.rs b/components/shared/webgpu/ids.rs new file mode 100644 index 00000000000..28f2d1c24af --- /dev/null +++ b/components/shared/webgpu/ids.rs @@ -0,0 +1,53 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; +use serde::{Deserialize, Serialize}; +pub use wgpu_core::id::markers::{ + ComputePassEncoder as ComputePass, RenderPassEncoder as RenderPass, +}; +use wgpu_core::id::{ + AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, CommandEncoderId, + ComputePipelineId, DeviceId, PipelineLayoutId, QueueId, RenderBundleId, RenderPipelineId, + SamplerId, ShaderModuleId, SurfaceId, TextureId, TextureViewId, +}; +pub use wgpu_core::id::{ + ComputePassEncoderId as ComputePassId, RenderPassEncoderId as RenderPassId, +}; + +macro_rules! webgpu_resource { + ($name:ident, $id:ty) => { + #[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, PartialOrd, Serialize)] + pub struct $name(pub $id); + + impl MallocSizeOf for $name { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } + } + + impl Eq for $name {} + }; +} + +webgpu_resource!(WebGPUAdapter, AdapterId); +webgpu_resource!(WebGPUBindGroup, BindGroupId); +webgpu_resource!(WebGPUBindGroupLayout, BindGroupLayoutId); +webgpu_resource!(WebGPUBuffer, BufferId); +webgpu_resource!(WebGPUCommandBuffer, CommandBufferId); +webgpu_resource!(WebGPUCommandEncoder, CommandEncoderId); +webgpu_resource!(WebGPUComputePipeline, ComputePipelineId); +webgpu_resource!(WebGPUDevice, DeviceId); +webgpu_resource!(WebGPUPipelineLayout, PipelineLayoutId); +webgpu_resource!(WebGPUQueue, QueueId); +webgpu_resource!(WebGPURenderBundle, RenderBundleId); +webgpu_resource!(WebGPURenderPipeline, RenderPipelineId); +webgpu_resource!(WebGPUSampler, SamplerId); +webgpu_resource!(WebGPUShaderModule, ShaderModuleId); +webgpu_resource!(WebGPUSurface, SurfaceId); +webgpu_resource!(WebGPUTexture, TextureId); +webgpu_resource!(WebGPUTextureView, TextureViewId); +webgpu_resource!(WebGPUComputePass, ComputePassId); +webgpu_resource!(WebGPURenderPass, RenderPassId); +webgpu_resource!(WebGPUContextId, u64); diff --git a/components/shared/webgpu/lib.rs b/components/shared/webgpu/lib.rs new file mode 100644 index 00000000000..c33afc0b734 --- /dev/null +++ b/components/shared/webgpu/lib.rs @@ -0,0 +1,144 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +pub mod error; +pub mod ids; +pub mod messages; +pub mod render_commands; + +use std::ops::Range; + +use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; +use serde::{Deserialize, Serialize}; +use webrender_api::ImageFormat; +use wgpu_core::device::HostMap; +pub use wgpu_core::id::markers::{ + ComputePassEncoder as ComputePass, RenderPassEncoder as RenderPass, +}; +pub use wgpu_core::id::{ + ComputePassEncoderId as ComputePassId, RenderPassEncoderId as RenderPassId, +}; +use wgpu_core::id::{ComputePipelineId, DeviceId, QueueId, RenderPipelineId}; +use wgpu_core::instance::{RequestAdapterError, RequestDeviceError}; +use wgpu_core::pipeline::CreateShaderModuleError; +use wgpu_types::{AdapterInfo, DeviceDescriptor, Features, Limits, TextureFormat}; + +pub use crate::error::*; +pub use crate::ids::*; +pub use crate::messages::*; +pub use crate::render_commands::*; + +pub const PRESENTATION_BUFFER_COUNT: usize = 10; + +pub type WebGPUAdapterResponse = Option<Result<Adapter, RequestAdapterError>>; +pub type WebGPUComputePipelineResponse = Result<Pipeline<ComputePipelineId>, Error>; +pub type WebGPUPoppedErrorScopeResponse = Result<Option<Error>, PopError>; +pub type WebGPURenderPipelineResponse = Result<Pipeline<RenderPipelineId>, Error>; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct WebGPU(pub IpcSender<WebGPURequest>); + +impl WebGPU { + pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> { + self.0 + .send(WebGPURequest::Exit(sender)) + .map_err(|_| "Failed to send Exit message") + } +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct Adapter { + pub adapter_info: AdapterInfo, + pub adapter_id: WebGPUAdapter, + pub features: Features, + pub limits: Limits, + pub channel: WebGPU, +} + +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub struct ContextConfiguration { + pub device_id: DeviceId, + pub queue_id: QueueId, + pub format: TextureFormat, + pub is_opaque: bool, +} + +impl ContextConfiguration { + pub fn format(&self) -> ImageFormat { + match self.format { + TextureFormat::Rgba8Unorm => ImageFormat::RGBA8, + TextureFormat::Bgra8Unorm => ImageFormat::BGRA8, + // TODO: wgt::TextureFormat::Rgba16Float + _ => unreachable!("Unsupported canvas context format in configuration"), + } + } +} + +/// <https://gpuweb.github.io/gpuweb/#enumdef-gpudevicelostreason> +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub enum DeviceLostReason { + Unknown, + Destroyed, +} + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct ShaderCompilationInfo { + pub line_number: u64, + pub line_pos: u64, + pub offset: u64, + pub length: u64, + pub message: String, +} + +impl ShaderCompilationInfo { + pub fn from(error: &CreateShaderModuleError, source: &str) -> Self { + let location = match error { + CreateShaderModuleError::Parsing(e) => e.inner.location(source), + CreateShaderModuleError::Validation(e) => e.inner.location(source), + _ => None, + }; + + if let Some(location) = location { + // Naga reports locations in UTF-8 code units, but spec requires location in UTF-16 code units + // Based on https://searchfox.org/mozilla-central/rev/5b037d9c6ecdb0729f39ad519f0b867d80a92aad/gfx/wgpu_bindings/src/server.rs#353 + fn len_utf16(s: &str) -> u64 { + s.chars().map(|c| c.len_utf16() as u64).sum() + } + let start = location.offset as usize; + let end = start + location.length as usize; + let line_start = source[0..start].rfind('\n').map(|pos| pos + 1).unwrap_or(0); + Self { + line_number: location.line_number as u64, + line_pos: len_utf16(&source[line_start..start]) + 1, + offset: len_utf16(&source[0..start]), + length: len_utf16(&source[start..end]), + message: error.to_string(), + } + } else { + Self { + message: error.to_string(), + ..Default::default() + } + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct Pipeline<T: std::fmt::Debug + Serialize> { + pub id: T, + pub label: String, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct Mapping { + pub data: IpcSharedMemory, + pub mode: HostMap, + pub range: Range<u64>, +} + +pub type WebGPUDeviceResponse = ( + WebGPUDevice, + WebGPUQueue, + Result<DeviceDescriptor<Option<String>>, RequestDeviceError>, +); diff --git a/components/shared/webgpu/messages/mod.rs b/components/shared/webgpu/messages/mod.rs new file mode 100644 index 00000000000..47fa26161f7 --- /dev/null +++ b/components/shared/webgpu/messages/mod.rs @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +pub mod recv; +pub mod to_dom; +pub mod to_script; + +pub use recv::*; +pub use to_dom::*; +pub use to_script::*; diff --git a/components/shared/webgpu/messages/recv.rs b/components/shared/webgpu/messages/recv.rs new file mode 100644 index 00000000000..47c32437e45 --- /dev/null +++ b/components/shared/webgpu/messages/recv.rs @@ -0,0 +1,338 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +//! IPC messages that are received in the WebGPU thread +//! (usually from the ScriptThread, and more specifically from DOM objects) + +use arrayvec::ArrayVec; +use base::id::PipelineId; +use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; +use serde::{Deserialize, Serialize}; +use webrender_api::ImageKey; +use webrender_api::units::DeviceIntSize; +use wgpu_core::Label; +use wgpu_core::binding_model::{ + BindGroupDescriptor, BindGroupLayoutDescriptor, PipelineLayoutDescriptor, +}; +use wgpu_core::command::{ + RenderBundleDescriptor, RenderBundleEncoder, RenderPassColorAttachment, + RenderPassDepthStencilAttachment, TexelCopyBufferInfo, TexelCopyTextureInfo, +}; +use wgpu_core::device::HostMap; +pub use wgpu_core::id::markers::{ + ComputePassEncoder as ComputePass, RenderPassEncoder as RenderPass, +}; +use wgpu_core::id::{ + AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, CommandEncoderId, + ComputePassEncoderId, ComputePipelineId, DeviceId, PipelineLayoutId, QuerySetId, QueueId, + RenderBundleId, RenderPassEncoderId, RenderPipelineId, SamplerId, ShaderModuleId, TextureId, + TextureViewId, +}; +pub use wgpu_core::id::{ + ComputePassEncoderId as ComputePassId, RenderPassEncoderId as RenderPassId, +}; +use wgpu_core::instance::RequestAdapterOptions; +use wgpu_core::pipeline::{ComputePipelineDescriptor, RenderPipelineDescriptor}; +use wgpu_core::resource::{ + BufferAccessError, BufferDescriptor, SamplerDescriptor, TextureDescriptor, + TextureViewDescriptor, +}; +use wgpu_types::{ + BufferAddress, CommandBufferDescriptor, CommandEncoderDescriptor, DeviceDescriptor, Extent3d, + TexelCopyBufferLayout, +}; + +use crate::{ + ContextConfiguration, Error, ErrorFilter, Mapping, PRESENTATION_BUFFER_COUNT, RenderCommand, + ShaderCompilationInfo, WebGPUAdapter, WebGPUAdapterResponse, WebGPUComputePipelineResponse, + WebGPUContextId, WebGPUDeviceResponse, WebGPUPoppedErrorScopeResponse, + WebGPURenderPipelineResponse, +}; + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebGPURequest { + BufferMapAsync { + sender: IpcSender<Result<Mapping, BufferAccessError>>, + buffer_id: BufferId, + device_id: DeviceId, + host_map: HostMap, + offset: u64, + size: Option<u64>, + }, + CommandEncoderFinish { + command_encoder_id: CommandEncoderId, + device_id: DeviceId, + desc: CommandBufferDescriptor<Label<'static>>, + }, + CopyBufferToBuffer { + command_encoder_id: CommandEncoderId, + source_id: BufferId, + source_offset: BufferAddress, + destination_id: BufferId, + destination_offset: BufferAddress, + size: BufferAddress, + }, + CopyBufferToTexture { + command_encoder_id: CommandEncoderId, + source: TexelCopyBufferInfo, + destination: TexelCopyTextureInfo, + copy_size: Extent3d, + }, + CopyTextureToBuffer { + command_encoder_id: CommandEncoderId, + source: TexelCopyTextureInfo, + destination: TexelCopyBufferInfo, + copy_size: Extent3d, + }, + CopyTextureToTexture { + command_encoder_id: CommandEncoderId, + source: TexelCopyTextureInfo, + destination: TexelCopyTextureInfo, + copy_size: Extent3d, + }, + CreateBindGroup { + device_id: DeviceId, + bind_group_id: BindGroupId, + descriptor: BindGroupDescriptor<'static>, + }, + CreateBindGroupLayout { + device_id: DeviceId, + bind_group_layout_id: BindGroupLayoutId, + descriptor: Option<BindGroupLayoutDescriptor<'static>>, + }, + CreateBuffer { + device_id: DeviceId, + buffer_id: BufferId, + descriptor: BufferDescriptor<'static>, + }, + CreateCommandEncoder { + device_id: DeviceId, + command_encoder_id: CommandEncoderId, + desc: CommandEncoderDescriptor<Label<'static>>, + }, + CreateComputePipeline { + device_id: DeviceId, + compute_pipeline_id: ComputePipelineId, + descriptor: ComputePipelineDescriptor<'static>, + implicit_ids: Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>, + /// present only on ASYNC versions + async_sender: Option<IpcSender<WebGPUComputePipelineResponse>>, + }, + CreatePipelineLayout { + device_id: DeviceId, + pipeline_layout_id: PipelineLayoutId, + descriptor: PipelineLayoutDescriptor<'static>, + }, + CreateRenderPipeline { + device_id: DeviceId, + render_pipeline_id: RenderPipelineId, + descriptor: RenderPipelineDescriptor<'static>, + implicit_ids: Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>, + /// present only on ASYNC versions + async_sender: Option<IpcSender<WebGPURenderPipelineResponse>>, + }, + CreateSampler { + device_id: DeviceId, + sampler_id: SamplerId, + descriptor: SamplerDescriptor<'static>, + }, + CreateShaderModule { + device_id: DeviceId, + program_id: ShaderModuleId, + program: String, + label: Option<String>, + sender: IpcSender<Option<ShaderCompilationInfo>>, + }, + /// Creates context + CreateContext { + buffer_ids: ArrayVec<BufferId, PRESENTATION_BUFFER_COUNT>, + size: DeviceIntSize, + sender: IpcSender<(WebGPUContextId, ImageKey)>, + }, + /// Recreates swapchain (if needed) + UpdateContext { + context_id: WebGPUContextId, + size: DeviceIntSize, + configuration: Option<ContextConfiguration>, + }, + /// Reads texture to swapchains buffer and maps it + SwapChainPresent { + context_id: WebGPUContextId, + texture_id: TextureId, + encoder_id: CommandEncoderId, + }, + /// Obtains image from latest presentation buffer (same as wr update) + GetImage { + context_id: WebGPUContextId, + sender: IpcSender<IpcSharedMemory>, + }, + ValidateTextureDescriptor { + device_id: DeviceId, + texture_id: TextureId, + descriptor: TextureDescriptor<'static>, + }, + DestroyContext { + context_id: WebGPUContextId, + }, + CreateTexture { + device_id: DeviceId, + texture_id: TextureId, + descriptor: TextureDescriptor<'static>, + }, + CreateTextureView { + texture_id: TextureId, + texture_view_id: TextureViewId, + device_id: DeviceId, + descriptor: Option<TextureViewDescriptor<'static>>, + }, + DestroyBuffer(BufferId), + DestroyDevice(DeviceId), + DestroyTexture(TextureId), + DropTexture(TextureId), + DropAdapter(AdapterId), + DropDevice(DeviceId), + DropBuffer(BufferId), + DropPipelineLayout(PipelineLayoutId), + DropComputePipeline(ComputePipelineId), + DropRenderPipeline(RenderPipelineId), + DropBindGroup(BindGroupId), + DropBindGroupLayout(BindGroupLayoutId), + DropCommandBuffer(CommandBufferId), + DropTextureView(TextureViewId), + DropSampler(SamplerId), + DropShaderModule(ShaderModuleId), + DropRenderBundle(RenderBundleId), + DropQuerySet(QuerySetId), + DropComputePass(ComputePassEncoderId), + DropRenderPass(RenderPassEncoderId), + Exit(IpcSender<()>), + RenderBundleEncoderFinish { + render_bundle_encoder: RenderBundleEncoder, + descriptor: RenderBundleDescriptor<'static>, + render_bundle_id: RenderBundleId, + device_id: DeviceId, + }, + RequestAdapter { + sender: IpcSender<WebGPUAdapterResponse>, + options: RequestAdapterOptions, + adapter_id: AdapterId, + }, + RequestDevice { + sender: IpcSender<WebGPUDeviceResponse>, + adapter_id: WebGPUAdapter, + descriptor: DeviceDescriptor<Option<String>>, + device_id: DeviceId, + queue_id: QueueId, + pipeline_id: PipelineId, + }, + // Compute Pass + BeginComputePass { + command_encoder_id: CommandEncoderId, + compute_pass_id: ComputePassId, + label: Label<'static>, + device_id: DeviceId, + }, + ComputePassSetPipeline { + compute_pass_id: ComputePassId, + pipeline_id: ComputePipelineId, + device_id: DeviceId, + }, + ComputePassSetBindGroup { + compute_pass_id: ComputePassId, + index: u32, + bind_group_id: BindGroupId, + offsets: Vec<u32>, + device_id: DeviceId, + }, + ComputePassDispatchWorkgroups { + compute_pass_id: ComputePassId, + x: u32, + y: u32, + z: u32, + device_id: DeviceId, + }, + ComputePassDispatchWorkgroupsIndirect { + compute_pass_id: ComputePassId, + buffer_id: BufferId, + offset: u64, + device_id: DeviceId, + }, + EndComputePass { + compute_pass_id: ComputePassId, + device_id: DeviceId, + command_encoder_id: CommandEncoderId, + }, + // Render Pass + BeginRenderPass { + command_encoder_id: CommandEncoderId, + render_pass_id: RenderPassId, + label: Label<'static>, + color_attachments: Vec<Option<RenderPassColorAttachment>>, + depth_stencil_attachment: Option<RenderPassDepthStencilAttachment>, + device_id: DeviceId, + }, + RenderPassCommand { + render_pass_id: RenderPassId, + render_command: RenderCommand, + device_id: DeviceId, + }, + EndRenderPass { + render_pass_id: RenderPassId, + device_id: DeviceId, + command_encoder_id: CommandEncoderId, + }, + Submit { + device_id: DeviceId, + queue_id: QueueId, + command_buffers: Vec<CommandBufferId>, + }, + UnmapBuffer { + buffer_id: BufferId, + /// Return back mapping for writeback + mapping: Option<Mapping>, + }, + WriteBuffer { + device_id: DeviceId, + queue_id: QueueId, + buffer_id: BufferId, + buffer_offset: u64, + data: IpcSharedMemory, + }, + WriteTexture { + device_id: DeviceId, + queue_id: QueueId, + texture_cv: TexelCopyTextureInfo, + data_layout: TexelCopyBufferLayout, + size: Extent3d, + data: IpcSharedMemory, + }, + QueueOnSubmittedWorkDone { + sender: IpcSender<()>, + queue_id: QueueId, + }, + PushErrorScope { + device_id: DeviceId, + filter: ErrorFilter, + }, + DispatchError { + device_id: DeviceId, + error: Error, + }, + PopErrorScope { + device_id: DeviceId, + sender: IpcSender<WebGPUPoppedErrorScopeResponse>, + }, + ComputeGetBindGroupLayout { + device_id: DeviceId, + pipeline_id: ComputePipelineId, + index: u32, + id: BindGroupLayoutId, + }, + RenderGetBindGroupLayout { + device_id: DeviceId, + pipeline_id: RenderPipelineId, + index: u32, + id: BindGroupLayoutId, + }, +} diff --git a/components/shared/webgpu/messages/to_dom.rs b/components/shared/webgpu/messages/to_dom.rs new file mode 100644 index 00000000000..b5d5db72e38 --- /dev/null +++ b/components/shared/webgpu/messages/to_dom.rs @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +//! IPC messages that are sent to WebGPU DOM objects. + +use wgpu_core::instance::RequestDeviceError; +use wgpu_types::DeviceDescriptor; + +use crate::{WebGPUDevice, WebGPUQueue}; + +pub type WebGPUDeviceResponse = ( + WebGPUDevice, + WebGPUQueue, + Result<DeviceDescriptor<Option<String>>, RequestDeviceError>, +); diff --git a/components/shared/webgpu/messages/to_script.rs b/components/shared/webgpu/messages/to_script.rs new file mode 100644 index 00000000000..303e17eeaad --- /dev/null +++ b/components/shared/webgpu/messages/to_script.rs @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +//! IPC messages that are sent to the ScriptThread. + +use base::id::PipelineId; +use serde::{Deserialize, Serialize}; +use wgpu_core::id::{ + AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, ComputePassEncoderId, + ComputePipelineId, DeviceId, PipelineLayoutId, QuerySetId, RenderBundleId, RenderPassEncoderId, + RenderPipelineId, SamplerId, ShaderModuleId, StagingBufferId, SurfaceId, TextureId, + TextureViewId, +}; + +use crate::{DeviceLostReason, Error, WebGPUDevice}; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum WebGPUMsg { + FreeAdapter(AdapterId), + FreeDevice { + device_id: DeviceId, + pipeline_id: PipelineId, + }, + FreeBuffer(BufferId), + FreePipelineLayout(PipelineLayoutId), + FreeComputePipeline(ComputePipelineId), + FreeRenderPipeline(RenderPipelineId), + FreeBindGroup(BindGroupId), + FreeBindGroupLayout(BindGroupLayoutId), + FreeCommandBuffer(CommandBufferId), + FreeTexture(TextureId), + FreeTextureView(TextureViewId), + FreeSampler(SamplerId), + FreeSurface(SurfaceId), + FreeShaderModule(ShaderModuleId), + FreeRenderBundle(RenderBundleId), + FreeStagingBuffer(StagingBufferId), + FreeQuerySet(QuerySetId), + FreeComputePass(ComputePassEncoderId), + FreeRenderPass(RenderPassEncoderId), + UncapturedError { + device: WebGPUDevice, + pipeline_id: PipelineId, + error: Error, + }, + DeviceLost { + device: WebGPUDevice, + pipeline_id: PipelineId, + reason: DeviceLostReason, + msg: String, + }, + Exit, +} diff --git a/components/shared/webgpu/render_commands.rs b/components/shared/webgpu/render_commands.rs new file mode 100644 index 00000000000..37ba70daaca --- /dev/null +++ b/components/shared/webgpu/render_commands.rs @@ -0,0 +1,155 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +//! Render pass commands + +use serde::{Deserialize, Serialize}; +use wgpu_core::command::{RenderPass, RenderPassError}; +use wgpu_core::global::Global; +use wgpu_core::id::{BindGroupId, BufferId, RenderBundleId, RenderPipelineId}; + +/// <https://github.com/gfx-rs/wgpu/blob/f25e07b984ab391628d9568296d5970981d79d8b/wgpu-core/src/command/render_command.rs#L17> +#[derive(Debug, Deserialize, Serialize)] +pub enum RenderCommand { + SetPipeline(RenderPipelineId), + SetBindGroup { + index: u32, + bind_group_id: BindGroupId, + offsets: Vec<u32>, + }, + SetViewport { + x: f32, + y: f32, + width: f32, + height: f32, + min_depth: f32, + max_depth: f32, + }, + SetScissorRect { + x: u32, + y: u32, + width: u32, + height: u32, + }, + SetBlendConstant(wgpu_types::Color), + SetStencilReference(u32), + SetIndexBuffer { + buffer_id: BufferId, + index_format: wgpu_types::IndexFormat, + offset: u64, + size: Option<wgpu_types::BufferSize>, + }, + SetVertexBuffer { + slot: u32, + buffer_id: BufferId, + offset: u64, + size: Option<wgpu_types::BufferSize>, + }, + Draw { + vertex_count: u32, + instance_count: u32, + first_vertex: u32, + first_instance: u32, + }, + DrawIndexed { + index_count: u32, + instance_count: u32, + first_index: u32, + base_vertex: i32, + first_instance: u32, + }, + DrawIndirect { + buffer_id: BufferId, + offset: u64, + }, + DrawIndexedIndirect { + buffer_id: BufferId, + offset: u64, + }, + ExecuteBundles(Vec<RenderBundleId>), +} + +pub fn apply_render_command( + global: &Global, + pass: &mut RenderPass, + command: RenderCommand, +) -> Result<(), RenderPassError> { + match command { + RenderCommand::SetPipeline(pipeline_id) => { + global.render_pass_set_pipeline(pass, pipeline_id) + }, + RenderCommand::SetBindGroup { + index, + bind_group_id, + offsets, + } => global.render_pass_set_bind_group(pass, index, Some(bind_group_id), &offsets), + RenderCommand::SetViewport { + x, + y, + width, + height, + min_depth, + max_depth, + } => global.render_pass_set_viewport(pass, x, y, width, height, min_depth, max_depth), + RenderCommand::SetScissorRect { + x, + y, + width, + height, + } => global.render_pass_set_scissor_rect(pass, x, y, width, height), + RenderCommand::SetBlendConstant(color) => { + global.render_pass_set_blend_constant(pass, color) + }, + RenderCommand::SetStencilReference(reference) => { + global.render_pass_set_stencil_reference(pass, reference) + }, + RenderCommand::SetIndexBuffer { + buffer_id, + index_format, + offset, + size, + } => global.render_pass_set_index_buffer(pass, buffer_id, index_format, offset, size), + RenderCommand::SetVertexBuffer { + slot, + buffer_id, + offset, + size, + } => global.render_pass_set_vertex_buffer(pass, slot, buffer_id, offset, size), + RenderCommand::Draw { + vertex_count, + instance_count, + first_vertex, + first_instance, + } => global.render_pass_draw( + pass, + vertex_count, + instance_count, + first_vertex, + first_instance, + ), + RenderCommand::DrawIndexed { + index_count, + instance_count, + first_index, + base_vertex, + first_instance, + } => global.render_pass_draw_indexed( + pass, + index_count, + instance_count, + first_index, + base_vertex, + first_instance, + ), + RenderCommand::DrawIndirect { buffer_id, offset } => { + global.render_pass_draw_indirect(pass, buffer_id, offset) + }, + RenderCommand::DrawIndexedIndirect { buffer_id, offset } => { + global.render_pass_draw_indexed_indirect(pass, buffer_id, offset) + }, + RenderCommand::ExecuteBundles(bundles) => { + global.render_pass_execute_bundles(pass, &bundles) + }, + } +} |