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