Skip to main content

script/dom/webgpu/
gpuconvert.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
5use std::borrow::Cow;
6use std::num::NonZeroU64;
7
8use webgpu_traits::WebGPUTextureView;
9use wgpu_core::binding_model::{BindGroupEntry, BindingResource, BufferBinding};
10use wgpu_core::command as wgpu_com;
11use wgpu_core::pipeline::ProgrammableStageDescriptor;
12use wgpu_core::resource::TextureDescriptor;
13use wgpu_types::{self, AstcBlock, AstcChannel};
14
15use crate::conversions::{Convert, TryConvert};
16use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
17    GPUAddressMode, GPUBindGroupEntry, GPUBindGroupLayoutEntry, GPUBindingResource,
18    GPUBlendComponent, GPUBlendFactor, GPUBlendOperation, GPUBufferBindingType, GPUColor,
19    GPUCompareFunction, GPUCullMode, GPUExtent3D, GPUFilterMode, GPUFrontFace, GPUIndexFormat,
20    GPULoadOp, GPUMipmapFilterMode, GPUObjectDescriptorBase, GPUOrigin3D, GPUPrimitiveState,
21    GPUPrimitiveTopology, GPUProgrammableStage, GPUSamplerBindingType, GPUStencilOperation,
22    GPUStorageTextureAccess, GPUStoreOp, GPUTexelCopyBufferInfo, GPUTexelCopyBufferLayout,
23    GPUTexelCopyTextureInfo, GPUTextureAspect, GPUTextureDescriptor, GPUTextureDimension,
24    GPUTextureFormat, GPUTextureSampleType, GPUTextureViewDimension, GPUVertexFormat,
25};
26use crate::dom::bindings::codegen::UnionTypes::GPUTextureOrGPUTextureView;
27use crate::dom::bindings::error::{Error, Fallible};
28use crate::dom::types::GPUDevice;
29
30impl Convert<wgpu_types::TextureFormat> for GPUTextureFormat {
31    fn convert(self) -> wgpu_types::TextureFormat {
32        match self {
33            // 8-bit formats
34            GPUTextureFormat::R8unorm => wgpu_types::TextureFormat::R8Unorm,
35            GPUTextureFormat::R8snorm => wgpu_types::TextureFormat::R8Snorm,
36            GPUTextureFormat::R8uint => wgpu_types::TextureFormat::R8Uint,
37            GPUTextureFormat::R8sint => wgpu_types::TextureFormat::R8Sint,
38            // 16-bit formats
39            GPUTextureFormat::R16unorm => wgpu_types::TextureFormat::R16Unorm,
40            GPUTextureFormat::R16snorm => wgpu_types::TextureFormat::R16Snorm,
41            GPUTextureFormat::R16uint => wgpu_types::TextureFormat::R16Uint,
42            GPUTextureFormat::R16sint => wgpu_types::TextureFormat::R16Sint,
43            GPUTextureFormat::R16float => wgpu_types::TextureFormat::R16Float,
44            GPUTextureFormat::Rg8unorm => wgpu_types::TextureFormat::Rg8Unorm,
45            GPUTextureFormat::Rg8snorm => wgpu_types::TextureFormat::Rg8Snorm,
46            GPUTextureFormat::Rg8uint => wgpu_types::TextureFormat::Rg8Uint,
47            GPUTextureFormat::Rg8sint => wgpu_types::TextureFormat::Rg8Sint,
48            // 32-bit formats
49            GPUTextureFormat::R32uint => wgpu_types::TextureFormat::R32Uint,
50            GPUTextureFormat::R32sint => wgpu_types::TextureFormat::R32Sint,
51            GPUTextureFormat::R32float => wgpu_types::TextureFormat::R32Float,
52            GPUTextureFormat::Rg16unorm => wgpu_types::TextureFormat::Rg16Unorm,
53            GPUTextureFormat::Rg16snorm => wgpu_types::TextureFormat::Rg16Snorm,
54            GPUTextureFormat::Rg16uint => wgpu_types::TextureFormat::Rg16Uint,
55            GPUTextureFormat::Rg16sint => wgpu_types::TextureFormat::Rg16Sint,
56            GPUTextureFormat::Rg16float => wgpu_types::TextureFormat::Rg16Float,
57            GPUTextureFormat::Rgba8unorm => wgpu_types::TextureFormat::Rgba8Unorm,
58            GPUTextureFormat::Rgba8unorm_srgb => wgpu_types::TextureFormat::Rgba8UnormSrgb,
59            GPUTextureFormat::Rgba8snorm => wgpu_types::TextureFormat::Rgba8Snorm,
60            GPUTextureFormat::Rgba8uint => wgpu_types::TextureFormat::Rgba8Uint,
61            GPUTextureFormat::Rgba8sint => wgpu_types::TextureFormat::Rgba8Sint,
62            GPUTextureFormat::Bgra8unorm => wgpu_types::TextureFormat::Bgra8Unorm,
63            GPUTextureFormat::Bgra8unorm_srgb => wgpu_types::TextureFormat::Bgra8UnormSrgb,
64            // Packed 32-bit formats
65            GPUTextureFormat::Rgb9e5ufloat => wgpu_types::TextureFormat::Rgb9e5Ufloat,
66            GPUTextureFormat::Rgb10a2uint => wgpu_types::TextureFormat::Rgb10a2Uint,
67            GPUTextureFormat::Rgb10a2unorm => wgpu_types::TextureFormat::Rgb10a2Unorm,
68            GPUTextureFormat::Rg11b10ufloat => wgpu_types::TextureFormat::Rg11b10Ufloat,
69            // 64-bit formats
70            GPUTextureFormat::Rg32uint => wgpu_types::TextureFormat::Rg32Uint,
71            GPUTextureFormat::Rg32sint => wgpu_types::TextureFormat::Rg32Sint,
72            GPUTextureFormat::Rg32float => wgpu_types::TextureFormat::Rg32Float,
73            GPUTextureFormat::Rgba16unorm => wgpu_types::TextureFormat::Rgba16Unorm,
74            GPUTextureFormat::Rgba16snorm => wgpu_types::TextureFormat::Rgba16Snorm,
75            GPUTextureFormat::Rgba16uint => wgpu_types::TextureFormat::Rgba16Uint,
76            GPUTextureFormat::Rgba16sint => wgpu_types::TextureFormat::Rgba16Sint,
77            GPUTextureFormat::Rgba16float => wgpu_types::TextureFormat::Rgba16Float,
78            // 96-bit formats
79            GPUTextureFormat::Rgba32uint => wgpu_types::TextureFormat::Rgba32Uint,
80            GPUTextureFormat::Rgba32sint => wgpu_types::TextureFormat::Rgba32Sint,
81            GPUTextureFormat::Rgba32float => wgpu_types::TextureFormat::Rgba32Float,
82            // Depth/stencil formats
83            GPUTextureFormat::Stencil8 => wgpu_types::TextureFormat::Stencil8,
84            GPUTextureFormat::Depth16unorm => wgpu_types::TextureFormat::Depth16Unorm,
85            GPUTextureFormat::Depth24plus => wgpu_types::TextureFormat::Depth24Plus,
86            GPUTextureFormat::Depth24plus_stencil8 => {
87                wgpu_types::TextureFormat::Depth24PlusStencil8
88            },
89            GPUTextureFormat::Depth32float => wgpu_types::TextureFormat::Depth32Float,
90            // "depth32float-stencil8" feature
91            GPUTextureFormat::Depth32float_stencil8 => {
92                wgpu_types::TextureFormat::Depth32FloatStencil8
93            },
94            // BC compressed formats usable if "texture-compression-bc" is both
95            // supported by the device/user agent and enabled in requestDevice.
96            GPUTextureFormat::Bc1_rgba_unorm => wgpu_types::TextureFormat::Bc1RgbaUnorm,
97            GPUTextureFormat::Bc1_rgba_unorm_srgb => wgpu_types::TextureFormat::Bc1RgbaUnormSrgb,
98            GPUTextureFormat::Bc2_rgba_unorm => wgpu_types::TextureFormat::Bc2RgbaUnorm,
99            GPUTextureFormat::Bc2_rgba_unorm_srgb => wgpu_types::TextureFormat::Bc2RgbaUnormSrgb,
100            GPUTextureFormat::Bc3_rgba_unorm => wgpu_types::TextureFormat::Bc3RgbaUnorm,
101            GPUTextureFormat::Bc3_rgba_unorm_srgb => wgpu_types::TextureFormat::Bc3RgbaUnormSrgb,
102            GPUTextureFormat::Bc4_r_unorm => wgpu_types::TextureFormat::Bc4RUnorm,
103            GPUTextureFormat::Bc4_r_snorm => wgpu_types::TextureFormat::Bc4RSnorm,
104            GPUTextureFormat::Bc5_rg_unorm => wgpu_types::TextureFormat::Bc5RgUnorm,
105            GPUTextureFormat::Bc5_rg_snorm => wgpu_types::TextureFormat::Bc5RgSnorm,
106            GPUTextureFormat::Bc6h_rgb_ufloat => wgpu_types::TextureFormat::Bc6hRgbUfloat,
107            GPUTextureFormat::Bc6h_rgb_float => wgpu_types::TextureFormat::Bc6hRgbFloat,
108            GPUTextureFormat::Bc7_rgba_unorm => wgpu_types::TextureFormat::Bc7RgbaUnorm,
109            GPUTextureFormat::Bc7_rgba_unorm_srgb => wgpu_types::TextureFormat::Bc7RgbaUnormSrgb,
110            // ETC2 compressed formats usable if "texture-compression-etc2" is both
111            // supported by the device/user agent and enabled in requestDevice.
112            GPUTextureFormat::Etc2_rgb8unorm => wgpu_types::TextureFormat::Etc2Rgb8Unorm,
113            GPUTextureFormat::Etc2_rgb8unorm_srgb => wgpu_types::TextureFormat::Etc2Rgb8UnormSrgb,
114            GPUTextureFormat::Etc2_rgb8a1unorm => wgpu_types::TextureFormat::Etc2Rgb8A1Unorm,
115            GPUTextureFormat::Etc2_rgb8a1unorm_srgb => {
116                wgpu_types::TextureFormat::Etc2Rgb8A1UnormSrgb
117            },
118            GPUTextureFormat::Etc2_rgba8unorm => wgpu_types::TextureFormat::Etc2Rgba8Unorm,
119            GPUTextureFormat::Etc2_rgba8unorm_srgb => wgpu_types::TextureFormat::Etc2Rgba8UnormSrgb,
120            GPUTextureFormat::Eac_r11unorm => wgpu_types::TextureFormat::EacR11Unorm,
121            GPUTextureFormat::Eac_r11snorm => wgpu_types::TextureFormat::EacR11Snorm,
122            GPUTextureFormat::Eac_rg11unorm => wgpu_types::TextureFormat::EacRg11Unorm,
123            GPUTextureFormat::Eac_rg11snorm => wgpu_types::TextureFormat::EacRg11Snorm,
124            // ASTC compressed formats usable if "texture-compression-astc" is both
125            // supported by the device/user agent and enabled in requestDevice.
126            GPUTextureFormat::Astc_4x4_unorm => wgpu_types::TextureFormat::Astc {
127                block: AstcBlock::B4x4,
128                channel: AstcChannel::Unorm,
129            },
130            GPUTextureFormat::Astc_4x4_unorm_srgb => wgpu_types::TextureFormat::Astc {
131                block: AstcBlock::B4x4,
132                channel: AstcChannel::UnormSrgb,
133            },
134            GPUTextureFormat::Astc_5x4_unorm => wgpu_types::TextureFormat::Astc {
135                block: AstcBlock::B5x4,
136                channel: AstcChannel::Unorm,
137            },
138            GPUTextureFormat::Astc_5x4_unorm_srgb => wgpu_types::TextureFormat::Astc {
139                block: AstcBlock::B5x4,
140                channel: AstcChannel::UnormSrgb,
141            },
142            GPUTextureFormat::Astc_5x5_unorm => wgpu_types::TextureFormat::Astc {
143                block: AstcBlock::B5x5,
144                channel: AstcChannel::Unorm,
145            },
146            GPUTextureFormat::Astc_5x5_unorm_srgb => wgpu_types::TextureFormat::Astc {
147                block: AstcBlock::B5x5,
148                channel: AstcChannel::UnormSrgb,
149            },
150            GPUTextureFormat::Astc_6x5_unorm => wgpu_types::TextureFormat::Astc {
151                block: AstcBlock::B6x5,
152                channel: AstcChannel::Unorm,
153            },
154            GPUTextureFormat::Astc_6x5_unorm_srgb => wgpu_types::TextureFormat::Astc {
155                block: AstcBlock::B6x5,
156                channel: AstcChannel::UnormSrgb,
157            },
158            GPUTextureFormat::Astc_6x6_unorm => wgpu_types::TextureFormat::Astc {
159                block: AstcBlock::B6x6,
160                channel: AstcChannel::Unorm,
161            },
162            GPUTextureFormat::Astc_6x6_unorm_srgb => wgpu_types::TextureFormat::Astc {
163                block: AstcBlock::B6x6,
164                channel: AstcChannel::UnormSrgb,
165            },
166            GPUTextureFormat::Astc_8x5_unorm => wgpu_types::TextureFormat::Astc {
167                block: AstcBlock::B8x5,
168                channel: AstcChannel::Unorm,
169            },
170            GPUTextureFormat::Astc_8x5_unorm_srgb => wgpu_types::TextureFormat::Astc {
171                block: AstcBlock::B8x5,
172                channel: AstcChannel::UnormSrgb,
173            },
174            GPUTextureFormat::Astc_8x6_unorm => wgpu_types::TextureFormat::Astc {
175                block: AstcBlock::B8x6,
176                channel: AstcChannel::Unorm,
177            },
178            GPUTextureFormat::Astc_8x6_unorm_srgb => wgpu_types::TextureFormat::Astc {
179                block: AstcBlock::B8x6,
180                channel: AstcChannel::UnormSrgb,
181            },
182            GPUTextureFormat::Astc_8x8_unorm => wgpu_types::TextureFormat::Astc {
183                block: AstcBlock::B8x8,
184                channel: AstcChannel::Unorm,
185            },
186            GPUTextureFormat::Astc_8x8_unorm_srgb => wgpu_types::TextureFormat::Astc {
187                block: AstcBlock::B8x8,
188                channel: AstcChannel::UnormSrgb,
189            },
190            GPUTextureFormat::Astc_10x5_unorm => wgpu_types::TextureFormat::Astc {
191                block: AstcBlock::B10x5,
192                channel: AstcChannel::Unorm,
193            },
194            GPUTextureFormat::Astc_10x5_unorm_srgb => wgpu_types::TextureFormat::Astc {
195                block: AstcBlock::B10x5,
196                channel: AstcChannel::UnormSrgb,
197            },
198            GPUTextureFormat::Astc_10x6_unorm => wgpu_types::TextureFormat::Astc {
199                block: AstcBlock::B10x6,
200                channel: AstcChannel::Unorm,
201            },
202            GPUTextureFormat::Astc_10x6_unorm_srgb => wgpu_types::TextureFormat::Astc {
203                block: AstcBlock::B10x6,
204                channel: AstcChannel::UnormSrgb,
205            },
206            GPUTextureFormat::Astc_10x8_unorm => wgpu_types::TextureFormat::Astc {
207                block: AstcBlock::B10x8,
208                channel: AstcChannel::Unorm,
209            },
210            GPUTextureFormat::Astc_10x8_unorm_srgb => wgpu_types::TextureFormat::Astc {
211                block: AstcBlock::B10x8,
212                channel: AstcChannel::UnormSrgb,
213            },
214            GPUTextureFormat::Astc_10x10_unorm => wgpu_types::TextureFormat::Astc {
215                block: AstcBlock::B10x10,
216                channel: AstcChannel::Unorm,
217            },
218            GPUTextureFormat::Astc_10x10_unorm_srgb => wgpu_types::TextureFormat::Astc {
219                block: AstcBlock::B10x10,
220                channel: AstcChannel::UnormSrgb,
221            },
222            GPUTextureFormat::Astc_12x10_unorm => wgpu_types::TextureFormat::Astc {
223                block: AstcBlock::B12x10,
224                channel: AstcChannel::Unorm,
225            },
226            GPUTextureFormat::Astc_12x10_unorm_srgb => wgpu_types::TextureFormat::Astc {
227                block: AstcBlock::B12x10,
228                channel: AstcChannel::UnormSrgb,
229            },
230            GPUTextureFormat::Astc_12x12_unorm => wgpu_types::TextureFormat::Astc {
231                block: AstcBlock::B12x12,
232                channel: AstcChannel::Unorm,
233            },
234            GPUTextureFormat::Astc_12x12_unorm_srgb => wgpu_types::TextureFormat::Astc {
235                block: AstcBlock::B12x12,
236                channel: AstcChannel::UnormSrgb,
237            },
238        }
239    }
240}
241
242impl TryConvert<wgpu_types::Extent3d> for &GPUExtent3D {
243    type Error = Error;
244
245    fn try_convert(self) -> Result<wgpu_types::Extent3d, Self::Error> {
246        match *self {
247            GPUExtent3D::GPUExtent3DDict(ref dict) => Ok(wgpu_types::Extent3d {
248                width: dict.width,
249                height: dict.height,
250                depth_or_array_layers: dict.depthOrArrayLayers,
251            }),
252            GPUExtent3D::RangeEnforcedUnsignedLongSequence(ref v) => {
253                // https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpuextent3d-shape
254                if v.is_empty() || v.len() > 3 {
255                    Err(Error::Type(
256                        c"GPUExtent3D size must be between 1 and 3 (inclusive)".to_owned(),
257                    ))
258                } else {
259                    Ok(wgpu_types::Extent3d {
260                        width: v[0],
261                        height: v.get(1).copied().unwrap_or(1),
262                        depth_or_array_layers: v.get(2).copied().unwrap_or(1),
263                    })
264                }
265            },
266        }
267    }
268}
269
270impl Convert<wgpu_types::TexelCopyBufferLayout> for &GPUTexelCopyBufferLayout {
271    fn convert(self) -> wgpu_types::TexelCopyBufferLayout {
272        wgpu_types::TexelCopyBufferLayout {
273            offset: self.offset as wgpu_types::BufferAddress,
274            bytes_per_row: self.bytesPerRow,
275            rows_per_image: self.rowsPerImage,
276        }
277    }
278}
279
280impl Convert<wgpu_types::VertexFormat> for GPUVertexFormat {
281    fn convert(self) -> wgpu_types::VertexFormat {
282        match self {
283            GPUVertexFormat::Uint8 => wgpu_types::VertexFormat::Uint8,
284            GPUVertexFormat::Uint8x2 => wgpu_types::VertexFormat::Uint8x2,
285            GPUVertexFormat::Uint8x4 => wgpu_types::VertexFormat::Uint8x4,
286            GPUVertexFormat::Sint8 => wgpu_types::VertexFormat::Sint8,
287            GPUVertexFormat::Sint8x2 => wgpu_types::VertexFormat::Sint8x2,
288            GPUVertexFormat::Sint8x4 => wgpu_types::VertexFormat::Sint8x4,
289            GPUVertexFormat::Unorm8 => wgpu_types::VertexFormat::Unorm8,
290            GPUVertexFormat::Unorm8x2 => wgpu_types::VertexFormat::Unorm8x2,
291            GPUVertexFormat::Unorm8x4 => wgpu_types::VertexFormat::Unorm8x4,
292            GPUVertexFormat::Snorm8 => wgpu_types::VertexFormat::Snorm8,
293            GPUVertexFormat::Snorm8x2 => wgpu_types::VertexFormat::Snorm8x2,
294            GPUVertexFormat::Snorm8x4 => wgpu_types::VertexFormat::Snorm8x4,
295            GPUVertexFormat::Uint16 => wgpu_types::VertexFormat::Uint16,
296            GPUVertexFormat::Uint16x2 => wgpu_types::VertexFormat::Uint16x2,
297            GPUVertexFormat::Uint16x4 => wgpu_types::VertexFormat::Uint16x4,
298            GPUVertexFormat::Sint16 => wgpu_types::VertexFormat::Sint16,
299            GPUVertexFormat::Sint16x2 => wgpu_types::VertexFormat::Sint16x2,
300            GPUVertexFormat::Sint16x4 => wgpu_types::VertexFormat::Sint16x4,
301            GPUVertexFormat::Unorm16 => wgpu_types::VertexFormat::Unorm16,
302            GPUVertexFormat::Unorm16x2 => wgpu_types::VertexFormat::Unorm16x2,
303            GPUVertexFormat::Unorm16x4 => wgpu_types::VertexFormat::Unorm16x4,
304            GPUVertexFormat::Snorm16 => wgpu_types::VertexFormat::Snorm16,
305            GPUVertexFormat::Snorm16x2 => wgpu_types::VertexFormat::Snorm16x2,
306            GPUVertexFormat::Snorm16x4 => wgpu_types::VertexFormat::Snorm16x4,
307            GPUVertexFormat::Float16 => wgpu_types::VertexFormat::Float16,
308            GPUVertexFormat::Float16x2 => wgpu_types::VertexFormat::Float16x2,
309            GPUVertexFormat::Float16x4 => wgpu_types::VertexFormat::Float16x4,
310            GPUVertexFormat::Float32 => wgpu_types::VertexFormat::Float32,
311            GPUVertexFormat::Float32x2 => wgpu_types::VertexFormat::Float32x2,
312            GPUVertexFormat::Float32x3 => wgpu_types::VertexFormat::Float32x3,
313            GPUVertexFormat::Float32x4 => wgpu_types::VertexFormat::Float32x4,
314            GPUVertexFormat::Uint32 => wgpu_types::VertexFormat::Uint32,
315            GPUVertexFormat::Uint32x2 => wgpu_types::VertexFormat::Uint32x2,
316            GPUVertexFormat::Uint32x3 => wgpu_types::VertexFormat::Uint32x3,
317            GPUVertexFormat::Uint32x4 => wgpu_types::VertexFormat::Uint32x4,
318            GPUVertexFormat::Sint32 => wgpu_types::VertexFormat::Sint32,
319            GPUVertexFormat::Sint32x2 => wgpu_types::VertexFormat::Sint32x2,
320            GPUVertexFormat::Sint32x3 => wgpu_types::VertexFormat::Sint32x3,
321            GPUVertexFormat::Sint32x4 => wgpu_types::VertexFormat::Sint32x4,
322            GPUVertexFormat::Unorm10_10_10_2 => wgpu_types::VertexFormat::Unorm10_10_10_2,
323            GPUVertexFormat::Unorm8x4_bgra => wgpu_types::VertexFormat::Unorm8x4Bgra,
324        }
325    }
326}
327
328impl Convert<wgpu_types::PrimitiveState> for &GPUPrimitiveState {
329    fn convert(self) -> wgpu_types::PrimitiveState {
330        wgpu_types::PrimitiveState {
331            topology: self.topology.convert(),
332            strip_index_format: self
333                .stripIndexFormat
334                .map(|index_format| match index_format {
335                    GPUIndexFormat::Uint16 => wgpu_types::IndexFormat::Uint16,
336                    GPUIndexFormat::Uint32 => wgpu_types::IndexFormat::Uint32,
337                }),
338            front_face: match self.frontFace {
339                GPUFrontFace::Ccw => wgpu_types::FrontFace::Ccw,
340                GPUFrontFace::Cw => wgpu_types::FrontFace::Cw,
341            },
342            cull_mode: match self.cullMode {
343                GPUCullMode::None => None,
344                GPUCullMode::Front => Some(wgpu_types::Face::Front),
345                GPUCullMode::Back => Some(wgpu_types::Face::Back),
346            },
347            unclipped_depth: self.clampDepth,
348            ..Default::default()
349        }
350    }
351}
352
353impl Convert<wgpu_types::PrimitiveTopology> for &GPUPrimitiveTopology {
354    fn convert(self) -> wgpu_types::PrimitiveTopology {
355        match self {
356            GPUPrimitiveTopology::Point_list => wgpu_types::PrimitiveTopology::PointList,
357            GPUPrimitiveTopology::Line_list => wgpu_types::PrimitiveTopology::LineList,
358            GPUPrimitiveTopology::Line_strip => wgpu_types::PrimitiveTopology::LineStrip,
359            GPUPrimitiveTopology::Triangle_list => wgpu_types::PrimitiveTopology::TriangleList,
360            GPUPrimitiveTopology::Triangle_strip => wgpu_types::PrimitiveTopology::TriangleStrip,
361        }
362    }
363}
364
365impl Convert<wgpu_types::AddressMode> for GPUAddressMode {
366    fn convert(self) -> wgpu_types::AddressMode {
367        match self {
368            GPUAddressMode::Clamp_to_edge => wgpu_types::AddressMode::ClampToEdge,
369            GPUAddressMode::Repeat => wgpu_types::AddressMode::Repeat,
370            GPUAddressMode::Mirror_repeat => wgpu_types::AddressMode::MirrorRepeat,
371        }
372    }
373}
374
375impl Convert<wgpu_types::FilterMode> for GPUFilterMode {
376    fn convert(self) -> wgpu_types::FilterMode {
377        match self {
378            GPUFilterMode::Nearest => wgpu_types::FilterMode::Nearest,
379            GPUFilterMode::Linear => wgpu_types::FilterMode::Linear,
380        }
381    }
382}
383
384impl Convert<wgpu_types::MipmapFilterMode> for GPUMipmapFilterMode {
385    fn convert(self) -> wgpu_types::MipmapFilterMode {
386        match self {
387            GPUMipmapFilterMode::Nearest => wgpu_types::MipmapFilterMode::Nearest,
388            GPUMipmapFilterMode::Linear => wgpu_types::MipmapFilterMode::Linear,
389        }
390    }
391}
392
393impl Convert<wgpu_types::TextureViewDimension> for GPUTextureViewDimension {
394    fn convert(self) -> wgpu_types::TextureViewDimension {
395        match self {
396            GPUTextureViewDimension::_1d => wgpu_types::TextureViewDimension::D1,
397            GPUTextureViewDimension::_2d => wgpu_types::TextureViewDimension::D2,
398            GPUTextureViewDimension::_2d_array => wgpu_types::TextureViewDimension::D2Array,
399            GPUTextureViewDimension::Cube => wgpu_types::TextureViewDimension::Cube,
400            GPUTextureViewDimension::Cube_array => wgpu_types::TextureViewDimension::CubeArray,
401            GPUTextureViewDimension::_3d => wgpu_types::TextureViewDimension::D3,
402        }
403    }
404}
405
406impl Convert<wgpu_types::CompareFunction> for GPUCompareFunction {
407    fn convert(self) -> wgpu_types::CompareFunction {
408        match self {
409            GPUCompareFunction::Never => wgpu_types::CompareFunction::Never,
410            GPUCompareFunction::Less => wgpu_types::CompareFunction::Less,
411            GPUCompareFunction::Equal => wgpu_types::CompareFunction::Equal,
412            GPUCompareFunction::Less_equal => wgpu_types::CompareFunction::LessEqual,
413            GPUCompareFunction::Greater => wgpu_types::CompareFunction::Greater,
414            GPUCompareFunction::Not_equal => wgpu_types::CompareFunction::NotEqual,
415            GPUCompareFunction::Greater_equal => wgpu_types::CompareFunction::GreaterEqual,
416            GPUCompareFunction::Always => wgpu_types::CompareFunction::Always,
417        }
418    }
419}
420
421impl Convert<wgpu_types::BlendFactor> for &GPUBlendFactor {
422    fn convert(self) -> wgpu_types::BlendFactor {
423        match self {
424            GPUBlendFactor::Zero => wgpu_types::BlendFactor::Zero,
425            GPUBlendFactor::One => wgpu_types::BlendFactor::One,
426            GPUBlendFactor::Src => wgpu_types::BlendFactor::Src,
427            GPUBlendFactor::One_minus_src => wgpu_types::BlendFactor::OneMinusSrc,
428            GPUBlendFactor::Src_alpha => wgpu_types::BlendFactor::SrcAlpha,
429            GPUBlendFactor::One_minus_src_alpha => wgpu_types::BlendFactor::OneMinusSrcAlpha,
430            GPUBlendFactor::Dst => wgpu_types::BlendFactor::Dst,
431            GPUBlendFactor::One_minus_dst => wgpu_types::BlendFactor::OneMinusDst,
432            GPUBlendFactor::Dst_alpha => wgpu_types::BlendFactor::DstAlpha,
433            GPUBlendFactor::One_minus_dst_alpha => wgpu_types::BlendFactor::OneMinusDstAlpha,
434            GPUBlendFactor::Src_alpha_saturated => wgpu_types::BlendFactor::SrcAlphaSaturated,
435            GPUBlendFactor::Constant => wgpu_types::BlendFactor::Constant,
436            GPUBlendFactor::One_minus_constant => wgpu_types::BlendFactor::OneMinusConstant,
437            GPUBlendFactor::Src1 => wgpu_types::BlendFactor::Src1,
438            GPUBlendFactor::One_minus_src1 => wgpu_types::BlendFactor::OneMinusSrc1,
439            GPUBlendFactor::Src1_alpha => wgpu_types::BlendFactor::Src1Alpha,
440            GPUBlendFactor::One_minus_src1_alpha => wgpu_types::BlendFactor::OneMinusSrc1Alpha,
441        }
442    }
443}
444
445impl Convert<wgpu_types::BlendComponent> for &GPUBlendComponent {
446    fn convert(self) -> wgpu_types::BlendComponent {
447        wgpu_types::BlendComponent {
448            src_factor: self.srcFactor.convert(),
449            dst_factor: self.dstFactor.convert(),
450            operation: match self.operation {
451                GPUBlendOperation::Add => wgpu_types::BlendOperation::Add,
452                GPUBlendOperation::Subtract => wgpu_types::BlendOperation::Subtract,
453                GPUBlendOperation::Reverse_subtract => wgpu_types::BlendOperation::ReverseSubtract,
454                GPUBlendOperation::Min => wgpu_types::BlendOperation::Min,
455                GPUBlendOperation::Max => wgpu_types::BlendOperation::Max,
456            },
457        }
458    }
459}
460
461pub(crate) fn convert_load_op<T>(load: &GPULoadOp, clear: T) -> wgpu_com::LoadOp<T> {
462    match load {
463        GPULoadOp::Load => wgpu_com::LoadOp::Load,
464        GPULoadOp::Clear => wgpu_com::LoadOp::Clear(clear),
465    }
466}
467
468impl Convert<wgpu_com::StoreOp> for &GPUStoreOp {
469    fn convert(self) -> wgpu_com::StoreOp {
470        match self {
471            GPUStoreOp::Store => wgpu_com::StoreOp::Store,
472            GPUStoreOp::Discard => wgpu_com::StoreOp::Discard,
473        }
474    }
475}
476
477impl Convert<wgpu_types::StencilOperation> for GPUStencilOperation {
478    fn convert(self) -> wgpu_types::StencilOperation {
479        match self {
480            GPUStencilOperation::Keep => wgpu_types::StencilOperation::Keep,
481            GPUStencilOperation::Zero => wgpu_types::StencilOperation::Zero,
482            GPUStencilOperation::Replace => wgpu_types::StencilOperation::Replace,
483            GPUStencilOperation::Invert => wgpu_types::StencilOperation::Invert,
484            GPUStencilOperation::Increment_clamp => wgpu_types::StencilOperation::IncrementClamp,
485            GPUStencilOperation::Decrement_clamp => wgpu_types::StencilOperation::DecrementClamp,
486            GPUStencilOperation::Increment_wrap => wgpu_types::StencilOperation::IncrementWrap,
487            GPUStencilOperation::Decrement_wrap => wgpu_types::StencilOperation::DecrementWrap,
488        }
489    }
490}
491
492impl Convert<wgpu_com::TexelCopyBufferInfo> for &GPUTexelCopyBufferInfo {
493    fn convert(self) -> wgpu_com::TexelCopyBufferInfo {
494        wgpu_com::TexelCopyBufferInfo {
495            buffer: self.buffer.id().0,
496            layout: self.parent.convert(),
497        }
498    }
499}
500
501impl TryConvert<wgpu_types::Origin3d> for &GPUOrigin3D {
502    type Error = Error;
503
504    fn try_convert(self) -> Result<wgpu_types::Origin3d, Self::Error> {
505        match self {
506            GPUOrigin3D::RangeEnforcedUnsignedLongSequence(v) => {
507                // https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpuorigin3d-shape
508                if v.len() > 3 {
509                    Err(Error::Type(
510                        c"sequence is too long for GPUOrigin3D".to_owned(),
511                    ))
512                } else {
513                    Ok(wgpu_types::Origin3d {
514                        x: v.first().copied().unwrap_or(0),
515                        y: v.get(1).copied().unwrap_or(0),
516                        z: v.get(2).copied().unwrap_or(0),
517                    })
518                }
519            },
520            GPUOrigin3D::GPUOrigin3DDict(d) => Ok(wgpu_types::Origin3d {
521                x: d.x,
522                y: d.y,
523                z: d.z,
524            }),
525        }
526    }
527}
528
529impl TryConvert<wgpu_com::TexelCopyTextureInfo> for &GPUTexelCopyTextureInfo {
530    type Error = Error;
531
532    fn try_convert(self) -> Result<wgpu_com::TexelCopyTextureInfo, Self::Error> {
533        Ok(wgpu_com::TexelCopyTextureInfo {
534            texture: self.texture.id().0,
535            mip_level: self.mipLevel,
536            origin: self
537                .origin
538                .as_ref()
539                .map(TryConvert::<wgpu_types::Origin3d>::try_convert)
540                .transpose()?
541                .unwrap_or_default(),
542            aspect: match self.aspect {
543                GPUTextureAspect::All => wgpu_types::TextureAspect::All,
544                GPUTextureAspect::Stencil_only => wgpu_types::TextureAspect::StencilOnly,
545                GPUTextureAspect::Depth_only => wgpu_types::TextureAspect::DepthOnly,
546            },
547        })
548    }
549}
550
551impl<'a> Convert<Option<Cow<'a, str>>> for &GPUObjectDescriptorBase {
552    fn convert(self) -> Option<Cow<'a, str>> {
553        if self.label.is_empty() {
554            None
555        } else {
556            Some(Cow::Owned(self.label.to_string()))
557        }
558    }
559}
560
561pub(crate) fn convert_bind_group_layout_entry(
562    bgle: &GPUBindGroupLayoutEntry,
563    device: &GPUDevice,
564) -> Fallible<Result<wgpu_types::BindGroupLayoutEntry, webgpu_traits::Error>> {
565    let number_of_provided_bindings = bgle.buffer.is_some() as u8 +
566        bgle.sampler.is_some() as u8 +
567        bgle.storageTexture.is_some() as u8 +
568        bgle.texture.is_some() as u8;
569    let ty = if let Some(buffer) = &bgle.buffer {
570        Some(wgpu_types::BindingType::Buffer {
571            ty: match buffer.type_ {
572                GPUBufferBindingType::Uniform => wgpu_types::BufferBindingType::Uniform,
573                GPUBufferBindingType::Storage => {
574                    wgpu_types::BufferBindingType::Storage { read_only: false }
575                },
576                GPUBufferBindingType::Read_only_storage => {
577                    wgpu_types::BufferBindingType::Storage { read_only: true }
578                },
579            },
580            has_dynamic_offset: buffer.hasDynamicOffset,
581            min_binding_size: NonZeroU64::new(buffer.minBindingSize),
582        })
583    } else if let Some(sampler) = &bgle.sampler {
584        Some(wgpu_types::BindingType::Sampler(match sampler.type_ {
585            GPUSamplerBindingType::Filtering => wgpu_types::SamplerBindingType::Filtering,
586            GPUSamplerBindingType::Non_filtering => wgpu_types::SamplerBindingType::NonFiltering,
587            GPUSamplerBindingType::Comparison => wgpu_types::SamplerBindingType::Comparison,
588        }))
589    } else if let Some(storage) = &bgle.storageTexture {
590        Some(wgpu_types::BindingType::StorageTexture {
591            access: match storage.access {
592                GPUStorageTextureAccess::Write_only => wgpu_types::StorageTextureAccess::WriteOnly,
593                GPUStorageTextureAccess::Read_only => wgpu_types::StorageTextureAccess::ReadOnly,
594                GPUStorageTextureAccess::Read_write => wgpu_types::StorageTextureAccess::ReadWrite,
595            },
596            format: device.validate_texture_format_required_features(&storage.format)?,
597            view_dimension: storage.viewDimension.convert(),
598        })
599    } else if let Some(texture) = &bgle.texture {
600        Some(wgpu_types::BindingType::Texture {
601            sample_type: match texture.sampleType {
602                GPUTextureSampleType::Float => {
603                    wgpu_types::TextureSampleType::Float { filterable: true }
604                },
605                GPUTextureSampleType::Unfilterable_float => {
606                    wgpu_types::TextureSampleType::Float { filterable: false }
607                },
608                GPUTextureSampleType::Depth => wgpu_types::TextureSampleType::Depth,
609                GPUTextureSampleType::Sint => wgpu_types::TextureSampleType::Sint,
610                GPUTextureSampleType::Uint => wgpu_types::TextureSampleType::Uint,
611            },
612            view_dimension: texture.viewDimension.convert(),
613            multisampled: texture.multisampled,
614        })
615    } else {
616        assert_eq!(number_of_provided_bindings, 0);
617        None
618    };
619    // Check for number of bindings should actually be done in device-timeline,
620    // but we do it last on content-timeline to have some visible effect
621    let ty = if number_of_provided_bindings != 1 {
622        None
623    } else {
624        ty
625    }
626    .ok_or(webgpu_traits::Error::Validation(
627        "Exactly on entry type must be provided".to_string(),
628    ));
629
630    Ok(ty.map(|ty| wgpu_types::BindGroupLayoutEntry {
631        binding: bgle.binding,
632        visibility: wgpu_types::ShaderStages::from_bits_retain(bgle.visibility),
633        ty,
634        count: None,
635    }))
636}
637
638pub(crate) fn convert_texture_descriptor(
639    descriptor: &GPUTextureDescriptor,
640    device: &GPUDevice,
641) -> Fallible<(TextureDescriptor<'static>, wgpu_types::Extent3d)> {
642    let size = (&descriptor.size).try_convert()?;
643    let desc = TextureDescriptor {
644        label: (&descriptor.parent).convert(),
645        size,
646        mip_level_count: descriptor.mipLevelCount,
647        sample_count: descriptor.sampleCount,
648        dimension: descriptor.dimension.convert(),
649        format: device.validate_texture_format_required_features(&descriptor.format)?,
650        usage: wgpu_types::TextureUsages::from_bits_retain(descriptor.usage),
651        view_formats: descriptor
652            .viewFormats
653            .iter()
654            .map(|tf| device.validate_texture_format_required_features(tf))
655            .collect::<Fallible<_>>()?,
656    };
657    Ok((desc, size))
658}
659
660impl TryConvert<wgpu_types::Color> for &GPUColor {
661    type Error = Error;
662
663    fn try_convert(self) -> Result<wgpu_types::Color, Self::Error> {
664        match self {
665            GPUColor::DoubleSequence(s) => {
666                // https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpucolor-shape
667                if s.len() != 4 {
668                    Err(Error::Type(c"GPUColor sequence must be len 4".to_owned()))
669                } else {
670                    Ok(wgpu_types::Color {
671                        r: *s[0],
672                        g: *s[1],
673                        b: *s[2],
674                        a: *s[3],
675                    })
676                }
677            },
678            GPUColor::GPUColorDict(d) => Ok(wgpu_types::Color {
679                r: *d.r,
680                g: *d.g,
681                b: *d.b,
682                a: *d.a,
683            }),
684        }
685    }
686}
687
688impl<'a> Convert<ProgrammableStageDescriptor<'a>> for &GPUProgrammableStage {
689    fn convert(self) -> ProgrammableStageDescriptor<'a> {
690        ProgrammableStageDescriptor {
691            module: self.module.id().0,
692            entry_point: self
693                .entryPoint
694                .as_ref()
695                .map(|ep| Cow::Owned(ep.to_string())),
696            constants: self
697                .constants
698                .as_ref()
699                .map(|records| records.iter().map(|(k, v)| (k.0.clone(), **v)).collect())
700                .unwrap_or_default(),
701            zero_initialize_workgroup_memory: true,
702        }
703    }
704}
705
706impl Convert<WebGPUTextureView> for &GPUTextureOrGPUTextureView {
707    fn convert(self) -> WebGPUTextureView {
708        match self {
709            GPUTextureOrGPUTextureView::GPUTextureView(view) => view.id(),
710            GPUTextureOrGPUTextureView::GPUTexture(texture) => texture.get_default_view(),
711        }
712    }
713}
714
715impl<'a> Convert<BindGroupEntry<'a>> for &GPUBindGroupEntry {
716    fn convert(self) -> BindGroupEntry<'a> {
717        BindGroupEntry {
718            binding: self.binding,
719            resource: match self.resource {
720                GPUBindingResource::GPUSampler(ref s) => BindingResource::Sampler(s.id().0),
721                GPUBindingResource::GPUTextureView(ref t) => BindingResource::TextureView(t.id().0),
722                GPUBindingResource::GPUTexture(ref t) => {
723                    BindingResource::TextureView(t.get_default_view().0)
724                },
725                GPUBindingResource::GPUBufferBinding(ref b) => {
726                    BindingResource::Buffer(BufferBinding {
727                        buffer: b.buffer.id().0,
728                        offset: b.offset,
729                        size: b.size,
730                    })
731                },
732                GPUBindingResource::GPUBuffer(ref b) => BindingResource::Buffer(BufferBinding {
733                    buffer: b.id().0,
734                    offset: 0,
735                    size: None,
736                }),
737            },
738        }
739    }
740}
741
742impl Convert<wgpu_types::TextureDimension> for GPUTextureDimension {
743    fn convert(self) -> wgpu_types::TextureDimension {
744        match self {
745            GPUTextureDimension::_1d => wgpu_types::TextureDimension::D1,
746            GPUTextureDimension::_2d => wgpu_types::TextureDimension::D2,
747            GPUTextureDimension::_3d => wgpu_types::TextureDimension::D3,
748        }
749    }
750}