Skip to main content

webgpu_traits/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5pub mod encoders;
6pub mod error;
7pub mod ids;
8pub mod messages;
9
10use std::ops::Range;
11
12use malloc_size_of_derive::MallocSizeOf;
13use serde::{Deserialize, Serialize};
14use servo_base::generic_channel::{GenericOneshotSender, GenericSender, GenericSharedMemory};
15use webrender_api::euclid::default::Size2D;
16use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
17pub mod markers {
18    pub use wgpu_core::id::markers::{
19        Adapter, BindGroup, BindGroupLayout, Buffer, CommandBuffer, CommandEncoder,
20        ComputePassEncoder, ComputePipeline, Device, ExternalTexture, PipelineLayout, QuerySet,
21        Queue, RenderBundle, RenderBundleEncoder, RenderPassEncoder, RenderPipeline, Sampler,
22        ShaderModule, Texture, TextureView,
23    };
24}
25pub mod id {
26    pub use wgpu_core::id::{
27        AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, CommandEncoderId,
28        ComputePassEncoderId, ComputePipelineId, DeviceId, ExternalTextureId, PipelineLayoutId,
29        QuerySetId, QueueId, RenderBundleEncoderId, RenderBundleId, RenderPassEncoderId,
30        RenderPipelineId, SamplerId, ShaderModuleId, TextureId, TextureViewId,
31    };
32}
33pub use wgpu_core::Label;
34pub use wgpu_core::binding_model::{
35    BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindingResource, BufferBinding,
36    PipelineLayoutDescriptor,
37};
38pub use wgpu_core::command::{
39    ComputePassDescriptor, LoadOp, PassChannel, PassTimestampWrites, RenderBundleDescriptor,
40    RenderBundleEncoderDescriptor, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
41    RenderPassDescriptor, StoreOp, TexelCopyBufferInfo, TexelCopyTextureInfo,
42};
43pub use wgpu_core::device::HostMap;
44use wgpu_core::id::{ComputePipelineId, DeviceId, QueueId, RenderPipelineId};
45pub use wgpu_core::identity::IdentityManager;
46pub use wgpu_core::instance::RequestAdapterOptions;
47use wgpu_core::limits::FailedLimit;
48pub use wgpu_core::naga::front::wgsl::ImplementedLanguageExtension;
49use wgpu_core::pipeline::CreateShaderModuleError;
50pub use wgpu_core::pipeline::{
51    ComputePipelineDescriptor, FragmentState, ProgrammableStageDescriptor,
52    RenderPipelineDescriptor, ShaderModuleDescriptor, VertexBufferLayout, VertexState,
53};
54pub use wgpu_core::resource::{
55    BufferAccessError, BufferDescriptor, QuerySetDescriptor, SamplerDescriptor, TextureDescriptor,
56    TextureViewDescriptor,
57};
58use wgpu_types::COPY_BYTES_PER_ROW_ALIGNMENT;
59pub use wgpu_types::{
60    AdapterInfo, AddressMode, AstcBlock, AstcChannel, BindGroupLayoutEntry, BindingType,
61    BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBindingType,
62    BufferSize, BufferUsages, COPY_BUFFER_ALIGNMENT, Color, ColorTargetState, ColorWrites,
63    CommandBufferDescriptor, CommandEncoderDescriptor, CompareFunction, DepthBiasState,
64    DepthStencilState, DeviceDescriptor, DeviceType, ExperimentalFeatures, Extent3d, Face,
65    Features, FilterMode, FrontFace, ImageSubresourceRange, IndexFormat, Limits, MAP_ALIGNMENT,
66    MemoryHints, MipmapFilterMode, MultisampleState, Origin2d, Origin3d, PowerPreference,
67    PredefinedColorSpace, PrimitiveState, PrimitiveTopology, QueryType, RenderBundleDepthStencil,
68    SamplerBindingType, ShaderStages, StencilFaceState, StencilOperation, StencilState,
69    StorageTextureAccess, TexelCopyBufferLayout, TextureAspect, TextureDimension, TextureFormat,
70    TextureSampleType, TextureUsages, TextureViewDimension, Trace, VertexAttribute, VertexFormat,
71    VertexStepMode,
72};
73
74pub use crate::encoders::*;
75pub use crate::error::*;
76pub use crate::ids::*;
77pub use crate::messages::*;
78
79pub const PRESENTATION_BUFFER_COUNT: usize = 10;
80
81pub type WebGPUAdapterResponse = Option<Result<Adapter, String>>;
82pub type WebGPUComputePipelineResponse = Result<Pipeline<ComputePipelineId>, Error>;
83pub type WebGPUPoppedErrorScopeResponse = Result<Option<Error>, PopError>;
84pub type WebGPURenderPipelineResponse = Result<Pipeline<RenderPipelineId>, Error>;
85
86#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
87pub struct WebGPU(pub GenericSender<WebGPURequest>);
88
89impl WebGPU {
90    pub fn exit(&self, sender: GenericOneshotSender<()>) -> Result<(), &'static str> {
91        self.0
92            .send(WebGPURequest::Exit(sender))
93            .map_err(|_| "Failed to send Exit message")
94    }
95}
96
97#[derive(Debug, Deserialize, Serialize)]
98pub struct Adapter {
99    pub adapter_info: AdapterInfo,
100    pub adapter_id: WebGPUAdapter,
101    pub features: Features,
102    pub limits: Limits,
103    pub channel: WebGPU,
104}
105
106#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
107pub struct ContextConfiguration {
108    pub device_id: DeviceId,
109    pub queue_id: QueueId,
110    pub format: ImageFormat,
111    pub is_opaque: bool,
112    pub size: Size2D<u32>,
113}
114
115impl ContextConfiguration {
116    pub fn stride(&self) -> u32 {
117        (self.size.width * self.format.bytes_per_pixel() as u32)
118            .next_multiple_of(COPY_BYTES_PER_ROW_ALIGNMENT)
119    }
120
121    pub fn buffer_size(&self) -> u64 {
122        self.stride() as u64 * self.size.height as u64
123    }
124}
125
126impl From<ContextConfiguration> for ImageDescriptor {
127    fn from(config: ContextConfiguration) -> Self {
128        ImageDescriptor {
129            format: config.format,
130            size: config.size.cast().cast_unit(),
131            stride: Some(config.stride() as i32),
132            offset: 0,
133            flags: if config.is_opaque {
134                ImageDescriptorFlags::IS_OPAQUE
135            } else {
136                ImageDescriptorFlags::empty()
137            },
138        }
139    }
140}
141
142/// <https://gpuweb.github.io/gpuweb/#enumdef-gpudevicelostreason>
143#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
144pub enum DeviceLostReason {
145    Unknown,
146    Destroyed,
147}
148
149#[derive(Clone, Debug, Default, Deserialize, Serialize)]
150pub struct ShaderCompilationInfo {
151    pub line_number: u64,
152    pub line_pos: u64,
153    pub offset: u64,
154    pub length: u64,
155    pub message: String,
156}
157
158impl ShaderCompilationInfo {
159    pub fn from(error: &CreateShaderModuleError, source: &str) -> Self {
160        let location = match error {
161            CreateShaderModuleError::Parsing(e) => e.inner.location(source),
162            CreateShaderModuleError::Validation(e) => e.inner.location(source),
163            _ => None,
164        };
165
166        if let Some(location) = location {
167            // Naga reports locations in UTF-8 code units, but spec requires location in UTF-16 code units
168            // Based on https://searchfox.org/mozilla-central/rev/5b037d9c6ecdb0729f39ad519f0b867d80a92aad/gfx/wgpu_bindings/src/server.rs#353
169            fn len_utf16(s: &str) -> u64 {
170                s.chars().map(|c| c.len_utf16() as u64).sum()
171            }
172            let start = location.offset as usize;
173            let end = start + location.length as usize;
174            let line_start = source[0..start].rfind('\n').map(|pos| pos + 1).unwrap_or(0);
175            Self {
176                line_number: location.line_number as u64,
177                line_pos: len_utf16(&source[line_start..start]) + 1,
178                offset: len_utf16(&source[0..start]),
179                length: len_utf16(&source[start..end]),
180                message: error.to_string(),
181            }
182        } else {
183            Self {
184                message: error.to_string(),
185                ..Default::default()
186            }
187        }
188    }
189}
190
191#[derive(Debug, Deserialize, Serialize)]
192pub struct Pipeline<T: std::fmt::Debug + Serialize> {
193    pub id: T,
194    pub label: String,
195}
196
197#[derive(Debug, Deserialize, Serialize)]
198pub struct Mapping {
199    pub data: GenericSharedMemory,
200    pub mode: HostMap,
201    pub range: Range<u64>,
202}
203
204pub type WebGPUDeviceResponse = (
205    WebGPUDevice,
206    WebGPUQueue,
207    Result<DeviceDescriptor<Option<String>>, RequestDeviceError>,
208);
209
210#[derive(Clone, Debug, Deserialize, Serialize)]
211pub enum RequestDeviceError {
212    LimitsExceeded(FailedLimit),
213    UnsupportedFeature(Features),
214    Other(String),
215}
216
217impl From<wgpu_core::instance::RequestDeviceError> for RequestDeviceError {
218    fn from(value: wgpu_core::instance::RequestDeviceError) -> Self {
219        match value {
220            wgpu_core::instance::RequestDeviceError::LimitsExceeded(failed_limit) => {
221                RequestDeviceError::LimitsExceeded(failed_limit)
222            },
223            wgpu_core::instance::RequestDeviceError::UnsupportedFeature(features) => {
224                RequestDeviceError::UnsupportedFeature(features)
225            },
226            e => RequestDeviceError::Other(e.to_string()),
227        }
228    }
229}