aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared/webgpu
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared/webgpu')
-rw-r--r--components/shared/webgpu/Cargo.toml22
-rw-r--r--components/shared/webgpu/error.rs97
-rw-r--r--components/shared/webgpu/ids.rs53
-rw-r--r--components/shared/webgpu/lib.rs144
-rw-r--r--components/shared/webgpu/messages/mod.rs11
-rw-r--r--components/shared/webgpu/messages/recv.rs338
-rw-r--r--components/shared/webgpu/messages/to_dom.rs16
-rw-r--r--components/shared/webgpu/messages/to_script.rs54
-rw-r--r--components/shared/webgpu/render_commands.rs155
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)
+ },
+ }
+}