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 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                        c"GPUExtent3D size must be between 1 and 3 (inclusive)".to_owned(),
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
351// TODO(sagudev): this will become GPUMipmapFilterMode once the webidl is updated
352impl Convert<wgpu_types::MipmapFilterMode> for GPUFilterMode {
353    fn convert(self) -> wgpu_types::MipmapFilterMode {
354        match self {
355            GPUFilterMode::Nearest => wgpu_types::MipmapFilterMode::Nearest,
356            GPUFilterMode::Linear => wgpu_types::MipmapFilterMode::Linear,
357        }
358    }
359}
360
361impl Convert<wgpu_types::TextureViewDimension> for GPUTextureViewDimension {
362    fn convert(self) -> wgpu_types::TextureViewDimension {
363        match self {
364            GPUTextureViewDimension::_1d => wgpu_types::TextureViewDimension::D1,
365            GPUTextureViewDimension::_2d => wgpu_types::TextureViewDimension::D2,
366            GPUTextureViewDimension::_2d_array => wgpu_types::TextureViewDimension::D2Array,
367            GPUTextureViewDimension::Cube => wgpu_types::TextureViewDimension::Cube,
368            GPUTextureViewDimension::Cube_array => wgpu_types::TextureViewDimension::CubeArray,
369            GPUTextureViewDimension::_3d => wgpu_types::TextureViewDimension::D3,
370        }
371    }
372}
373
374impl Convert<wgpu_types::CompareFunction> for GPUCompareFunction {
375    fn convert(self) -> wgpu_types::CompareFunction {
376        match self {
377            GPUCompareFunction::Never => wgpu_types::CompareFunction::Never,
378            GPUCompareFunction::Less => wgpu_types::CompareFunction::Less,
379            GPUCompareFunction::Equal => wgpu_types::CompareFunction::Equal,
380            GPUCompareFunction::Less_equal => wgpu_types::CompareFunction::LessEqual,
381            GPUCompareFunction::Greater => wgpu_types::CompareFunction::Greater,
382            GPUCompareFunction::Not_equal => wgpu_types::CompareFunction::NotEqual,
383            GPUCompareFunction::Greater_equal => wgpu_types::CompareFunction::GreaterEqual,
384            GPUCompareFunction::Always => wgpu_types::CompareFunction::Always,
385        }
386    }
387}
388
389impl Convert<wgpu_types::BlendFactor> for &GPUBlendFactor {
390    fn convert(self) -> wgpu_types::BlendFactor {
391        match self {
392            GPUBlendFactor::Zero => wgpu_types::BlendFactor::Zero,
393            GPUBlendFactor::One => wgpu_types::BlendFactor::One,
394            GPUBlendFactor::Src => wgpu_types::BlendFactor::Src,
395            GPUBlendFactor::One_minus_src => wgpu_types::BlendFactor::OneMinusSrc,
396            GPUBlendFactor::Src_alpha => wgpu_types::BlendFactor::SrcAlpha,
397            GPUBlendFactor::One_minus_src_alpha => wgpu_types::BlendFactor::OneMinusSrcAlpha,
398            GPUBlendFactor::Dst => wgpu_types::BlendFactor::Dst,
399            GPUBlendFactor::One_minus_dst => wgpu_types::BlendFactor::OneMinusDst,
400            GPUBlendFactor::Dst_alpha => wgpu_types::BlendFactor::DstAlpha,
401            GPUBlendFactor::One_minus_dst_alpha => wgpu_types::BlendFactor::OneMinusDstAlpha,
402            GPUBlendFactor::Src_alpha_saturated => wgpu_types::BlendFactor::SrcAlphaSaturated,
403            GPUBlendFactor::Constant => wgpu_types::BlendFactor::Constant,
404            GPUBlendFactor::One_minus_constant => wgpu_types::BlendFactor::OneMinusConstant,
405        }
406    }
407}
408
409impl Convert<wgpu_types::BlendComponent> for &GPUBlendComponent {
410    fn convert(self) -> wgpu_types::BlendComponent {
411        wgpu_types::BlendComponent {
412            src_factor: self.srcFactor.convert(),
413            dst_factor: self.dstFactor.convert(),
414            operation: match self.operation {
415                GPUBlendOperation::Add => wgpu_types::BlendOperation::Add,
416                GPUBlendOperation::Subtract => wgpu_types::BlendOperation::Subtract,
417                GPUBlendOperation::Reverse_subtract => wgpu_types::BlendOperation::ReverseSubtract,
418                GPUBlendOperation::Min => wgpu_types::BlendOperation::Min,
419                GPUBlendOperation::Max => wgpu_types::BlendOperation::Max,
420            },
421        }
422    }
423}
424
425pub(crate) fn convert_load_op<T>(load: &GPULoadOp, clear: T) -> wgpu_com::LoadOp<T> {
426    match load {
427        GPULoadOp::Load => wgpu_com::LoadOp::Load,
428        GPULoadOp::Clear => wgpu_com::LoadOp::Clear(clear),
429    }
430}
431
432impl Convert<wgpu_com::StoreOp> for &GPUStoreOp {
433    fn convert(self) -> wgpu_com::StoreOp {
434        match self {
435            GPUStoreOp::Store => wgpu_com::StoreOp::Store,
436            GPUStoreOp::Discard => wgpu_com::StoreOp::Discard,
437        }
438    }
439}
440
441impl Convert<wgpu_types::StencilOperation> for GPUStencilOperation {
442    fn convert(self) -> wgpu_types::StencilOperation {
443        match self {
444            GPUStencilOperation::Keep => wgpu_types::StencilOperation::Keep,
445            GPUStencilOperation::Zero => wgpu_types::StencilOperation::Zero,
446            GPUStencilOperation::Replace => wgpu_types::StencilOperation::Replace,
447            GPUStencilOperation::Invert => wgpu_types::StencilOperation::Invert,
448            GPUStencilOperation::Increment_clamp => wgpu_types::StencilOperation::IncrementClamp,
449            GPUStencilOperation::Decrement_clamp => wgpu_types::StencilOperation::DecrementClamp,
450            GPUStencilOperation::Increment_wrap => wgpu_types::StencilOperation::IncrementWrap,
451            GPUStencilOperation::Decrement_wrap => wgpu_types::StencilOperation::DecrementWrap,
452        }
453    }
454}
455
456impl Convert<wgpu_com::TexelCopyBufferInfo> for &GPUImageCopyBuffer {
457    fn convert(self) -> wgpu_com::TexelCopyBufferInfo {
458        wgpu_com::TexelCopyBufferInfo {
459            buffer: self.buffer.id().0,
460            layout: self.parent.convert(),
461        }
462    }
463}
464
465impl TryConvert<wgpu_types::Origin3d> for &GPUOrigin3D {
466    type Error = Error;
467
468    fn try_convert(self) -> Result<wgpu_types::Origin3d, Self::Error> {
469        match self {
470            GPUOrigin3D::RangeEnforcedUnsignedLongSequence(v) => {
471                // https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpuorigin3d-shape
472                if v.len() > 3 {
473                    Err(Error::Type(
474                        c"sequence is too long for GPUOrigin3D".to_owned(),
475                    ))
476                } else {
477                    Ok(wgpu_types::Origin3d {
478                        x: v.first().copied().unwrap_or(0),
479                        y: v.get(1).copied().unwrap_or(0),
480                        z: v.get(2).copied().unwrap_or(0),
481                    })
482                }
483            },
484            GPUOrigin3D::GPUOrigin3DDict(d) => Ok(wgpu_types::Origin3d {
485                x: d.x,
486                y: d.y,
487                z: d.z,
488            }),
489        }
490    }
491}
492
493impl TryConvert<wgpu_com::TexelCopyTextureInfo> for &GPUImageCopyTexture {
494    type Error = Error;
495
496    fn try_convert(self) -> Result<wgpu_com::TexelCopyTextureInfo, Self::Error> {
497        Ok(wgpu_com::TexelCopyTextureInfo {
498            texture: self.texture.id().0,
499            mip_level: self.mipLevel,
500            origin: self
501                .origin
502                .as_ref()
503                .map(TryConvert::<wgpu_types::Origin3d>::try_convert)
504                .transpose()?
505                .unwrap_or_default(),
506            aspect: match self.aspect {
507                GPUTextureAspect::All => wgpu_types::TextureAspect::All,
508                GPUTextureAspect::Stencil_only => wgpu_types::TextureAspect::StencilOnly,
509                GPUTextureAspect::Depth_only => wgpu_types::TextureAspect::DepthOnly,
510            },
511        })
512    }
513}
514
515impl<'a> Convert<Option<Cow<'a, str>>> for &GPUObjectDescriptorBase {
516    fn convert(self) -> Option<Cow<'a, str>> {
517        if self.label.is_empty() {
518            None
519        } else {
520            Some(Cow::Owned(self.label.to_string()))
521        }
522    }
523}
524
525pub(crate) fn convert_bind_group_layout_entry(
526    bgle: &GPUBindGroupLayoutEntry,
527    device: &GPUDevice,
528) -> Fallible<Result<wgpu_types::BindGroupLayoutEntry, webgpu_traits::Error>> {
529    let number_of_provided_bindings = bgle.buffer.is_some() as u8 +
530        bgle.sampler.is_some() as u8 +
531        bgle.storageTexture.is_some() as u8 +
532        bgle.texture.is_some() as u8;
533    let ty = if let Some(buffer) = &bgle.buffer {
534        Some(wgpu_types::BindingType::Buffer {
535            ty: match buffer.type_ {
536                GPUBufferBindingType::Uniform => wgpu_types::BufferBindingType::Uniform,
537                GPUBufferBindingType::Storage => {
538                    wgpu_types::BufferBindingType::Storage { read_only: false }
539                },
540                GPUBufferBindingType::Read_only_storage => {
541                    wgpu_types::BufferBindingType::Storage { read_only: true }
542                },
543            },
544            has_dynamic_offset: buffer.hasDynamicOffset,
545            min_binding_size: NonZeroU64::new(buffer.minBindingSize),
546        })
547    } else if let Some(sampler) = &bgle.sampler {
548        Some(wgpu_types::BindingType::Sampler(match sampler.type_ {
549            GPUSamplerBindingType::Filtering => wgpu_types::SamplerBindingType::Filtering,
550            GPUSamplerBindingType::Non_filtering => wgpu_types::SamplerBindingType::NonFiltering,
551            GPUSamplerBindingType::Comparison => wgpu_types::SamplerBindingType::Comparison,
552        }))
553    } else if let Some(storage) = &bgle.storageTexture {
554        Some(wgpu_types::BindingType::StorageTexture {
555            access: match storage.access {
556                GPUStorageTextureAccess::Write_only => wgpu_types::StorageTextureAccess::WriteOnly,
557                GPUStorageTextureAccess::Read_only => wgpu_types::StorageTextureAccess::ReadOnly,
558                GPUStorageTextureAccess::Read_write => wgpu_types::StorageTextureAccess::ReadWrite,
559            },
560            format: device.validate_texture_format_required_features(&storage.format)?,
561            view_dimension: storage.viewDimension.convert(),
562        })
563    } else if let Some(texture) = &bgle.texture {
564        Some(wgpu_types::BindingType::Texture {
565            sample_type: match texture.sampleType {
566                GPUTextureSampleType::Float => {
567                    wgpu_types::TextureSampleType::Float { filterable: true }
568                },
569                GPUTextureSampleType::Unfilterable_float => {
570                    wgpu_types::TextureSampleType::Float { filterable: false }
571                },
572                GPUTextureSampleType::Depth => wgpu_types::TextureSampleType::Depth,
573                GPUTextureSampleType::Sint => wgpu_types::TextureSampleType::Sint,
574                GPUTextureSampleType::Uint => wgpu_types::TextureSampleType::Uint,
575            },
576            view_dimension: texture.viewDimension.convert(),
577            multisampled: texture.multisampled,
578        })
579    } else {
580        assert_eq!(number_of_provided_bindings, 0);
581        None
582    };
583    // Check for number of bindings should actually be done in device-timeline,
584    // but we do it last on content-timeline to have some visible effect
585    let ty = if number_of_provided_bindings != 1 {
586        None
587    } else {
588        ty
589    }
590    .ok_or(webgpu_traits::Error::Validation(
591        "Exactly on entry type must be provided".to_string(),
592    ));
593
594    Ok(ty.map(|ty| wgpu_types::BindGroupLayoutEntry {
595        binding: bgle.binding,
596        visibility: wgpu_types::ShaderStages::from_bits_retain(bgle.visibility),
597        ty,
598        count: None,
599    }))
600}
601
602pub(crate) fn convert_texture_descriptor(
603    descriptor: &GPUTextureDescriptor,
604    device: &GPUDevice,
605) -> Fallible<(TextureDescriptor<'static>, wgpu_types::Extent3d)> {
606    let size = (&descriptor.size).try_convert()?;
607    let desc = TextureDescriptor {
608        label: (&descriptor.parent).convert(),
609        size,
610        mip_level_count: descriptor.mipLevelCount,
611        sample_count: descriptor.sampleCount,
612        dimension: descriptor.dimension.convert(),
613        format: device.validate_texture_format_required_features(&descriptor.format)?,
614        usage: wgpu_types::TextureUsages::from_bits_retain(descriptor.usage),
615        view_formats: descriptor
616            .viewFormats
617            .iter()
618            .map(|tf| device.validate_texture_format_required_features(tf))
619            .collect::<Fallible<_>>()?,
620    };
621    Ok((desc, size))
622}
623
624impl TryConvert<wgpu_types::Color> for &GPUColor {
625    type Error = Error;
626
627    fn try_convert(self) -> Result<wgpu_types::Color, Self::Error> {
628        match self {
629            GPUColor::DoubleSequence(s) => {
630                // https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpucolor-shape
631                if s.len() != 4 {
632                    Err(Error::Type(c"GPUColor sequence must be len 4".to_owned()))
633                } else {
634                    Ok(wgpu_types::Color {
635                        r: *s[0],
636                        g: *s[1],
637                        b: *s[2],
638                        a: *s[3],
639                    })
640                }
641            },
642            GPUColor::GPUColorDict(d) => Ok(wgpu_types::Color {
643                r: *d.r,
644                g: *d.g,
645                b: *d.b,
646                a: *d.a,
647            }),
648        }
649    }
650}
651
652impl<'a> Convert<ProgrammableStageDescriptor<'a>> for &GPUProgrammableStage {
653    fn convert(self) -> ProgrammableStageDescriptor<'a> {
654        ProgrammableStageDescriptor {
655            module: self.module.id().0,
656            entry_point: self
657                .entryPoint
658                .as_ref()
659                .map(|ep| Cow::Owned(ep.to_string())),
660            constants: self
661                .constants
662                .as_ref()
663                .map(|records| records.iter().map(|(k, v)| (k.0.clone(), **v)).collect())
664                .unwrap_or_default(),
665            zero_initialize_workgroup_memory: true,
666        }
667    }
668}
669
670impl<'a> Convert<BindGroupEntry<'a>> for &GPUBindGroupEntry {
671    fn convert(self) -> BindGroupEntry<'a> {
672        BindGroupEntry {
673            binding: self.binding,
674            resource: match self.resource {
675                GPUBindingResource::GPUSampler(ref s) => BindingResource::Sampler(s.id().0),
676                GPUBindingResource::GPUTextureView(ref t) => BindingResource::TextureView(t.id().0),
677                GPUBindingResource::GPUBufferBinding(ref b) => {
678                    BindingResource::Buffer(BufferBinding {
679                        buffer: b.buffer.id().0,
680                        offset: b.offset,
681                        size: b.size,
682                    })
683                },
684            },
685        }
686    }
687}
688
689impl Convert<wgpu_types::TextureDimension> for GPUTextureDimension {
690    fn convert(self) -> wgpu_types::TextureDimension {
691        match self {
692            GPUTextureDimension::_1d => wgpu_types::TextureDimension::D1,
693            GPUTextureDimension::_2d => wgpu_types::TextureDimension::D2,
694            GPUTextureDimension::_3d => wgpu_types::TextureDimension::D3,
695        }
696    }
697}