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