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