Skip to main content

dawn_wgpu/
lib.rs

1#![allow(unexpected_cfgs, dead_code, unreachable_patterns)]
2
3use dawn_rs::*;
4use std::fmt;
5use std::future::Future;
6use std::pin::Pin;
7use std::sync::{Arc, Mutex};
8use std::task::{Context, Poll, Waker};
9
10use wgpu::custom::*;
11
12#[derive(Debug)]
13pub enum WgpuCompatError {
14    NotCustomBackend,
15    NotDawnBackend,
16}
17
18impl fmt::Display for WgpuCompatError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            WgpuCompatError::NotCustomBackend => write!(f, "wgpu object is not a custom backend"),
22            WgpuCompatError::NotDawnBackend => write!(f, "wgpu custom backend is not dawn-rs"),
23        }
24    }
25}
26
27impl std::error::Error for WgpuCompatError {}
28
29#[derive(Debug, Clone)]
30struct DawnInstance {
31    inner: Instance,
32}
33
34#[derive(Debug, Clone)]
35struct DawnAdapter {
36    inner: Adapter,
37}
38
39#[derive(Debug, Clone)]
40struct DawnDevice {
41    inner: Device,
42}
43
44#[derive(Debug, Clone)]
45struct DawnQueue {
46    inner: Queue,
47}
48
49#[derive(Debug, Clone)]
50struct DawnShaderModule {
51    inner: ShaderModule,
52}
53
54#[derive(Debug, Clone)]
55struct DawnBindGroupLayout {
56    inner: BindGroupLayout,
57}
58
59#[derive(Debug, Clone)]
60struct DawnBindGroup {
61    inner: BindGroup,
62}
63
64#[derive(Debug, Clone)]
65struct DawnTextureView {
66    inner: TextureView,
67}
68
69#[derive(Debug, Clone)]
70struct DawnSampler {
71    inner: Sampler,
72}
73
74#[derive(Debug, Clone)]
75struct DawnBuffer {
76    inner: Buffer,
77}
78
79#[derive(Debug, Clone)]
80struct DawnTexture {
81    inner: Texture,
82}
83
84#[derive(Debug, Clone)]
85struct DawnExternalTexture {
86    inner: ExternalTexture,
87}
88
89#[derive(Debug, Clone)]
90struct DawnQuerySet {
91    inner: QuerySet,
92}
93
94#[derive(Debug, Clone)]
95struct DawnPipelineLayout {
96    inner: PipelineLayout,
97}
98
99#[derive(Debug, Clone)]
100struct DawnRenderPipeline {
101    inner: RenderPipeline,
102}
103
104#[derive(Debug, Clone)]
105struct DawnComputePipeline {
106    inner: ComputePipeline,
107}
108
109#[derive(Debug)]
110struct DawnCommandEncoder {
111    inner: CommandEncoder,
112}
113
114#[derive(Debug)]
115struct DawnComputePass {
116    inner: ComputePassEncoder,
117    ended: bool,
118}
119
120#[derive(Debug)]
121struct DawnRenderPass {
122    inner: RenderPassEncoder,
123    ended: bool,
124}
125
126#[derive(Debug)]
127struct DawnCommandBuffer {
128    inner: CommandBuffer,
129}
130
131#[derive(Debug)]
132struct DawnRenderBundleEncoder {
133    inner: RenderBundleEncoder,
134}
135
136#[derive(Debug, Clone)]
137struct DawnRenderBundle {
138    inner: RenderBundle,
139}
140
141#[cfg(target_os = "macos")]
142#[derive(Debug)]
143struct MetalLayerHandle {
144    ptr: *mut std::ffi::c_void,
145}
146
147#[cfg(target_os = "macos")]
148unsafe impl Send for MetalLayerHandle {}
149#[cfg(target_os = "macos")]
150unsafe impl Sync for MetalLayerHandle {}
151
152#[cfg(target_os = "macos")]
153impl Drop for MetalLayerHandle {
154    fn drop(&mut self) {
155        if self.ptr.is_null() {
156            return;
157        }
158        unsafe {
159            let ptr = self.ptr.cast::<objc2_quartz_core::CAMetalLayer>();
160            let _ = objc2::rc::Retained::from_raw(ptr);
161        }
162    }
163}
164
165#[derive(Debug, Clone)]
166struct DawnSurface {
167    inner: Surface,
168    #[cfg(target_os = "macos")]
169    metal_layer: Option<Arc<MetalLayerHandle>>,
170}
171
172#[derive(Debug, Clone)]
173struct DawnSurfaceOutputDetail {
174    surface: Surface,
175}
176
177#[derive(Debug)]
178struct DawnQueueWriteBuffer {
179    inner: Vec<u8>,
180}
181
182#[derive(Debug)]
183struct DawnBufferMappedRange {
184    data: *mut u8,
185    size: usize,
186}
187
188#[derive(Debug)]
189struct DawnPipelineCache;
190
191#[derive(Debug)]
192struct DawnBlas;
193
194#[derive(Debug)]
195struct DawnTlas;
196
197#[derive(Debug)]
198struct DawnError(String);
199
200impl fmt::Display for DawnError {
201    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202        write!(f, "{}", self.0)
203    }
204}
205
206impl std::error::Error for DawnError {}
207
208macro_rules! unsafe_send_sync {
209    ($($ty:ty),+ $(,)?) => {
210        $(unsafe impl Send for $ty {}
211        unsafe impl Sync for $ty {})+
212    };
213}
214
215unsafe_send_sync!(
216    DawnInstance,
217    DawnAdapter,
218    DawnDevice,
219    DawnQueue,
220    DawnShaderModule,
221    DawnBindGroupLayout,
222    DawnBindGroup,
223    DawnTextureView,
224    DawnSampler,
225    DawnBuffer,
226    DawnTexture,
227    DawnExternalTexture,
228    DawnQuerySet,
229    DawnPipelineLayout,
230    DawnRenderPipeline,
231    DawnComputePipeline,
232    DawnCommandEncoder,
233    DawnComputePass,
234    DawnRenderPass,
235    DawnCommandBuffer,
236    DawnRenderBundleEncoder,
237    DawnRenderBundle,
238    DawnSurface,
239    DawnSurfaceOutputDetail,
240    DawnQueueWriteBuffer,
241    DawnBufferMappedRange,
242    DawnPipelineCache,
243    DawnBlas,
244    DawnTlas,
245    DawnError,
246);
247
248struct CallbackFuture<T> {
249    shared: Arc<Mutex<CallbackShared<T>>>,
250}
251
252struct CallbackShared<T> {
253    result: Option<T>,
254    waker: Option<Waker>,
255}
256
257impl<T> CallbackFuture<T> {
258    fn new() -> (Self, Arc<Mutex<CallbackShared<T>>>) {
259        let shared = Arc::new(Mutex::new(CallbackShared {
260            result: None,
261            waker: None,
262        }));
263        (
264            Self {
265                shared: shared.clone(),
266            },
267            shared,
268        )
269    }
270}
271
272impl<T> Future for CallbackFuture<T> {
273    type Output = T;
274
275    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
276        let mut shared = self.shared.lock().expect("wgpu-compat future lock");
277        if let Some(result) = shared.result.take() {
278            return Poll::Ready(result);
279        }
280        shared.waker = Some(cx.waker().clone());
281        Poll::Pending
282    }
283}
284
285fn complete_shared<T>(shared: &Arc<Mutex<CallbackShared<T>>>, value: T) {
286    let mut shared = shared.lock().expect("wgpu-compat future lock");
287    shared.result = Some(value);
288    if let Some(waker) = shared.waker.take() {
289        waker.wake();
290    }
291}
292
293fn label_to_string(label: wgpu::Label<'_>) -> Option<String> {
294    label.map(|s| s.to_string())
295}
296
297fn map_backend_type_to_wgpu(value: BackendType) -> wgpu::Backend {
298    match value {
299        BackendType::Vulkan => wgpu::Backend::Vulkan,
300        BackendType::Metal => wgpu::Backend::Metal,
301        BackendType::D3D12 => wgpu::Backend::Dx12,
302        BackendType::D3D11 => wgpu::Backend::Noop,
303        BackendType::OpenGL | BackendType::OpenGLes => wgpu::Backend::Gl,
304        BackendType::WebGPU => wgpu::Backend::BrowserWebGpu,
305        _ => wgpu::Backend::Noop,
306    }
307}
308
309fn map_power_preference(value: wgpu::PowerPreference) -> PowerPreference {
310    match value {
311        wgpu::PowerPreference::None => PowerPreference::Undefined,
312        wgpu::PowerPreference::LowPower => PowerPreference::LowPower,
313        wgpu::PowerPreference::HighPerformance => PowerPreference::HighPerformance,
314        _ => PowerPreference::Undefined,
315    }
316}
317
318fn map_texture_format(value: wgpu::TextureFormat) -> TextureFormat {
319    use wgpu::TextureFormat as W;
320    match value {
321        W::R8Unorm => TextureFormat::R8Unorm,
322        W::R8Snorm => TextureFormat::R8Snorm,
323        W::R8Uint => TextureFormat::R8Uint,
324        W::R8Sint => TextureFormat::R8Sint,
325        W::R16Unorm => TextureFormat::R16Unorm,
326        W::R16Snorm => TextureFormat::R16Snorm,
327        W::R16Uint => TextureFormat::R16Uint,
328        W::R16Sint => TextureFormat::R16Sint,
329        W::R16Float => TextureFormat::R16Float,
330        W::Rg8Unorm => TextureFormat::Rg8Unorm,
331        W::Rg8Snorm => TextureFormat::Rg8Snorm,
332        W::Rg8Uint => TextureFormat::Rg8Uint,
333        W::Rg8Sint => TextureFormat::Rg8Sint,
334        W::R32Float => TextureFormat::R32Float,
335        W::R32Uint => TextureFormat::R32Uint,
336        W::R32Sint => TextureFormat::R32Sint,
337        W::Rg16Unorm => TextureFormat::Rg16Unorm,
338        W::Rg16Snorm => TextureFormat::Rg16Snorm,
339        W::Rg16Uint => TextureFormat::Rg16Uint,
340        W::Rg16Sint => TextureFormat::Rg16Sint,
341        W::Rg16Float => TextureFormat::Rg16Float,
342        W::Rgba8Unorm => TextureFormat::Rgba8Unorm,
343        W::Rgba8UnormSrgb => TextureFormat::Rgba8UnormSrgb,
344        W::Rgba8Snorm => TextureFormat::Rgba8Snorm,
345        W::Rgba8Uint => TextureFormat::Rgba8Uint,
346        W::Rgba8Sint => TextureFormat::Rgba8Sint,
347        W::Bgra8Unorm => TextureFormat::Bgra8Unorm,
348        W::Bgra8UnormSrgb => TextureFormat::Bgra8UnormSrgb,
349        W::Rgb10a2Unorm => TextureFormat::Rgb10A2Unorm,
350        W::Rgb10a2Uint => TextureFormat::Rgb10A2Uint,
351        W::Rg11b10Ufloat => TextureFormat::Rg11B10Ufloat,
352        W::Rgb9e5Ufloat => TextureFormat::Rgb9E5Ufloat,
353        W::Rg32Float => TextureFormat::Rg32Float,
354        W::Rg32Uint => TextureFormat::Rg32Uint,
355        W::Rg32Sint => TextureFormat::Rg32Sint,
356        W::Rgba16Unorm => TextureFormat::Rgba16Unorm,
357        W::Rgba16Snorm => TextureFormat::Rgba16Snorm,
358        W::Rgba16Uint => TextureFormat::Rgba16Uint,
359        W::Rgba16Sint => TextureFormat::Rgba16Sint,
360        W::Rgba16Float => TextureFormat::Rgba16Float,
361        W::Rgba32Float => TextureFormat::Rgba32Float,
362        W::Rgba32Uint => TextureFormat::Rgba32Uint,
363        W::Rgba32Sint => TextureFormat::Rgba32Sint,
364        W::Stencil8 => TextureFormat::Stencil8,
365        W::Depth16Unorm => TextureFormat::Depth16Unorm,
366        W::Depth24Plus => TextureFormat::Depth24Plus,
367        W::Depth24PlusStencil8 => TextureFormat::Depth24PlusStencil8,
368        W::Depth32Float => TextureFormat::Depth32Float,
369        W::Depth32FloatStencil8 => TextureFormat::Depth32FloatStencil8,
370        W::Bc1RgbaUnorm => TextureFormat::Bc1RgbaUnorm,
371        W::Bc1RgbaUnormSrgb => TextureFormat::Bc1RgbaUnormSrgb,
372        W::Bc2RgbaUnorm => TextureFormat::Bc2RgbaUnorm,
373        W::Bc2RgbaUnormSrgb => TextureFormat::Bc2RgbaUnormSrgb,
374        W::Bc3RgbaUnorm => TextureFormat::Bc3RgbaUnorm,
375        W::Bc3RgbaUnormSrgb => TextureFormat::Bc3RgbaUnormSrgb,
376        W::Bc4RUnorm => TextureFormat::Bc4RUnorm,
377        W::Bc4RSnorm => TextureFormat::Bc4RSnorm,
378        W::Bc5RgUnorm => TextureFormat::Bc5RgUnorm,
379        W::Bc5RgSnorm => TextureFormat::Bc5RgSnorm,
380        W::Bc6hRgbUfloat => TextureFormat::Bc6HRgbUfloat,
381        W::Bc6hRgbFloat => TextureFormat::Bc6HRgbFloat,
382        W::Bc7RgbaUnorm => TextureFormat::Bc7RgbaUnorm,
383        W::Bc7RgbaUnormSrgb => TextureFormat::Bc7RgbaUnormSrgb,
384        W::Etc2Rgb8Unorm => TextureFormat::Etc2Rgb8Unorm,
385        W::Etc2Rgb8UnormSrgb => TextureFormat::Etc2Rgb8UnormSrgb,
386        W::Etc2Rgb8A1Unorm => TextureFormat::Etc2Rgb8A1Unorm,
387        W::Etc2Rgb8A1UnormSrgb => TextureFormat::Etc2Rgb8A1UnormSrgb,
388        W::Etc2Rgba8Unorm => TextureFormat::Etc2Rgba8Unorm,
389        W::Etc2Rgba8UnormSrgb => TextureFormat::Etc2Rgba8UnormSrgb,
390        W::EacR11Unorm => TextureFormat::EacR11Unorm,
391        W::EacR11Snorm => TextureFormat::EacR11Snorm,
392        W::EacRg11Unorm => TextureFormat::EacRg11Unorm,
393        W::EacRg11Snorm => TextureFormat::EacRg11Snorm,
394        W::Astc { block, channel } => match (block, channel) {
395            (wgpu::AstcBlock::B4x4, wgpu::AstcChannel::Unorm) => TextureFormat::Astc4X4Unorm,
396            (wgpu::AstcBlock::B4x4, wgpu::AstcChannel::UnormSrgb) => {
397                TextureFormat::Astc4X4UnormSrgb
398            }
399            (wgpu::AstcBlock::B5x4, wgpu::AstcChannel::Unorm) => TextureFormat::Astc5X4Unorm,
400            (wgpu::AstcBlock::B5x4, wgpu::AstcChannel::UnormSrgb) => {
401                TextureFormat::Astc5X4UnormSrgb
402            }
403            (wgpu::AstcBlock::B5x5, wgpu::AstcChannel::Unorm) => TextureFormat::Astc5X5Unorm,
404            (wgpu::AstcBlock::B5x5, wgpu::AstcChannel::UnormSrgb) => {
405                TextureFormat::Astc5X5UnormSrgb
406            }
407            (wgpu::AstcBlock::B6x5, wgpu::AstcChannel::Unorm) => TextureFormat::Astc6X5Unorm,
408            (wgpu::AstcBlock::B6x5, wgpu::AstcChannel::UnormSrgb) => {
409                TextureFormat::Astc6X5UnormSrgb
410            }
411            (wgpu::AstcBlock::B6x6, wgpu::AstcChannel::Unorm) => TextureFormat::Astc6X6Unorm,
412            (wgpu::AstcBlock::B6x6, wgpu::AstcChannel::UnormSrgb) => {
413                TextureFormat::Astc6X6UnormSrgb
414            }
415            (wgpu::AstcBlock::B8x5, wgpu::AstcChannel::Unorm) => TextureFormat::Astc8X5Unorm,
416            (wgpu::AstcBlock::B8x5, wgpu::AstcChannel::UnormSrgb) => {
417                TextureFormat::Astc8X5UnormSrgb
418            }
419            (wgpu::AstcBlock::B8x6, wgpu::AstcChannel::Unorm) => TextureFormat::Astc8X6Unorm,
420            (wgpu::AstcBlock::B8x6, wgpu::AstcChannel::UnormSrgb) => {
421                TextureFormat::Astc8X6UnormSrgb
422            }
423            (wgpu::AstcBlock::B8x8, wgpu::AstcChannel::Unorm) => TextureFormat::Astc8X8Unorm,
424            (wgpu::AstcBlock::B8x8, wgpu::AstcChannel::UnormSrgb) => {
425                TextureFormat::Astc8X8UnormSrgb
426            }
427            (wgpu::AstcBlock::B10x5, wgpu::AstcChannel::Unorm) => TextureFormat::Astc10X5Unorm,
428            (wgpu::AstcBlock::B10x5, wgpu::AstcChannel::UnormSrgb) => {
429                TextureFormat::Astc10X5UnormSrgb
430            }
431            (wgpu::AstcBlock::B10x6, wgpu::AstcChannel::Unorm) => TextureFormat::Astc10X6Unorm,
432            (wgpu::AstcBlock::B10x6, wgpu::AstcChannel::UnormSrgb) => {
433                TextureFormat::Astc10X6UnormSrgb
434            }
435            (wgpu::AstcBlock::B10x8, wgpu::AstcChannel::Unorm) => TextureFormat::Astc10X8Unorm,
436            (wgpu::AstcBlock::B10x8, wgpu::AstcChannel::UnormSrgb) => {
437                TextureFormat::Astc10X8UnormSrgb
438            }
439            (wgpu::AstcBlock::B10x10, wgpu::AstcChannel::Unorm) => TextureFormat::Astc10X10Unorm,
440            (wgpu::AstcBlock::B10x10, wgpu::AstcChannel::UnormSrgb) => {
441                TextureFormat::Astc10X10UnormSrgb
442            }
443            (wgpu::AstcBlock::B12x10, wgpu::AstcChannel::Unorm) => TextureFormat::Astc12X10Unorm,
444            (wgpu::AstcBlock::B12x10, wgpu::AstcChannel::UnormSrgb) => {
445                TextureFormat::Astc12X10UnormSrgb
446            }
447            (wgpu::AstcBlock::B12x12, wgpu::AstcChannel::Unorm) => TextureFormat::Astc12X12Unorm,
448            (wgpu::AstcBlock::B12x12, wgpu::AstcChannel::UnormSrgb) => {
449                TextureFormat::Astc12X12UnormSrgb
450            }
451            _ => panic!("wgpu-compat: unsupported ASTC format"),
452        },
453        _ => panic!("wgpu-compat: unsupported texture format"),
454    }
455}
456
457fn map_texture_format_to_wgpu(value: TextureFormat) -> wgpu::TextureFormat {
458    use wgpu::TextureFormat as W;
459    match value {
460        TextureFormat::R8Unorm => W::R8Unorm,
461        TextureFormat::R8Snorm => W::R8Snorm,
462        TextureFormat::R8Uint => W::R8Uint,
463        TextureFormat::R8Sint => W::R8Sint,
464        TextureFormat::R16Unorm => W::R16Unorm,
465        TextureFormat::R16Snorm => W::R16Snorm,
466        TextureFormat::R16Uint => W::R16Uint,
467        TextureFormat::R16Sint => W::R16Sint,
468        TextureFormat::R16Float => W::R16Float,
469        TextureFormat::Rg8Unorm => W::Rg8Unorm,
470        TextureFormat::Rg8Snorm => W::Rg8Snorm,
471        TextureFormat::Rg8Uint => W::Rg8Uint,
472        TextureFormat::Rg8Sint => W::Rg8Sint,
473        TextureFormat::R32Float => W::R32Float,
474        TextureFormat::R32Uint => W::R32Uint,
475        TextureFormat::R32Sint => W::R32Sint,
476        TextureFormat::Rg16Unorm => W::Rg16Unorm,
477        TextureFormat::Rg16Snorm => W::Rg16Snorm,
478        TextureFormat::Rg16Uint => W::Rg16Uint,
479        TextureFormat::Rg16Sint => W::Rg16Sint,
480        TextureFormat::Rg16Float => W::Rg16Float,
481        TextureFormat::Rgba8Unorm => W::Rgba8Unorm,
482        TextureFormat::Rgba8UnormSrgb => W::Rgba8UnormSrgb,
483        TextureFormat::Rgba8Snorm => W::Rgba8Snorm,
484        TextureFormat::Rgba8Uint => W::Rgba8Uint,
485        TextureFormat::Rgba8Sint => W::Rgba8Sint,
486        TextureFormat::Bgra8Unorm => W::Bgra8Unorm,
487        TextureFormat::Bgra8UnormSrgb => W::Bgra8UnormSrgb,
488        TextureFormat::Rgb10A2Uint => W::Rgb10a2Uint,
489        TextureFormat::Rgb10A2Unorm => W::Rgb10a2Unorm,
490        TextureFormat::Rg11B10Ufloat => W::Rg11b10Ufloat,
491        TextureFormat::Rgb9E5Ufloat => W::Rgb9e5Ufloat,
492        TextureFormat::Rg32Float => W::Rg32Float,
493        TextureFormat::Rg32Uint => W::Rg32Uint,
494        TextureFormat::Rg32Sint => W::Rg32Sint,
495        TextureFormat::Rgba16Unorm => W::Rgba16Unorm,
496        TextureFormat::Rgba16Snorm => W::Rgba16Snorm,
497        TextureFormat::Rgba16Uint => W::Rgba16Uint,
498        TextureFormat::Rgba16Sint => W::Rgba16Sint,
499        TextureFormat::Rgba16Float => W::Rgba16Float,
500        TextureFormat::Rgba32Float => W::Rgba32Float,
501        TextureFormat::Rgba32Uint => W::Rgba32Uint,
502        TextureFormat::Rgba32Sint => W::Rgba32Sint,
503        TextureFormat::Stencil8 => W::Stencil8,
504        TextureFormat::Depth16Unorm => W::Depth16Unorm,
505        TextureFormat::Depth24Plus => W::Depth24Plus,
506        TextureFormat::Depth24PlusStencil8 => W::Depth24PlusStencil8,
507        TextureFormat::Depth32Float => W::Depth32Float,
508        TextureFormat::Depth32FloatStencil8 => W::Depth32FloatStencil8,
509        TextureFormat::Bc1RgbaUnorm => W::Bc1RgbaUnorm,
510        TextureFormat::Bc1RgbaUnormSrgb => W::Bc1RgbaUnormSrgb,
511        TextureFormat::Bc2RgbaUnorm => W::Bc2RgbaUnorm,
512        TextureFormat::Bc2RgbaUnormSrgb => W::Bc2RgbaUnormSrgb,
513        TextureFormat::Bc3RgbaUnorm => W::Bc3RgbaUnorm,
514        TextureFormat::Bc3RgbaUnormSrgb => W::Bc3RgbaUnormSrgb,
515        TextureFormat::Bc4RUnorm => W::Bc4RUnorm,
516        TextureFormat::Bc4RSnorm => W::Bc4RSnorm,
517        TextureFormat::Bc5RgUnorm => W::Bc5RgUnorm,
518        TextureFormat::Bc5RgSnorm => W::Bc5RgSnorm,
519        TextureFormat::Bc6HRgbUfloat => W::Bc6hRgbUfloat,
520        TextureFormat::Bc6HRgbFloat => W::Bc6hRgbFloat,
521        TextureFormat::Bc7RgbaUnorm => W::Bc7RgbaUnorm,
522        TextureFormat::Bc7RgbaUnormSrgb => W::Bc7RgbaUnormSrgb,
523        TextureFormat::Etc2Rgb8Unorm => W::Etc2Rgb8Unorm,
524        TextureFormat::Etc2Rgb8UnormSrgb => W::Etc2Rgb8UnormSrgb,
525        TextureFormat::Etc2Rgb8A1Unorm => W::Etc2Rgb8A1Unorm,
526        TextureFormat::Etc2Rgb8A1UnormSrgb => W::Etc2Rgb8A1UnormSrgb,
527        TextureFormat::Etc2Rgba8Unorm => W::Etc2Rgba8Unorm,
528        TextureFormat::Etc2Rgba8UnormSrgb => W::Etc2Rgba8UnormSrgb,
529        TextureFormat::EacR11Unorm => W::EacR11Unorm,
530        TextureFormat::EacR11Snorm => W::EacR11Snorm,
531        TextureFormat::EacRg11Unorm => W::EacRg11Unorm,
532        TextureFormat::EacRg11Snorm => W::EacRg11Snorm,
533        TextureFormat::Astc4X4Unorm => W::Astc {
534            block: wgpu::AstcBlock::B4x4,
535            channel: wgpu::AstcChannel::Unorm,
536        },
537        TextureFormat::Astc4X4UnormSrgb => W::Astc {
538            block: wgpu::AstcBlock::B4x4,
539            channel: wgpu::AstcChannel::UnormSrgb,
540        },
541        TextureFormat::Astc5X4Unorm => W::Astc {
542            block: wgpu::AstcBlock::B5x4,
543            channel: wgpu::AstcChannel::Unorm,
544        },
545        TextureFormat::Astc5X4UnormSrgb => W::Astc {
546            block: wgpu::AstcBlock::B5x4,
547            channel: wgpu::AstcChannel::UnormSrgb,
548        },
549        TextureFormat::Astc5X5Unorm => W::Astc {
550            block: wgpu::AstcBlock::B5x5,
551            channel: wgpu::AstcChannel::Unorm,
552        },
553        TextureFormat::Astc5X5UnormSrgb => W::Astc {
554            block: wgpu::AstcBlock::B5x5,
555            channel: wgpu::AstcChannel::UnormSrgb,
556        },
557        TextureFormat::Astc6X5Unorm => W::Astc {
558            block: wgpu::AstcBlock::B6x5,
559            channel: wgpu::AstcChannel::Unorm,
560        },
561        TextureFormat::Astc6X5UnormSrgb => W::Astc {
562            block: wgpu::AstcBlock::B6x5,
563            channel: wgpu::AstcChannel::UnormSrgb,
564        },
565        TextureFormat::Astc6X6Unorm => W::Astc {
566            block: wgpu::AstcBlock::B6x6,
567            channel: wgpu::AstcChannel::Unorm,
568        },
569        TextureFormat::Astc6X6UnormSrgb => W::Astc {
570            block: wgpu::AstcBlock::B6x6,
571            channel: wgpu::AstcChannel::UnormSrgb,
572        },
573        TextureFormat::Astc8X5Unorm => W::Astc {
574            block: wgpu::AstcBlock::B8x5,
575            channel: wgpu::AstcChannel::Unorm,
576        },
577        TextureFormat::Astc8X5UnormSrgb => W::Astc {
578            block: wgpu::AstcBlock::B8x5,
579            channel: wgpu::AstcChannel::UnormSrgb,
580        },
581        TextureFormat::Astc8X6Unorm => W::Astc {
582            block: wgpu::AstcBlock::B8x6,
583            channel: wgpu::AstcChannel::Unorm,
584        },
585        TextureFormat::Astc8X6UnormSrgb => W::Astc {
586            block: wgpu::AstcBlock::B8x6,
587            channel: wgpu::AstcChannel::UnormSrgb,
588        },
589        TextureFormat::Astc8X8Unorm => W::Astc {
590            block: wgpu::AstcBlock::B8x8,
591            channel: wgpu::AstcChannel::Unorm,
592        },
593        TextureFormat::Astc8X8UnormSrgb => W::Astc {
594            block: wgpu::AstcBlock::B8x8,
595            channel: wgpu::AstcChannel::UnormSrgb,
596        },
597        TextureFormat::Astc10X5Unorm => W::Astc {
598            block: wgpu::AstcBlock::B10x5,
599            channel: wgpu::AstcChannel::Unorm,
600        },
601        TextureFormat::Astc10X5UnormSrgb => W::Astc {
602            block: wgpu::AstcBlock::B10x5,
603            channel: wgpu::AstcChannel::UnormSrgb,
604        },
605        TextureFormat::Astc10X6Unorm => W::Astc {
606            block: wgpu::AstcBlock::B10x6,
607            channel: wgpu::AstcChannel::Unorm,
608        },
609        TextureFormat::Astc10X6UnormSrgb => W::Astc {
610            block: wgpu::AstcBlock::B10x6,
611            channel: wgpu::AstcChannel::UnormSrgb,
612        },
613        TextureFormat::Astc10X8Unorm => W::Astc {
614            block: wgpu::AstcBlock::B10x8,
615            channel: wgpu::AstcChannel::Unorm,
616        },
617        TextureFormat::Astc10X8UnormSrgb => W::Astc {
618            block: wgpu::AstcBlock::B10x8,
619            channel: wgpu::AstcChannel::UnormSrgb,
620        },
621        TextureFormat::Astc10X10Unorm => W::Astc {
622            block: wgpu::AstcBlock::B10x10,
623            channel: wgpu::AstcChannel::Unorm,
624        },
625        TextureFormat::Astc10X10UnormSrgb => W::Astc {
626            block: wgpu::AstcBlock::B10x10,
627            channel: wgpu::AstcChannel::UnormSrgb,
628        },
629        TextureFormat::Astc12X10Unorm => W::Astc {
630            block: wgpu::AstcBlock::B12x10,
631            channel: wgpu::AstcChannel::Unorm,
632        },
633        TextureFormat::Astc12X10UnormSrgb => W::Astc {
634            block: wgpu::AstcBlock::B12x10,
635            channel: wgpu::AstcChannel::UnormSrgb,
636        },
637        TextureFormat::Astc12X12Unorm => W::Astc {
638            block: wgpu::AstcBlock::B12x12,
639            channel: wgpu::AstcChannel::Unorm,
640        },
641        TextureFormat::Astc12X12UnormSrgb => W::Astc {
642            block: wgpu::AstcBlock::B12x12,
643            channel: wgpu::AstcChannel::UnormSrgb,
644        },
645        _ => panic!("wgpu-compat: unsupported texture format conversion"),
646    }
647}
648
649fn map_texture_dimension(value: wgpu::TextureDimension) -> TextureDimension {
650    match value {
651        wgpu::TextureDimension::D1 => TextureDimension::D1,
652        wgpu::TextureDimension::D2 => TextureDimension::D2,
653        wgpu::TextureDimension::D3 => TextureDimension::D3,
654        _ => TextureDimension::D2,
655    }
656}
657
658fn map_texture_view_dimension(value: wgpu::TextureViewDimension) -> TextureViewDimension {
659    match value {
660        wgpu::TextureViewDimension::D1 => TextureViewDimension::D1,
661        wgpu::TextureViewDimension::D2 => TextureViewDimension::D2,
662        wgpu::TextureViewDimension::D2Array => TextureViewDimension::D2Array,
663        wgpu::TextureViewDimension::Cube => TextureViewDimension::Cube,
664        wgpu::TextureViewDimension::CubeArray => TextureViewDimension::CubeArray,
665        wgpu::TextureViewDimension::D3 => TextureViewDimension::D3,
666        _ => TextureViewDimension::D2,
667    }
668}
669
670fn map_texture_aspect(value: wgpu::TextureAspect) -> TextureAspect {
671    match value {
672        wgpu::TextureAspect::All => TextureAspect::All,
673        wgpu::TextureAspect::StencilOnly => TextureAspect::StencilOnly,
674        wgpu::TextureAspect::DepthOnly => TextureAspect::DepthOnly,
675        wgpu::TextureAspect::Plane0 => TextureAspect::Plane0Only,
676        wgpu::TextureAspect::Plane1 => TextureAspect::Plane1Only,
677        wgpu::TextureAspect::Plane2 => TextureAspect::Plane2Only,
678        _ => TextureAspect::All,
679    }
680}
681
682fn map_filter_mode(value: wgpu::FilterMode) -> FilterMode {
683    match value {
684        wgpu::FilterMode::Nearest => FilterMode::Nearest,
685        wgpu::FilterMode::Linear => FilterMode::Linear,
686        _ => FilterMode::Nearest,
687    }
688}
689
690fn map_mipmap_filter_mode(value: wgpu::MipmapFilterMode) -> MipmapFilterMode {
691    match value {
692        wgpu::MipmapFilterMode::Nearest => MipmapFilterMode::Nearest,
693        wgpu::MipmapFilterMode::Linear => MipmapFilterMode::Linear,
694        _ => MipmapFilterMode::Nearest,
695    }
696}
697
698fn map_address_mode(value: wgpu::AddressMode) -> AddressMode {
699    match value {
700        wgpu::AddressMode::ClampToEdge => AddressMode::ClampToEdge,
701        wgpu::AddressMode::Repeat => AddressMode::Repeat,
702        wgpu::AddressMode::MirrorRepeat => AddressMode::MirrorRepeat,
703        _ => AddressMode::ClampToEdge,
704    }
705}
706
707fn map_compare_function(value: wgpu::CompareFunction) -> CompareFunction {
708    match value {
709        wgpu::CompareFunction::Never => CompareFunction::Never,
710        wgpu::CompareFunction::Less => CompareFunction::Less,
711        wgpu::CompareFunction::Equal => CompareFunction::Equal,
712        wgpu::CompareFunction::LessEqual => CompareFunction::LessEqual,
713        wgpu::CompareFunction::Greater => CompareFunction::Greater,
714        wgpu::CompareFunction::NotEqual => CompareFunction::NotEqual,
715        wgpu::CompareFunction::GreaterEqual => CompareFunction::GreaterEqual,
716        wgpu::CompareFunction::Always => CompareFunction::Always,
717        _ => CompareFunction::Always,
718    }
719}
720
721fn map_index_format(value: wgpu::IndexFormat) -> IndexFormat {
722    match value {
723        wgpu::IndexFormat::Uint16 => IndexFormat::Uint16,
724        wgpu::IndexFormat::Uint32 => IndexFormat::Uint32,
725        _ => IndexFormat::Uint32,
726    }
727}
728
729fn map_primitive_topology(value: wgpu::PrimitiveTopology) -> PrimitiveTopology {
730    match value {
731        wgpu::PrimitiveTopology::PointList => PrimitiveTopology::PointList,
732        wgpu::PrimitiveTopology::LineList => PrimitiveTopology::LineList,
733        wgpu::PrimitiveTopology::LineStrip => PrimitiveTopology::LineStrip,
734        wgpu::PrimitiveTopology::TriangleList => PrimitiveTopology::TriangleList,
735        wgpu::PrimitiveTopology::TriangleStrip => PrimitiveTopology::TriangleStrip,
736        _ => PrimitiveTopology::TriangleList,
737    }
738}
739
740fn map_front_face(value: wgpu::FrontFace) -> FrontFace {
741    match value {
742        wgpu::FrontFace::Ccw => FrontFace::Ccw,
743        wgpu::FrontFace::Cw => FrontFace::Cw,
744        _ => FrontFace::Ccw,
745    }
746}
747
748fn map_cull_mode(value: Option<wgpu::Face>) -> CullMode {
749    match value {
750        Some(wgpu::Face::Front) => CullMode::Front,
751        Some(wgpu::Face::Back) => CullMode::Back,
752        None => CullMode::None,
753    }
754}
755
756fn map_stencil_operation(value: wgpu::StencilOperation) -> StencilOperation {
757    match value {
758        wgpu::StencilOperation::Keep => StencilOperation::Keep,
759        wgpu::StencilOperation::Zero => StencilOperation::Zero,
760        wgpu::StencilOperation::Replace => StencilOperation::Replace,
761        wgpu::StencilOperation::Invert => StencilOperation::Invert,
762        wgpu::StencilOperation::IncrementClamp => StencilOperation::IncrementClamp,
763        wgpu::StencilOperation::DecrementClamp => StencilOperation::DecrementClamp,
764        wgpu::StencilOperation::IncrementWrap => StencilOperation::IncrementWrap,
765        wgpu::StencilOperation::DecrementWrap => StencilOperation::DecrementWrap,
766        _ => StencilOperation::Keep,
767    }
768}
769
770fn map_blend_operation(value: wgpu::BlendOperation) -> BlendOperation {
771    match value {
772        wgpu::BlendOperation::Add => BlendOperation::Add,
773        wgpu::BlendOperation::Subtract => BlendOperation::Subtract,
774        wgpu::BlendOperation::ReverseSubtract => BlendOperation::ReverseSubtract,
775        wgpu::BlendOperation::Min => BlendOperation::Min,
776        wgpu::BlendOperation::Max => BlendOperation::Max,
777        _ => BlendOperation::Add,
778    }
779}
780
781fn map_blend_factor(value: wgpu::BlendFactor) -> BlendFactor {
782    match value {
783        wgpu::BlendFactor::Zero => BlendFactor::Zero,
784        wgpu::BlendFactor::One => BlendFactor::One,
785        wgpu::BlendFactor::Src => BlendFactor::Src,
786        wgpu::BlendFactor::OneMinusSrc => BlendFactor::OneMinusSrc,
787        wgpu::BlendFactor::SrcAlpha => BlendFactor::SrcAlpha,
788        wgpu::BlendFactor::OneMinusSrcAlpha => BlendFactor::OneMinusSrcAlpha,
789        wgpu::BlendFactor::Dst => BlendFactor::Dst,
790        wgpu::BlendFactor::OneMinusDst => BlendFactor::OneMinusDst,
791        wgpu::BlendFactor::DstAlpha => BlendFactor::DstAlpha,
792        wgpu::BlendFactor::OneMinusDstAlpha => BlendFactor::OneMinusDstAlpha,
793        wgpu::BlendFactor::SrcAlphaSaturated => BlendFactor::SrcAlphaSaturated,
794        wgpu::BlendFactor::Constant => BlendFactor::Constant,
795        wgpu::BlendFactor::OneMinusConstant => BlendFactor::OneMinusConstant,
796        _ => BlendFactor::One,
797    }
798}
799
800fn map_color_write_mask(value: wgpu::ColorWrites) -> ColorWriteMask {
801    ColorWriteMask::from_bits_truncate(value.bits() as u64)
802}
803
804fn map_buffer_usages(value: wgpu::BufferUsages) -> BufferUsage {
805    BufferUsage::from_bits_truncate(value.bits() as u64)
806}
807
808fn map_texture_usages(value: wgpu::TextureUsages) -> TextureUsage {
809    TextureUsage::from_bits_truncate(value.bits() as u64)
810}
811
812fn map_texture_usage_to_wgpu(value: TextureUsage) -> wgpu::TextureUsages {
813    let mut out = wgpu::TextureUsages::empty();
814    if value.contains(TextureUsage::COPY_SRC) {
815        out |= wgpu::TextureUsages::COPY_SRC;
816    }
817    if value.contains(TextureUsage::COPY_DST) {
818        out |= wgpu::TextureUsages::COPY_DST;
819    }
820    if value.contains(TextureUsage::TEXTURE_BINDING) {
821        out |= wgpu::TextureUsages::TEXTURE_BINDING;
822    }
823    if value.contains(TextureUsage::STORAGE_BINDING) {
824        out |= wgpu::TextureUsages::STORAGE_BINDING;
825    }
826    if value.contains(TextureUsage::RENDER_ATTACHMENT) {
827        out |= wgpu::TextureUsages::RENDER_ATTACHMENT;
828    }
829    if value.contains(TextureUsage::TRANSIENT_ATTACHMENT) {
830        out |= wgpu::TextureUsages::TRANSIENT;
831    }
832    if value.contains(TextureUsage::STORAGE_ATTACHMENT) {
833        out |= wgpu::TextureUsages::STORAGE_BINDING;
834    }
835    out
836}
837
838fn map_shader_stages(value: wgpu::ShaderStages) -> ShaderStage {
839    ShaderStage::from_bits_truncate(value.bits() as u64)
840}
841
842fn map_sampler_binding_type(value: wgpu::SamplerBindingType) -> SamplerBindingType {
843    match value {
844        wgpu::SamplerBindingType::Filtering => SamplerBindingType::Filtering,
845        wgpu::SamplerBindingType::NonFiltering => SamplerBindingType::NonFiltering,
846        wgpu::SamplerBindingType::Comparison => SamplerBindingType::Comparison,
847        _ => SamplerBindingType::Filtering,
848    }
849}
850
851fn map_texture_sample_type(value: wgpu::TextureSampleType) -> TextureSampleType {
852    match value {
853        wgpu::TextureSampleType::Float { filterable } => {
854            if filterable {
855                TextureSampleType::Float
856            } else {
857                TextureSampleType::UnfilterableFloat
858            }
859        }
860        wgpu::TextureSampleType::Depth => TextureSampleType::Depth,
861        wgpu::TextureSampleType::Sint => TextureSampleType::Sint,
862        wgpu::TextureSampleType::Uint => TextureSampleType::Uint,
863        _ => TextureSampleType::Float,
864    }
865}
866
867fn map_storage_texture_access(value: wgpu::StorageTextureAccess) -> StorageTextureAccess {
868    match value {
869        wgpu::StorageTextureAccess::ReadOnly => StorageTextureAccess::ReadOnly,
870        wgpu::StorageTextureAccess::WriteOnly => StorageTextureAccess::WriteOnly,
871        wgpu::StorageTextureAccess::ReadWrite => StorageTextureAccess::ReadWrite,
872        _ => StorageTextureAccess::WriteOnly,
873    }
874}
875
876fn map_vertex_format(value: wgpu::VertexFormat) -> VertexFormat {
877    match value {
878        wgpu::VertexFormat::Uint8x2 => VertexFormat::Uint8X2,
879        wgpu::VertexFormat::Uint8x4 => VertexFormat::Uint8X4,
880        wgpu::VertexFormat::Sint8x2 => VertexFormat::Sint8X2,
881        wgpu::VertexFormat::Sint8x4 => VertexFormat::Sint8X4,
882        wgpu::VertexFormat::Unorm8x2 => VertexFormat::Unorm8X2,
883        wgpu::VertexFormat::Unorm8x4 => VertexFormat::Unorm8X4,
884        wgpu::VertexFormat::Snorm8x2 => VertexFormat::Snorm8X2,
885        wgpu::VertexFormat::Snorm8x4 => VertexFormat::Snorm8X4,
886        wgpu::VertexFormat::Uint16x2 => VertexFormat::Uint16X2,
887        wgpu::VertexFormat::Uint16x4 => VertexFormat::Uint16X4,
888        wgpu::VertexFormat::Sint16x2 => VertexFormat::Sint16X2,
889        wgpu::VertexFormat::Sint16x4 => VertexFormat::Sint16X4,
890        wgpu::VertexFormat::Unorm16x2 => VertexFormat::Unorm16X2,
891        wgpu::VertexFormat::Unorm16x4 => VertexFormat::Unorm16X4,
892        wgpu::VertexFormat::Snorm16x2 => VertexFormat::Snorm16X2,
893        wgpu::VertexFormat::Snorm16x4 => VertexFormat::Snorm16X4,
894        wgpu::VertexFormat::Float16x2 => VertexFormat::Float16X2,
895        wgpu::VertexFormat::Float16x4 => VertexFormat::Float16X4,
896        wgpu::VertexFormat::Float32 => VertexFormat::Float32,
897        wgpu::VertexFormat::Float32x2 => VertexFormat::Float32X2,
898        wgpu::VertexFormat::Float32x3 => VertexFormat::Float32X3,
899        wgpu::VertexFormat::Float32x4 => VertexFormat::Float32X4,
900        wgpu::VertexFormat::Uint32 => VertexFormat::Uint32,
901        wgpu::VertexFormat::Uint32x2 => VertexFormat::Uint32X2,
902        wgpu::VertexFormat::Uint32x3 => VertexFormat::Uint32X3,
903        wgpu::VertexFormat::Uint32x4 => VertexFormat::Uint32X4,
904        wgpu::VertexFormat::Sint32 => VertexFormat::Sint32,
905        wgpu::VertexFormat::Sint32x2 => VertexFormat::Sint32X2,
906        wgpu::VertexFormat::Sint32x3 => VertexFormat::Sint32X3,
907        wgpu::VertexFormat::Sint32x4 => VertexFormat::Sint32X4,
908        wgpu::VertexFormat::Unorm10_10_10_2 => VertexFormat::Unorm1010102,
909        wgpu::VertexFormat::Unorm8x4Bgra => VertexFormat::Unorm8X4Bgra,
910        _ => VertexFormat::Float32X3,
911    }
912}
913
914fn map_vertex_step_mode(value: wgpu::VertexStepMode) -> VertexStepMode {
915    match value {
916        wgpu::VertexStepMode::Vertex => VertexStepMode::Vertex,
917        wgpu::VertexStepMode::Instance => VertexStepMode::Instance,
918        _ => VertexStepMode::Vertex,
919    }
920}
921
922fn map_load_op<T>(value: wgpu::LoadOp<T>) -> LoadOp {
923    match value {
924        wgpu::LoadOp::Load => LoadOp::Load,
925        wgpu::LoadOp::Clear(_) => LoadOp::Clear,
926        wgpu::LoadOp::DontCare(_) => LoadOp::Load,
927    }
928}
929
930fn map_store_op(value: wgpu::StoreOp) -> StoreOp {
931    match value {
932        wgpu::StoreOp::Store => StoreOp::Store,
933        wgpu::StoreOp::Discard => StoreOp::Discard,
934        _ => StoreOp::Store,
935    }
936}
937
938fn map_color(value: wgpu::Color) -> Color {
939    Color {
940        r: Some(value.r),
941        g: Some(value.g),
942        b: Some(value.b),
943        a: Some(value.a),
944    }
945}
946
947fn map_origin_3d(value: wgpu::Origin3d) -> Origin3D {
948    Origin3D {
949        x: Some(value.x),
950        y: Some(value.y),
951        z: Some(value.z),
952    }
953}
954
955fn map_extent_3d(value: wgpu::Extent3d) -> Extent3D {
956    Extent3D {
957        width: Some(value.width),
958        height: Some(value.height),
959        depth_or_array_layers: Some(value.depth_or_array_layers),
960    }
961}
962
963fn map_texel_copy_buffer_layout(value: wgpu::TexelCopyBufferLayout) -> TexelCopyBufferLayout {
964    TexelCopyBufferLayout {
965        offset: Some(value.offset),
966        bytes_per_row: value.bytes_per_row,
967        rows_per_image: value.rows_per_image,
968    }
969}
970
971fn map_texel_copy_buffer_info(value: wgpu::TexelCopyBufferInfo<'_>) -> TexelCopyBufferInfo {
972    TexelCopyBufferInfo {
973        layout: Some(map_texel_copy_buffer_layout(value.layout)),
974        buffer: Some(expect_buffer_from_api(value.buffer)),
975    }
976}
977
978fn map_texel_copy_texture_info(value: wgpu::TexelCopyTextureInfo<'_>) -> TexelCopyTextureInfo {
979    TexelCopyTextureInfo {
980        texture: Some(expect_texture_from_api(value.texture)),
981        mip_level: Some(value.mip_level),
982        origin: Some(map_origin_3d(value.origin)),
983        aspect: Some(map_texture_aspect(value.aspect)),
984    }
985}
986
987fn map_shader_module_descriptor(desc: wgpu::ShaderModuleDescriptor<'_>) -> ShaderModuleDescriptor {
988    let mut out = ShaderModuleDescriptor::new();
989    out.label = label_to_string(desc.label);
990    match desc.source {
991        wgpu::ShaderSource::Wgsl(source) => {
992            let ext = ShaderSourceWGSL {
993                code: Some(source.to_string()),
994            };
995            out = out.with_extension(ShaderModuleDescriptorExtension::from(ext));
996        }
997        _ => panic!("wgpu-compat: unsupported shader source"),
998    }
999    out
1000}
1001
1002fn map_buffer_descriptor(desc: &wgpu::BufferDescriptor<'_>) -> BufferDescriptor {
1003    let mut out = BufferDescriptor::new();
1004    out.label = label_to_string(desc.label);
1005    out.size = Some(desc.size);
1006    out.usage = Some(map_buffer_usages(desc.usage));
1007    out.mapped_at_creation = Some(desc.mapped_at_creation);
1008    out
1009}
1010
1011fn map_texture_descriptor(desc: &wgpu::TextureDescriptor<'_>) -> TextureDescriptor {
1012    let mut out = TextureDescriptor::new();
1013    out.label = label_to_string(desc.label);
1014    out.size = Some(map_extent_3d(desc.size));
1015    out.mip_level_count = Some(desc.mip_level_count);
1016    out.sample_count = Some(desc.sample_count);
1017    out.dimension = Some(map_texture_dimension(desc.dimension));
1018    out.format = Some(map_texture_format(desc.format));
1019    out.usage = Some(map_texture_usages(desc.usage));
1020    out.view_formats = Some(
1021        desc.view_formats
1022            .iter()
1023            .copied()
1024            .map(map_texture_format)
1025            .collect(),
1026    );
1027    out
1028}
1029
1030fn map_texture_view_descriptor(desc: &wgpu::TextureViewDescriptor<'_>) -> TextureViewDescriptor {
1031    let mut out = TextureViewDescriptor::new();
1032    out.label = label_to_string(desc.label);
1033    out.format = desc.format.map(map_texture_format);
1034    out.dimension = desc.dimension.map(map_texture_view_dimension);
1035    out.aspect = Some(map_texture_aspect(desc.aspect));
1036    out.base_mip_level = Some(desc.base_mip_level);
1037    if let Some(count) = desc.mip_level_count {
1038        out.mip_level_count = Some(count);
1039    }
1040    out.base_array_layer = Some(desc.base_array_layer);
1041    if let Some(count) = desc.array_layer_count {
1042        out.array_layer_count = Some(count);
1043    }
1044    out.usage = desc.usage.map(map_texture_usages);
1045    out
1046}
1047
1048fn map_sampler_descriptor(desc: &wgpu::SamplerDescriptor<'_>) -> SamplerDescriptor {
1049    let mut out = SamplerDescriptor::new();
1050    out.label = label_to_string(desc.label);
1051    out.address_mode_u = Some(map_address_mode(desc.address_mode_u));
1052    out.address_mode_v = Some(map_address_mode(desc.address_mode_v));
1053    out.address_mode_w = Some(map_address_mode(desc.address_mode_w));
1054    out.mag_filter = Some(map_filter_mode(desc.mag_filter));
1055    out.min_filter = Some(map_filter_mode(desc.min_filter));
1056    out.mipmap_filter = Some(map_mipmap_filter_mode(desc.mipmap_filter));
1057    out.lod_min_clamp = Some(desc.lod_min_clamp);
1058    out.lod_max_clamp = Some(desc.lod_max_clamp);
1059    out.compare = desc.compare.map(map_compare_function);
1060    out.max_anisotropy = Some(desc.anisotropy_clamp);
1061    out
1062}
1063
1064fn map_bind_group_layout_entry(entry: &wgpu::BindGroupLayoutEntry) -> BindGroupLayoutEntry {
1065    let mut out = BindGroupLayoutEntry::new();
1066    out.binding = Some(entry.binding);
1067    out.visibility = Some(map_shader_stages(entry.visibility));
1068    out.binding_array_size = entry.count.map(|v| v.get()).or(Some(0));
1069
1070    match entry.ty {
1071        wgpu::BindingType::Buffer {
1072            ty,
1073            has_dynamic_offset,
1074            min_binding_size,
1075        } => {
1076            let mut layout = BufferBindingLayout::new();
1077            layout.r#type = Some(match ty {
1078                wgpu::BufferBindingType::Uniform => BufferBindingType::Uniform,
1079                wgpu::BufferBindingType::Storage { read_only } => {
1080                    if read_only {
1081                        BufferBindingType::ReadOnlyStorage
1082                    } else {
1083                        BufferBindingType::Storage
1084                    }
1085                }
1086                _ => BufferBindingType::Uniform,
1087            });
1088            layout.has_dynamic_offset = Some(has_dynamic_offset);
1089            layout.min_binding_size = min_binding_size.map(|v| v.get());
1090            out.buffer = Some(layout);
1091        }
1092        wgpu::BindingType::Sampler(ty) => {
1093            let mut layout = SamplerBindingLayout::new();
1094            layout.r#type = Some(map_sampler_binding_type(ty));
1095            out.sampler = Some(layout);
1096        }
1097        wgpu::BindingType::Texture {
1098            sample_type,
1099            view_dimension,
1100            multisampled,
1101        } => {
1102            let mut layout = TextureBindingLayout::new();
1103            layout.sample_type = Some(map_texture_sample_type(sample_type));
1104            layout.view_dimension = Some(map_texture_view_dimension(view_dimension));
1105            layout.multisampled = Some(multisampled);
1106            out.texture = Some(layout);
1107        }
1108        wgpu::BindingType::StorageTexture {
1109            access,
1110            format,
1111            view_dimension,
1112        } => {
1113            let mut layout = StorageTextureBindingLayout::new();
1114            layout.access = Some(map_storage_texture_access(access));
1115            layout.format = Some(map_texture_format(format));
1116            layout.view_dimension = Some(map_texture_view_dimension(view_dimension));
1117            out.storage_texture = Some(layout);
1118        }
1119        _ => panic!("wgpu-compat: unsupported binding type"),
1120    }
1121
1122    out
1123}
1124
1125fn map_bind_group_layout_descriptor(
1126    desc: &wgpu::BindGroupLayoutDescriptor<'_>,
1127) -> BindGroupLayoutDescriptor {
1128    let mut out = BindGroupLayoutDescriptor::new();
1129    out.label = label_to_string(desc.label);
1130    out.entries = Some(
1131        desc.entries
1132            .iter()
1133            .map(map_bind_group_layout_entry)
1134            .collect(),
1135    );
1136    out
1137}
1138
1139fn map_bind_group_entry(entry: &wgpu::BindGroupEntry<'_>) -> BindGroupEntry {
1140    let mut out = BindGroupEntry::default();
1141    out.binding = Some(entry.binding);
1142    match &entry.resource {
1143        wgpu::BindingResource::Buffer(buffer) => {
1144            out.buffer = Some(expect_buffer_from_api(buffer.buffer));
1145            out.offset = Some(buffer.offset);
1146            out.size = Some(buffer.size.map(|v| v.get()).unwrap_or(WHOLE_SIZE));
1147        }
1148        wgpu::BindingResource::Sampler(sampler) => {
1149            out.sampler = Some(expect_sampler_from_api(sampler));
1150        }
1151        wgpu::BindingResource::TextureView(view) => {
1152            out.texture_view = Some(expect_texture_view_from_api(view));
1153        }
1154        _ => panic!("wgpu-compat: binding resource arrays not supported"),
1155    }
1156    out
1157}
1158
1159fn map_bind_group_descriptor(desc: &wgpu::BindGroupDescriptor<'_>) -> BindGroupDescriptor {
1160    let mut out = BindGroupDescriptor::new();
1161    out.label = label_to_string(desc.label);
1162    out.layout = Some(expect_bind_group_layout_from_api(desc.layout));
1163    out.entries = Some(desc.entries.iter().map(map_bind_group_entry).collect());
1164    out
1165}
1166
1167fn map_pipeline_layout_descriptor(
1168    desc: &wgpu::PipelineLayoutDescriptor<'_>,
1169) -> PipelineLayoutDescriptor {
1170    let mut out = PipelineLayoutDescriptor::new();
1171    out.label = label_to_string(desc.label);
1172    out.bind_group_layouts = Some(
1173        desc.bind_group_layouts
1174            .iter()
1175            .copied()
1176            .map(expect_bind_group_layout_from_api)
1177            .collect(),
1178    );
1179    out.immediate_size = Some(0);
1180    out
1181}
1182
1183fn map_vertex_attribute(attr: &wgpu::VertexAttribute) -> VertexAttribute {
1184    let mut out = VertexAttribute::new();
1185    out.format = Some(map_vertex_format(attr.format));
1186    out.offset = Some(attr.offset);
1187    out.shader_location = Some(attr.shader_location);
1188    out
1189}
1190
1191fn map_vertex_buffer_layout(layout: &wgpu::VertexBufferLayout<'_>) -> VertexBufferLayout {
1192    let mut out = VertexBufferLayout::new();
1193    out.array_stride = Some(layout.array_stride);
1194    out.step_mode = Some(map_vertex_step_mode(layout.step_mode));
1195    out.attributes = Some(layout.attributes.iter().map(map_vertex_attribute).collect());
1196    out
1197}
1198
1199fn map_vertex_state(state: &wgpu::VertexState<'_>) -> VertexState {
1200    let mut out = VertexState::new();
1201    out.module = Some(expect_shader_module_from_api(state.module));
1202    out.entry_point = state.entry_point.map(str::to_string);
1203    out.constants = Some(
1204        state
1205            .compilation_options
1206            .constants
1207            .iter()
1208            .map(|(k, v)| {
1209                let mut entry = ConstantEntry::new();
1210                entry.key = Some(k.to_string());
1211                entry.value = Some(*v);
1212                entry
1213            })
1214            .collect(),
1215    );
1216    out.buffers = Some(state.buffers.iter().map(map_vertex_buffer_layout).collect());
1217    out
1218}
1219
1220fn map_blend_component(comp: &wgpu::BlendComponent) -> BlendComponent {
1221    BlendComponent {
1222        operation: Some(map_blend_operation(comp.operation)),
1223        src_factor: Some(map_blend_factor(comp.src_factor)),
1224        dst_factor: Some(map_blend_factor(comp.dst_factor)),
1225    }
1226}
1227
1228fn map_blend_state(state: &wgpu::BlendState) -> BlendState {
1229    BlendState {
1230        color: Some(map_blend_component(&state.color)),
1231        alpha: Some(map_blend_component(&state.alpha)),
1232    }
1233}
1234
1235fn map_color_target_state(state: &wgpu::ColorTargetState) -> ColorTargetState {
1236    let mut out = ColorTargetState::new();
1237    out.format = Some(map_texture_format(state.format));
1238    out.blend = state.blend.as_ref().map(map_blend_state);
1239    out.write_mask = Some(map_color_write_mask(state.write_mask));
1240    out
1241}
1242
1243fn map_fragment_state(state: &wgpu::FragmentState<'_>) -> FragmentState {
1244    let mut out = FragmentState::new();
1245    out.module = Some(expect_shader_module_from_api(state.module));
1246    out.entry_point = state.entry_point.map(str::to_string);
1247    out.constants = Some(
1248        state
1249            .compilation_options
1250            .constants
1251            .iter()
1252            .map(|(k, v)| {
1253                let mut entry = ConstantEntry::new();
1254                entry.key = Some(k.to_string());
1255                entry.value = Some(*v);
1256                entry
1257            })
1258            .collect(),
1259    );
1260    out.targets = Some(
1261        state
1262            .targets
1263            .iter()
1264            .map(|t| t.as_ref().map(map_color_target_state).unwrap_or_default())
1265            .collect(),
1266    );
1267    out
1268}
1269
1270fn map_stencil_face_state(state: &wgpu::StencilFaceState) -> StencilFaceState {
1271    StencilFaceState {
1272        compare: Some(map_compare_function(state.compare)),
1273        fail_op: Some(map_stencil_operation(state.fail_op)),
1274        depth_fail_op: Some(map_stencil_operation(state.depth_fail_op)),
1275        pass_op: Some(map_stencil_operation(state.pass_op)),
1276    }
1277}
1278
1279fn map_depth_stencil_state(state: &wgpu::DepthStencilState) -> DepthStencilState {
1280    let mut out = DepthStencilState::new();
1281    out.format = Some(map_texture_format(state.format));
1282    out.depth_write_enabled = Some(if state.depth_write_enabled {
1283        OptionalBool::True
1284    } else {
1285        OptionalBool::False
1286    });
1287    out.depth_compare = Some(map_compare_function(state.depth_compare));
1288    out.stencil_front = Some(map_stencil_face_state(&state.stencil.front));
1289    out.stencil_back = Some(map_stencil_face_state(&state.stencil.back));
1290    out.stencil_read_mask = Some(state.stencil.read_mask);
1291    out.stencil_write_mask = Some(state.stencil.write_mask);
1292    out.depth_bias = Some(state.bias.constant);
1293    out.depth_bias_slope_scale = Some(state.bias.slope_scale);
1294    out.depth_bias_clamp = Some(state.bias.clamp);
1295    out
1296}
1297
1298fn map_multisample_state(state: wgpu::MultisampleState) -> MultisampleState {
1299    let mut out = MultisampleState::new();
1300    out.count = Some(state.count);
1301    out.mask = Some(state.mask.try_into().unwrap_or(u32::MAX));
1302    out.alpha_to_coverage_enabled = Some(state.alpha_to_coverage_enabled);
1303    out
1304}
1305
1306fn map_primitive_state(state: wgpu::PrimitiveState) -> PrimitiveState {
1307    let mut out = PrimitiveState::new();
1308    out.topology = Some(map_primitive_topology(state.topology));
1309    out.strip_index_format = state.strip_index_format.map(map_index_format);
1310    out.front_face = Some(map_front_face(state.front_face));
1311    out.cull_mode = Some(map_cull_mode(state.cull_mode));
1312    out.unclipped_depth = Some(state.unclipped_depth);
1313    out
1314}
1315
1316fn map_render_pipeline_descriptor(
1317    desc: &wgpu::RenderPipelineDescriptor<'_>,
1318) -> RenderPipelineDescriptor {
1319    let mut out = RenderPipelineDescriptor::new();
1320    out.label = label_to_string(desc.label);
1321    out.layout = desc.layout.map(expect_pipeline_layout_from_api);
1322    out.vertex = Some(map_vertex_state(&desc.vertex));
1323    out.primitive = Some(map_primitive_state(desc.primitive));
1324    out.depth_stencil = desc.depth_stencil.as_ref().map(map_depth_stencil_state);
1325    out.multisample = Some(map_multisample_state(desc.multisample));
1326    out.fragment = desc.fragment.as_ref().map(map_fragment_state);
1327    out
1328}
1329
1330fn map_compute_pipeline_descriptor(
1331    desc: &wgpu::ComputePipelineDescriptor<'_>,
1332) -> ComputePipelineDescriptor {
1333    let mut compute = ComputeState::new();
1334    compute.module = Some(expect_shader_module_from_api(desc.module));
1335    compute.entry_point = desc.entry_point.map(str::to_string);
1336    compute.constants = Some(
1337        desc.compilation_options
1338            .constants
1339            .iter()
1340            .map(|(k, v)| {
1341                let mut entry = ConstantEntry::new();
1342                entry.key = Some(k.to_string());
1343                entry.value = Some(*v);
1344                entry
1345            })
1346            .collect(),
1347    );
1348
1349    let mut out = ComputePipelineDescriptor::new();
1350    out.label = label_to_string(desc.label);
1351    out.layout = desc.layout.map(expect_pipeline_layout_from_api);
1352    out.compute = Some(compute);
1353    out
1354}
1355
1356fn map_command_encoder_descriptor(
1357    desc: &wgpu::CommandEncoderDescriptor<'_>,
1358) -> CommandEncoderDescriptor {
1359    let mut out = CommandEncoderDescriptor::new();
1360    out.label = label_to_string(desc.label);
1361    out
1362}
1363
1364fn map_render_bundle_encoder_descriptor(
1365    desc: &wgpu::RenderBundleEncoderDescriptor<'_>,
1366) -> RenderBundleEncoderDescriptor {
1367    let (depth_stencil_format, depth_read_only, stencil_read_only) = match desc.depth_stencil {
1368        Some(depth_stencil) => (
1369            Some(map_texture_format(depth_stencil.format)),
1370            Some(depth_stencil.depth_read_only),
1371            Some(depth_stencil.stencil_read_only),
1372        ),
1373        None => (None, None, None),
1374    };
1375    let mut out = RenderBundleEncoderDescriptor::new();
1376    out.label = label_to_string(desc.label);
1377    out.color_formats = Some(
1378        desc.color_formats
1379            .iter()
1380            .map(|v| {
1381                v.map(map_texture_format)
1382                    .unwrap_or(TextureFormat::Undefined)
1383            })
1384            .collect(),
1385    );
1386    out.depth_stencil_format = depth_stencil_format;
1387    out.sample_count = Some(desc.sample_count);
1388    out.depth_read_only = depth_read_only;
1389    out.stencil_read_only = stencil_read_only;
1390    out
1391}
1392
1393fn map_render_pass_color_attachment(
1394    attachment: &wgpu::RenderPassColorAttachment<'_>,
1395) -> RenderPassColorAttachment {
1396    let (load_op, clear_value) = match attachment.ops.load {
1397        wgpu::LoadOp::Load => (LoadOp::Load, None),
1398        wgpu::LoadOp::Clear(value) => (LoadOp::Clear, Some(map_color(value))),
1399        wgpu::LoadOp::DontCare(_) => (LoadOp::Load, None),
1400    };
1401    let mut out = RenderPassColorAttachment::new();
1402    out.view = Some(expect_texture_view_from_api(attachment.view));
1403    if let Some(depth_slice) = attachment.depth_slice {
1404        out.depth_slice = Some(depth_slice);
1405    }
1406    out.resolve_target = attachment.resolve_target.map(expect_texture_view_from_api);
1407    out.load_op = Some(load_op);
1408    out.store_op = Some(map_store_op(attachment.ops.store));
1409    out.clear_value = clear_value;
1410    out
1411}
1412
1413fn map_render_pass_depth_stencil_attachment(
1414    attachment: &wgpu::RenderPassDepthStencilAttachment<'_>,
1415) -> RenderPassDepthStencilAttachment {
1416    let depth_read_only = attachment.depth_ops.is_none();
1417    let stencil_read_only = attachment.stencil_ops.is_none();
1418    let (depth_load_op, depth_store_op, depth_clear_value) = match attachment.depth_ops.as_ref() {
1419        Some(ops) => match ops.load {
1420            wgpu::LoadOp::Load => (Some(LoadOp::Load), Some(map_store_op(ops.store)), None),
1421            wgpu::LoadOp::Clear(value) => (
1422                Some(LoadOp::Clear),
1423                Some(map_store_op(ops.store)),
1424                Some(value),
1425            ),
1426            wgpu::LoadOp::DontCare(_) => (Some(LoadOp::Load), Some(map_store_op(ops.store)), None),
1427        },
1428        None => (None, None, None),
1429    };
1430    let (stencil_load_op, stencil_store_op, stencil_clear_value) = match attachment
1431        .stencil_ops
1432        .as_ref()
1433    {
1434        Some(ops) => match ops.load {
1435            wgpu::LoadOp::Load => (Some(LoadOp::Load), Some(map_store_op(ops.store)), None),
1436            wgpu::LoadOp::Clear(value) => (
1437                Some(LoadOp::Clear),
1438                Some(map_store_op(ops.store)),
1439                Some(value),
1440            ),
1441            wgpu::LoadOp::DontCare(_) => (Some(LoadOp::Load), Some(map_store_op(ops.store)), None),
1442        },
1443        None => (None, None, None),
1444    };
1445    let mut out = RenderPassDepthStencilAttachment::new();
1446    out.view = Some(expect_texture_view_from_api(attachment.view));
1447    out.depth_load_op = depth_load_op;
1448    out.depth_store_op = depth_store_op;
1449    out.depth_clear_value = depth_clear_value;
1450    out.depth_read_only = Some(depth_read_only);
1451    out.stencil_load_op = stencil_load_op;
1452    out.stencil_store_op = stencil_store_op;
1453    out.stencil_clear_value = stencil_clear_value;
1454    out.stencil_read_only = Some(stencil_read_only);
1455    out
1456}
1457
1458fn map_render_pass_descriptor(desc: &wgpu::RenderPassDescriptor<'_>) -> RenderPassDescriptor {
1459    let mut out = RenderPassDescriptor::new();
1460    out.label = label_to_string(desc.label);
1461    out.color_attachments = Some(
1462        desc.color_attachments
1463            .iter()
1464            .map(|att| {
1465                att.as_ref()
1466                    .map(map_render_pass_color_attachment)
1467                    .unwrap_or_default()
1468            })
1469            .collect(),
1470    );
1471    out.depth_stencil_attachment = desc
1472        .depth_stencil_attachment
1473        .as_ref()
1474        .map(map_render_pass_depth_stencil_attachment);
1475    out.occlusion_query_set = desc.occlusion_query_set.map(expect_query_set_from_api);
1476    out.timestamp_writes = None;
1477    out
1478}
1479
1480fn map_compute_pass_descriptor(desc: &wgpu::ComputePassDescriptor<'_>) -> ComputePassDescriptor {
1481    let mut out = ComputePassDescriptor::new();
1482    out.label = label_to_string(desc.label);
1483    out.timestamp_writes = None;
1484    out
1485}
1486
1487fn map_surface_configuration(config: &wgpu::SurfaceConfiguration) -> SurfaceConfiguration {
1488    let mut out = SurfaceConfiguration::new();
1489    out.format = Some(map_texture_format(config.format));
1490    out.usage = Some(map_texture_usages(config.usage));
1491    out.width = Some(config.width);
1492    out.height = Some(config.height);
1493    out.present_mode = Some(match config.present_mode {
1494        wgpu::PresentMode::Fifo => PresentMode::Fifo,
1495        wgpu::PresentMode::Mailbox => PresentMode::Mailbox,
1496        wgpu::PresentMode::Immediate => PresentMode::Immediate,
1497        wgpu::PresentMode::AutoVsync => PresentMode::Fifo,
1498        wgpu::PresentMode::AutoNoVsync => PresentMode::Immediate,
1499        _ => PresentMode::Fifo,
1500    });
1501    out.alpha_mode = Some(match config.alpha_mode {
1502        wgpu::CompositeAlphaMode::Auto => CompositeAlphaMode::Auto,
1503        wgpu::CompositeAlphaMode::Opaque => CompositeAlphaMode::Opaque,
1504        wgpu::CompositeAlphaMode::PreMultiplied => CompositeAlphaMode::Premultiplied,
1505        wgpu::CompositeAlphaMode::PostMultiplied => CompositeAlphaMode::Premultiplied,
1506        wgpu::CompositeAlphaMode::Inherit => CompositeAlphaMode::Inherit,
1507        _ => CompositeAlphaMode::Auto,
1508    });
1509    out.view_formats = Some(
1510        config
1511            .view_formats
1512            .iter()
1513            .copied()
1514            .map(map_texture_format)
1515            .collect(),
1516    );
1517    out
1518}
1519
1520fn map_surface_capabilities(caps: SurfaceCapabilities) -> wgpu::SurfaceCapabilities {
1521    wgpu::SurfaceCapabilities {
1522        formats: caps
1523            .formats
1524            .clone()
1525            .unwrap_or_default()
1526            .iter()
1527            .copied()
1528            .map(map_texture_format_to_wgpu)
1529            .collect(),
1530        present_modes: caps
1531            .present_modes
1532            .clone()
1533            .unwrap_or_default()
1534            .iter()
1535            .copied()
1536            .map(|m| match m {
1537                PresentMode::Fifo => wgpu::PresentMode::Fifo,
1538                PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
1539                PresentMode::Immediate => wgpu::PresentMode::Immediate,
1540                PresentMode::FifoRelaxed => wgpu::PresentMode::AutoVsync,
1541                _ => wgpu::PresentMode::Fifo,
1542            })
1543            .collect(),
1544        alpha_modes: caps
1545            .alpha_modes
1546            .clone()
1547            .unwrap_or_default()
1548            .iter()
1549            .copied()
1550            .map(|m| match m {
1551                CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
1552                CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
1553                CompositeAlphaMode::Premultiplied => wgpu::CompositeAlphaMode::PreMultiplied,
1554                CompositeAlphaMode::Unpremultiplied => wgpu::CompositeAlphaMode::PostMultiplied,
1555                CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit,
1556                _ => wgpu::CompositeAlphaMode::Auto,
1557            })
1558            .collect(),
1559        usages: map_texture_usage_to_wgpu(caps.usages.unwrap_or(TextureUsage::RENDER_ATTACHMENT)),
1560    }
1561}
1562
1563fn map_compilation_info(info: &CompilationInfo) -> wgpu::CompilationInfo {
1564    wgpu::CompilationInfo {
1565        messages: info
1566            .messages
1567            .as_ref()
1568            .map(|messages| {
1569                messages
1570                    .iter()
1571                    .map(|message| wgpu::CompilationMessage {
1572                        message: message.message.clone().unwrap_or_default(),
1573                        message_type: match message.r#type.unwrap_or(CompilationMessageType::Info) {
1574                            CompilationMessageType::Error => wgpu::CompilationMessageType::Error,
1575                            CompilationMessageType::Warning => {
1576                                wgpu::CompilationMessageType::Warning
1577                            }
1578                            CompilationMessageType::Info => wgpu::CompilationMessageType::Info,
1579                        },
1580                        location: Some(wgpu::SourceLocation {
1581                            line_number: message.line_num.unwrap_or(0) as u32,
1582                            line_position: message.line_pos.unwrap_or(0) as u32,
1583                            offset: message.offset.unwrap_or(0) as u32,
1584                            length: message.length.unwrap_or(0) as u32,
1585                        }),
1586                    })
1587                    .collect()
1588            })
1589            .unwrap_or_default(),
1590    }
1591}
1592
1593fn map_uncaptured_error(error_type: ErrorType, message: String) -> wgpu::Error {
1594    match error_type {
1595        ErrorType::OutOfMemory => wgpu::Error::OutOfMemory {
1596            source: Box::new(DawnError(message)),
1597        },
1598        ErrorType::Validation => wgpu::Error::Validation {
1599            source: Box::new(DawnError(message.clone())),
1600            description: message,
1601        },
1602        ErrorType::Internal | ErrorType::Unknown => wgpu::Error::Internal {
1603            source: Box::new(DawnError(message.clone())),
1604            description: message,
1605        },
1606        ErrorType::NoError => wgpu::Error::Internal {
1607            source: Box::new(DawnError("no error".to_string())),
1608            description: "no error".to_string(),
1609        },
1610    }
1611}
1612
1613fn map_limits_to_dawn(limits: &wgpu::Limits) -> Limits {
1614    let mut out = Limits::new();
1615    out.max_texture_dimension_1d = Some(limits.max_texture_dimension_1d);
1616    out.max_texture_dimension_2d = Some(limits.max_texture_dimension_2d);
1617    out.max_texture_dimension_3d = Some(limits.max_texture_dimension_3d);
1618    out.max_texture_array_layers = Some(limits.max_texture_array_layers);
1619    out.max_bind_groups = Some(limits.max_bind_groups);
1620    out.max_bindings_per_bind_group = Some(limits.max_bindings_per_bind_group);
1621    out.max_dynamic_uniform_buffers_per_pipeline_layout =
1622        Some(limits.max_dynamic_uniform_buffers_per_pipeline_layout);
1623    out.max_dynamic_storage_buffers_per_pipeline_layout =
1624        Some(limits.max_dynamic_storage_buffers_per_pipeline_layout);
1625    out.max_sampled_textures_per_shader_stage = Some(limits.max_sampled_textures_per_shader_stage);
1626    out.max_samplers_per_shader_stage = Some(limits.max_samplers_per_shader_stage);
1627    out.max_storage_buffers_per_shader_stage = Some(limits.max_storage_buffers_per_shader_stage);
1628    out.max_storage_textures_per_shader_stage = Some(limits.max_storage_textures_per_shader_stage);
1629    out.max_uniform_buffers_per_shader_stage = Some(limits.max_uniform_buffers_per_shader_stage);
1630    out.max_uniform_buffer_binding_size = Some(limits.max_uniform_buffer_binding_size as u64);
1631    out.max_storage_buffer_binding_size = Some(limits.max_storage_buffer_binding_size as u64);
1632    out.min_uniform_buffer_offset_alignment = Some(limits.min_uniform_buffer_offset_alignment);
1633    out.min_storage_buffer_offset_alignment = Some(limits.min_storage_buffer_offset_alignment);
1634    out.max_vertex_buffers = Some(limits.max_vertex_buffers);
1635    out.max_buffer_size = Some(limits.max_buffer_size);
1636    out.max_vertex_attributes = Some(limits.max_vertex_attributes);
1637    out.max_vertex_buffer_array_stride = Some(limits.max_vertex_buffer_array_stride);
1638    out.max_inter_stage_shader_variables = Some(limits.max_inter_stage_shader_components);
1639    out.max_color_attachments = Some(limits.max_color_attachments);
1640    out.max_color_attachment_bytes_per_sample = Some(limits.max_color_attachment_bytes_per_sample);
1641    out.max_compute_workgroup_storage_size = Some(limits.max_compute_workgroup_storage_size);
1642    out.max_compute_invocations_per_workgroup = Some(limits.max_compute_invocations_per_workgroup);
1643    out.max_compute_workgroup_size_x = Some(limits.max_compute_workgroup_size_x);
1644    out.max_compute_workgroup_size_y = Some(limits.max_compute_workgroup_size_y);
1645    out.max_compute_workgroup_size_z = Some(limits.max_compute_workgroup_size_z);
1646    out.max_compute_workgroups_per_dimension = Some(limits.max_compute_workgroups_per_dimension);
1647    out.max_bind_groups_plus_vertex_buffers =
1648        Some(limits.max_bind_groups + limits.max_vertex_buffers);
1649    out
1650}
1651
1652fn map_limits_to_wgpu(limits: &Limits) -> wgpu::Limits {
1653    let mut out = wgpu::Limits::default();
1654    if let Some(value) = limits.max_texture_dimension_1d {
1655        out.max_texture_dimension_1d = value;
1656    }
1657    if let Some(value) = limits.max_texture_dimension_2d {
1658        out.max_texture_dimension_2d = value;
1659    }
1660    if let Some(value) = limits.max_texture_dimension_3d {
1661        out.max_texture_dimension_3d = value;
1662    }
1663    if let Some(value) = limits.max_texture_array_layers {
1664        out.max_texture_array_layers = value;
1665    }
1666    if let Some(value) = limits.max_bind_groups {
1667        out.max_bind_groups = value;
1668    }
1669    if let Some(value) = limits.max_bindings_per_bind_group {
1670        out.max_bindings_per_bind_group = value;
1671    }
1672    if let Some(value) = limits.max_dynamic_uniform_buffers_per_pipeline_layout {
1673        out.max_dynamic_uniform_buffers_per_pipeline_layout = value;
1674    }
1675    if let Some(value) = limits.max_dynamic_storage_buffers_per_pipeline_layout {
1676        out.max_dynamic_storage_buffers_per_pipeline_layout = value;
1677    }
1678    if let Some(value) = limits.max_sampled_textures_per_shader_stage {
1679        out.max_sampled_textures_per_shader_stage = value;
1680    }
1681    if let Some(value) = limits.max_samplers_per_shader_stage {
1682        out.max_samplers_per_shader_stage = value;
1683    }
1684    if let Some(value) = limits.max_storage_buffers_per_shader_stage {
1685        out.max_storage_buffers_per_shader_stage = value;
1686    }
1687    if let Some(value) = limits.max_storage_textures_per_shader_stage {
1688        out.max_storage_textures_per_shader_stage = value;
1689    }
1690    if let Some(value) = limits.max_uniform_buffers_per_shader_stage {
1691        out.max_uniform_buffers_per_shader_stage = value;
1692    }
1693    if let Some(value) = limits.max_uniform_buffer_binding_size {
1694        out.max_uniform_buffer_binding_size = value as u32;
1695    }
1696    if let Some(value) = limits.max_storage_buffer_binding_size {
1697        out.max_storage_buffer_binding_size = value as u32;
1698    }
1699    if let Some(value) = limits.min_uniform_buffer_offset_alignment {
1700        out.min_uniform_buffer_offset_alignment = value;
1701    }
1702    if let Some(value) = limits.min_storage_buffer_offset_alignment {
1703        out.min_storage_buffer_offset_alignment = value;
1704    }
1705    if let Some(value) = limits.max_vertex_buffers {
1706        out.max_vertex_buffers = value;
1707    }
1708    if let Some(value) = limits.max_buffer_size {
1709        out.max_buffer_size = value;
1710    }
1711    if let Some(value) = limits.max_vertex_attributes {
1712        out.max_vertex_attributes = value;
1713    }
1714    if let Some(value) = limits.max_vertex_buffer_array_stride {
1715        out.max_vertex_buffer_array_stride = value;
1716    }
1717    if let Some(value) = limits.max_inter_stage_shader_variables {
1718        out.max_inter_stage_shader_components = value;
1719    }
1720    if let Some(value) = limits.max_color_attachments {
1721        out.max_color_attachments = value;
1722    }
1723    if let Some(value) = limits.max_color_attachment_bytes_per_sample {
1724        out.max_color_attachment_bytes_per_sample = value;
1725    }
1726    if let Some(value) = limits.max_compute_workgroup_storage_size {
1727        out.max_compute_workgroup_storage_size = value;
1728    }
1729    if let Some(value) = limits.max_compute_invocations_per_workgroup {
1730        out.max_compute_invocations_per_workgroup = value;
1731    }
1732    if let Some(value) = limits.max_compute_workgroup_size_x {
1733        out.max_compute_workgroup_size_x = value;
1734    }
1735    if let Some(value) = limits.max_compute_workgroup_size_y {
1736        out.max_compute_workgroup_size_y = value;
1737    }
1738    if let Some(value) = limits.max_compute_workgroup_size_z {
1739        out.max_compute_workgroup_size_z = value;
1740    }
1741    if let Some(value) = limits.max_compute_workgroups_per_dimension {
1742        out.max_compute_workgroups_per_dimension = value;
1743    }
1744    out
1745}
1746
1747fn map_features_to_dawn(features: wgpu::Features) -> Vec<FeatureName> {
1748    let mut out = Vec::new();
1749    if features.contains(wgpu::Features::DEPTH_CLIP_CONTROL) {
1750        out.push(FeatureName::DepthClipControl);
1751    }
1752    if features.contains(wgpu::Features::DEPTH32FLOAT_STENCIL8) {
1753        out.push(FeatureName::Depth32FloatStencil8);
1754    }
1755    if features.contains(wgpu::Features::TEXTURE_COMPRESSION_BC) {
1756        out.push(FeatureName::TextureCompressionBc);
1757    }
1758    if features.contains(wgpu::Features::TEXTURE_COMPRESSION_BC_SLICED_3D) {
1759        out.push(FeatureName::TextureCompressionBcSliced3D);
1760    }
1761    if features.contains(wgpu::Features::TEXTURE_COMPRESSION_ETC2) {
1762        out.push(FeatureName::TextureCompressionEtc2);
1763    }
1764    if features.contains(wgpu::Features::TEXTURE_COMPRESSION_ASTC) {
1765        out.push(FeatureName::TextureCompressionAstc);
1766    }
1767    if features.contains(wgpu::Features::TEXTURE_COMPRESSION_ASTC_HDR) {
1768        out.push(FeatureName::TextureCompressionAstc);
1769    }
1770    if features.contains(wgpu::Features::TIMESTAMP_QUERY) {
1771        out.push(FeatureName::TimestampQuery);
1772    }
1773    if features.contains(wgpu::Features::INDIRECT_FIRST_INSTANCE) {
1774        out.push(FeatureName::IndirectFirstInstance);
1775    }
1776    if features.contains(wgpu::Features::SHADER_F16) {
1777        out.push(FeatureName::ShaderF16);
1778    }
1779    if features.contains(wgpu::Features::RG11B10UFLOAT_RENDERABLE) {
1780        out.push(FeatureName::Rg11B10UfloatRenderable);
1781    }
1782    if features.contains(wgpu::Features::BGRA8UNORM_STORAGE) {
1783        out.push(FeatureName::Bgra8UnormStorage);
1784    }
1785    if features.contains(wgpu::Features::FLOAT32_FILTERABLE) {
1786        out.push(FeatureName::Float32Filterable);
1787    }
1788    if features.contains(wgpu::Features::CLIP_DISTANCES) {
1789        out.push(FeatureName::ClipDistances);
1790    }
1791    if features.contains(wgpu::Features::DUAL_SOURCE_BLENDING) {
1792        out.push(FeatureName::DualSourceBlending);
1793    }
1794    if features.contains(wgpu::Features::SUBGROUP) {
1795        out.push(FeatureName::Subgroups);
1796    }
1797    if features.contains(wgpu::Features::TEXTURE_FORMAT_16BIT_NORM) {
1798        out.push(FeatureName::Unorm16TextureFormats);
1799    }
1800    if features.contains(wgpu::Features::MULTI_DRAW_INDIRECT_COUNT) {
1801        out.push(FeatureName::MultiDrawIndirect);
1802    }
1803    out
1804}
1805
1806fn map_features_to_wgpu(features: &SupportedFeatures) -> wgpu::Features {
1807    let mut out = wgpu::Features::empty();
1808    if let Some(list) = &features.features {
1809        for feature in list {
1810            match feature {
1811                FeatureName::DepthClipControl => out |= wgpu::Features::DEPTH_CLIP_CONTROL,
1812                FeatureName::Depth32FloatStencil8 => out |= wgpu::Features::DEPTH32FLOAT_STENCIL8,
1813                FeatureName::TextureCompressionBc => out |= wgpu::Features::TEXTURE_COMPRESSION_BC,
1814                FeatureName::TextureCompressionBcSliced3D => {
1815                    out |= wgpu::Features::TEXTURE_COMPRESSION_BC_SLICED_3D
1816                }
1817                FeatureName::TextureCompressionEtc2 => {
1818                    out |= wgpu::Features::TEXTURE_COMPRESSION_ETC2
1819                }
1820                FeatureName::TextureCompressionAstc => {
1821                    out |= wgpu::Features::TEXTURE_COMPRESSION_ASTC
1822                }
1823                FeatureName::TimestampQuery => out |= wgpu::Features::TIMESTAMP_QUERY,
1824                FeatureName::IndirectFirstInstance => {
1825                    out |= wgpu::Features::INDIRECT_FIRST_INSTANCE
1826                }
1827                FeatureName::ShaderF16 => out |= wgpu::Features::SHADER_F16,
1828                FeatureName::Rg11B10UfloatRenderable => {
1829                    out |= wgpu::Features::RG11B10UFLOAT_RENDERABLE
1830                }
1831                FeatureName::Bgra8UnormStorage => out |= wgpu::Features::BGRA8UNORM_STORAGE,
1832                FeatureName::Float32Filterable => out |= wgpu::Features::FLOAT32_FILTERABLE,
1833                FeatureName::Float32Blendable => {}
1834                FeatureName::ClipDistances => out |= wgpu::Features::CLIP_DISTANCES,
1835                FeatureName::DualSourceBlending => out |= wgpu::Features::DUAL_SOURCE_BLENDING,
1836                FeatureName::Subgroups => out |= wgpu::Features::SUBGROUP,
1837                FeatureName::Unorm16TextureFormats => {
1838                    out |= wgpu::Features::TEXTURE_FORMAT_16BIT_NORM
1839                }
1840                FeatureName::MultiDrawIndirect => out |= wgpu::Features::MULTI_DRAW_INDIRECT_COUNT,
1841                _ => {}
1842            }
1843        }
1844    }
1845    out
1846}
1847
1848fn bytes_to_u32(data: &[u8]) -> Vec<u32> {
1849    let mut out = Vec::with_capacity((data.len() + 3) / 4);
1850    for chunk in data.chunks(4) {
1851        let mut buf = [0u8; 4];
1852        buf[..chunk.len()].copy_from_slice(chunk);
1853        out.push(u32::from_le_bytes(buf));
1854    }
1855    out
1856}
1857
1858fn dispatch_adapter(adapter: Adapter) -> DispatchAdapter {
1859    DispatchAdapter::custom(DawnAdapter { inner: adapter })
1860}
1861
1862fn dispatch_device(device: Device) -> DispatchDevice {
1863    DispatchDevice::custom(DawnDevice { inner: device })
1864}
1865
1866fn dispatch_queue(queue: Queue) -> DispatchQueue {
1867    DispatchQueue::custom(DawnQueue { inner: queue })
1868}
1869
1870fn dispatch_surface(surface: DawnSurface) -> DispatchSurface {
1871    DispatchSurface::custom(surface)
1872}
1873
1874fn dispatch_shader_module(module: ShaderModule) -> DispatchShaderModule {
1875    DispatchShaderModule::custom(DawnShaderModule { inner: module })
1876}
1877
1878fn dispatch_bind_group_layout(layout: BindGroupLayout) -> DispatchBindGroupLayout {
1879    DispatchBindGroupLayout::custom(DawnBindGroupLayout { inner: layout })
1880}
1881
1882fn dispatch_bind_group(group: BindGroup) -> DispatchBindGroup {
1883    DispatchBindGroup::custom(DawnBindGroup { inner: group })
1884}
1885
1886fn dispatch_texture_view(view: TextureView) -> DispatchTextureView {
1887    DispatchTextureView::custom(DawnTextureView { inner: view })
1888}
1889
1890fn dispatch_sampler(sampler: Sampler) -> DispatchSampler {
1891    DispatchSampler::custom(DawnSampler { inner: sampler })
1892}
1893
1894fn dispatch_buffer(buffer: Buffer) -> DispatchBuffer {
1895    DispatchBuffer::custom(DawnBuffer { inner: buffer })
1896}
1897
1898fn dispatch_texture(texture: Texture) -> DispatchTexture {
1899    DispatchTexture::custom(DawnTexture { inner: texture })
1900}
1901
1902fn dispatch_external_texture(texture: ExternalTexture) -> DispatchExternalTexture {
1903    DispatchExternalTexture::custom(DawnExternalTexture { inner: texture })
1904}
1905
1906fn dispatch_query_set(query_set: QuerySet) -> DispatchQuerySet {
1907    DispatchQuerySet::custom(DawnQuerySet { inner: query_set })
1908}
1909
1910fn dispatch_pipeline_layout(layout: PipelineLayout) -> DispatchPipelineLayout {
1911    DispatchPipelineLayout::custom(DawnPipelineLayout { inner: layout })
1912}
1913
1914fn dispatch_render_pipeline(pipeline: RenderPipeline) -> DispatchRenderPipeline {
1915    DispatchRenderPipeline::custom(DawnRenderPipeline { inner: pipeline })
1916}
1917
1918fn dispatch_compute_pipeline(pipeline: ComputePipeline) -> DispatchComputePipeline {
1919    DispatchComputePipeline::custom(DawnComputePipeline { inner: pipeline })
1920}
1921
1922fn dispatch_command_encoder(encoder: CommandEncoder) -> DispatchCommandEncoder {
1923    DispatchCommandEncoder::custom(DawnCommandEncoder { inner: encoder })
1924}
1925
1926fn dispatch_command_buffer(buffer: CommandBuffer) -> DispatchCommandBuffer {
1927    DispatchCommandBuffer::custom(DawnCommandBuffer { inner: buffer })
1928}
1929
1930fn dispatch_compute_pass(pass: ComputePassEncoder) -> DispatchComputePass {
1931    DispatchComputePass::custom(DawnComputePass {
1932        inner: pass,
1933        ended: false,
1934    })
1935}
1936
1937fn dispatch_render_pass(pass: RenderPassEncoder) -> DispatchRenderPass {
1938    DispatchRenderPass::custom(DawnRenderPass {
1939        inner: pass,
1940        ended: false,
1941    })
1942}
1943
1944fn dispatch_render_bundle_encoder(encoder: RenderBundleEncoder) -> DispatchRenderBundleEncoder {
1945    DispatchRenderBundleEncoder::custom(DawnRenderBundleEncoder { inner: encoder })
1946}
1947
1948fn dispatch_render_bundle(bundle: RenderBundle) -> DispatchRenderBundle {
1949    DispatchRenderBundle::custom(DawnRenderBundle { inner: bundle })
1950}
1951
1952fn dispatch_surface_output_detail(surface: Surface) -> DispatchSurfaceOutputDetail {
1953    DispatchSurfaceOutputDetail::custom(DawnSurfaceOutputDetail { surface })
1954}
1955
1956fn dispatch_queue_write_buffer(data: Vec<u8>) -> DispatchQueueWriteBuffer {
1957    DispatchQueueWriteBuffer::custom(DawnQueueWriteBuffer { inner: data })
1958}
1959
1960fn dispatch_buffer_mapped_range(ptr: *mut u8, size: usize) -> DispatchBufferMappedRange {
1961    DispatchBufferMappedRange::custom(DawnBufferMappedRange { data: ptr, size })
1962}
1963
1964fn dispatch_pipeline_cache() -> DispatchPipelineCache {
1965    DispatchPipelineCache::custom(DawnPipelineCache)
1966}
1967
1968fn dispatch_blas() -> DispatchBlas {
1969    DispatchBlas::custom(DawnBlas)
1970}
1971
1972fn dispatch_tlas() -> DispatchTlas {
1973    DispatchTlas::custom(DawnTlas)
1974}
1975
1976fn expect_adapter(adapter: &DispatchAdapter) -> Adapter {
1977    adapter
1978        .as_custom::<DawnAdapter>()
1979        .expect("wgpu-compat: adapter not dawn")
1980        .inner
1981        .clone()
1982}
1983
1984fn expect_device(device: &DispatchDevice) -> Device {
1985    device
1986        .as_custom::<DawnDevice>()
1987        .expect("wgpu-compat: device not dawn")
1988        .inner
1989        .clone()
1990}
1991
1992fn expect_queue(queue: &DispatchQueue) -> Queue {
1993    queue
1994        .as_custom::<DawnQueue>()
1995        .expect("wgpu-compat: queue not dawn")
1996        .inner
1997        .clone()
1998}
1999
2000fn expect_surface(surface: &DispatchSurface) -> DawnSurface {
2001    surface
2002        .as_custom::<DawnSurface>()
2003        .expect("wgpu-compat: surface not dawn")
2004        .clone()
2005}
2006
2007fn expect_shader_module(module: &DispatchShaderModule) -> ShaderModule {
2008    module
2009        .as_custom::<DawnShaderModule>()
2010        .expect("wgpu-compat: shader module not dawn")
2011        .inner
2012        .clone()
2013}
2014
2015fn expect_bind_group_layout(layout: &DispatchBindGroupLayout) -> BindGroupLayout {
2016    layout
2017        .as_custom::<DawnBindGroupLayout>()
2018        .expect("wgpu-compat: bind group layout not dawn")
2019        .inner
2020        .clone()
2021}
2022
2023fn expect_bind_group(group: &DispatchBindGroup) -> BindGroup {
2024    group
2025        .as_custom::<DawnBindGroup>()
2026        .expect("wgpu-compat: bind group not dawn")
2027        .inner
2028        .clone()
2029}
2030
2031fn expect_texture_view(view: &DispatchTextureView) -> TextureView {
2032    view.as_custom::<DawnTextureView>()
2033        .expect("wgpu-compat: texture view not dawn")
2034        .inner
2035        .clone()
2036}
2037
2038fn expect_sampler(sampler: &DispatchSampler) -> Sampler {
2039    sampler
2040        .as_custom::<DawnSampler>()
2041        .expect("wgpu-compat: sampler not dawn")
2042        .inner
2043        .clone()
2044}
2045
2046fn expect_buffer(buffer: &DispatchBuffer) -> Buffer {
2047    buffer
2048        .as_custom::<DawnBuffer>()
2049        .expect("wgpu-compat: buffer not dawn")
2050        .inner
2051        .clone()
2052}
2053
2054fn expect_texture(texture: &DispatchTexture) -> Texture {
2055    texture
2056        .as_custom::<DawnTexture>()
2057        .expect("wgpu-compat: texture not dawn")
2058        .inner
2059        .clone()
2060}
2061
2062fn expect_external_texture(texture: &DispatchExternalTexture) -> ExternalTexture {
2063    texture
2064        .as_custom::<DawnExternalTexture>()
2065        .expect("wgpu-compat: external texture not dawn")
2066        .inner
2067        .clone()
2068}
2069
2070fn expect_query_set(query_set: &DispatchQuerySet) -> QuerySet {
2071    query_set
2072        .as_custom::<DawnQuerySet>()
2073        .expect("wgpu-compat: query set not dawn")
2074        .inner
2075        .clone()
2076}
2077
2078fn expect_pipeline_layout(layout: &DispatchPipelineLayout) -> PipelineLayout {
2079    layout
2080        .as_custom::<DawnPipelineLayout>()
2081        .expect("wgpu-compat: pipeline layout not dawn")
2082        .inner
2083        .clone()
2084}
2085
2086fn expect_render_pipeline(pipeline: &DispatchRenderPipeline) -> RenderPipeline {
2087    pipeline
2088        .as_custom::<DawnRenderPipeline>()
2089        .expect("wgpu-compat: render pipeline not dawn")
2090        .inner
2091        .clone()
2092}
2093
2094fn expect_compute_pipeline(pipeline: &DispatchComputePipeline) -> ComputePipeline {
2095    pipeline
2096        .as_custom::<DawnComputePipeline>()
2097        .expect("wgpu-compat: compute pipeline not dawn")
2098        .inner
2099        .clone()
2100}
2101
2102fn expect_command_encoder(encoder: &DispatchCommandEncoder) -> CommandEncoder {
2103    encoder
2104        .as_custom::<DawnCommandEncoder>()
2105        .expect("wgpu-compat: command encoder not dawn")
2106        .inner
2107        .clone()
2108}
2109
2110fn expect_command_buffer(buffer: &DispatchCommandBuffer) -> CommandBuffer {
2111    buffer
2112        .as_custom::<DawnCommandBuffer>()
2113        .expect("wgpu-compat: command buffer not dawn")
2114        .inner
2115        .clone()
2116}
2117
2118fn expect_render_bundle(bundle: &DispatchRenderBundle) -> RenderBundle {
2119    bundle
2120        .as_custom::<DawnRenderBundle>()
2121        .expect("wgpu-compat: render bundle not dawn")
2122        .inner
2123        .clone()
2124}
2125
2126fn expect_surface_output_detail(detail: &DispatchSurfaceOutputDetail) -> Surface {
2127    detail
2128        .as_custom::<DawnSurfaceOutputDetail>()
2129        .expect("wgpu-compat: surface output detail not dawn")
2130        .surface
2131        .clone()
2132}
2133
2134fn expect_device_from_api(device: &wgpu::Device) -> Device {
2135    device
2136        .as_custom::<DawnDevice>()
2137        .expect("wgpu-compat: device not dawn")
2138        .inner
2139        .clone()
2140}
2141
2142fn expect_surface_from_api(surface: &wgpu::Surface) -> DawnSurface {
2143    surface
2144        .as_custom::<DawnSurface>()
2145        .expect("wgpu-compat: surface not dawn")
2146        .clone()
2147}
2148
2149fn expect_buffer_from_api(buffer: &wgpu::Buffer) -> Buffer {
2150    buffer
2151        .as_custom::<DawnBuffer>()
2152        .expect("wgpu-compat: buffer not dawn")
2153        .inner
2154        .clone()
2155}
2156
2157fn expect_texture_from_api(texture: &wgpu::Texture) -> Texture {
2158    texture
2159        .as_custom::<DawnTexture>()
2160        .expect("wgpu-compat: texture not dawn")
2161        .inner
2162        .clone()
2163}
2164
2165fn expect_texture_view_from_api(view: &wgpu::TextureView) -> TextureView {
2166    view.as_custom::<DawnTextureView>()
2167        .expect("wgpu-compat: texture view not dawn")
2168        .inner
2169        .clone()
2170}
2171
2172fn expect_sampler_from_api(sampler: &wgpu::Sampler) -> Sampler {
2173    sampler
2174        .as_custom::<DawnSampler>()
2175        .expect("wgpu-compat: sampler not dawn")
2176        .inner
2177        .clone()
2178}
2179
2180fn expect_bind_group_layout_from_api(layout: &wgpu::BindGroupLayout) -> BindGroupLayout {
2181    layout
2182        .as_custom::<DawnBindGroupLayout>()
2183        .expect("wgpu-compat: bind group layout not dawn")
2184        .inner
2185        .clone()
2186}
2187
2188fn expect_pipeline_layout_from_api(layout: &wgpu::PipelineLayout) -> PipelineLayout {
2189    layout
2190        .as_custom::<DawnPipelineLayout>()
2191        .expect("wgpu-compat: pipeline layout not dawn")
2192        .inner
2193        .clone()
2194}
2195
2196fn expect_shader_module_from_api(module: &wgpu::ShaderModule) -> ShaderModule {
2197    module
2198        .as_custom::<DawnShaderModule>()
2199        .expect("wgpu-compat: shader module not dawn")
2200        .inner
2201        .clone()
2202}
2203
2204fn expect_bind_group_from_api(group: &wgpu::BindGroup) -> BindGroup {
2205    group
2206        .as_custom::<DawnBindGroup>()
2207        .expect("wgpu-compat: bind group not dawn")
2208        .inner
2209        .clone()
2210}
2211
2212fn expect_query_set_from_api(query_set: &wgpu::QuerySet) -> QuerySet {
2213    query_set
2214        .as_custom::<DawnQuerySet>()
2215        .expect("wgpu-compat: query set not dawn")
2216        .inner
2217        .clone()
2218}
2219
2220impl InstanceInterface for DawnInstance {
2221    fn new(_desc: &wgpu::InstanceDescriptor) -> Self {
2222        let mut desc = InstanceDescriptor::new();
2223        desc.required_features = Some(vec![InstanceFeatureName::TimedWaitAny]);
2224        let instance = Instance::new(Some(&desc));
2225        Self { inner: instance }
2226    }
2227
2228    unsafe fn create_surface(
2229        &self,
2230        target: wgpu::SurfaceTargetUnsafe,
2231    ) -> Result<DispatchSurface, wgpu::CreateSurfaceError> {
2232        match target {
2233            #[cfg(target_os = "macos")]
2234            wgpu::SurfaceTargetUnsafe::CoreAnimationLayer(layer) => {
2235                let mut desc = SurfaceDescriptor::new();
2236                let source = SurfaceSourceMetalLayer { layer: Some(layer) };
2237                desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2238                let surface = self.inner.create_surface(&desc);
2239                let dawn_surface = DawnSurface {
2240                    inner: surface,
2241                    metal_layer: None,
2242                };
2243                Ok(dispatch_surface(dawn_surface))
2244            }
2245            #[cfg(target_os = "macos")]
2246            wgpu::SurfaceTargetUnsafe::RawHandle {
2247                raw_window_handle, ..
2248            } => {
2249                use wgpu::rwh::RawWindowHandle;
2250                match raw_window_handle {
2251                    RawWindowHandle::AppKit(handle) => {
2252                        let layer =
2253                            unsafe { raw_window_metal::Layer::from_ns_view(handle.ns_view) };
2254                        let layer_ptr = layer.into_raw();
2255                        let mut desc = SurfaceDescriptor::new();
2256                        let source = SurfaceSourceMetalLayer {
2257                            layer: Some(layer_ptr.as_ptr().cast()),
2258                        };
2259                        desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2260                        let surface = self.inner.create_surface(&desc);
2261                        let handle = MetalLayerHandle {
2262                            ptr: layer_ptr.as_ptr().cast(),
2263                        };
2264                        let dawn_surface = DawnSurface {
2265                            inner: surface,
2266                            metal_layer: Some(Arc::new(handle)),
2267                        };
2268                        Ok(dispatch_surface(dawn_surface))
2269                    }
2270                    _ => panic!("wgpu-compat: unsupported raw window handle on macOS"),
2271                }
2272            }
2273            #[cfg(target_os = "windows")]
2274            wgpu::SurfaceTargetUnsafe::RawHandle {
2275                raw_window_handle, ..
2276            } => {
2277                use wgpu::rwh::RawWindowHandle;
2278                match raw_window_handle {
2279                    RawWindowHandle::Win32(handle) => {
2280                        let mut desc = SurfaceDescriptor::new();
2281                        let source = SurfaceSourceWindowsHWND {
2282                            hinstance: Some(handle.hinstance.cast()),
2283                            hwnd: Some(handle.hwnd.cast()),
2284                        };
2285                        desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2286                        let surface = self.inner.create_surface(&desc);
2287                        let dawn_surface = DawnSurface { inner: surface };
2288                        Ok(dispatch_surface(dawn_surface))
2289                    }
2290                    _ => panic!("wgpu-compat: unsupported raw window handle on Windows"),
2291                }
2292            }
2293            #[cfg(all(unix, not(target_vendor = "apple")))]
2294            wgpu::SurfaceTargetUnsafe::RawHandle {
2295                raw_display_handle,
2296                raw_window_handle,
2297            } => {
2298                use wgpu::rwh::{RawDisplayHandle, RawWindowHandle};
2299                match (raw_display_handle, raw_window_handle) {
2300                    (RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(window)) => {
2301                        let mut desc = SurfaceDescriptor::new();
2302                        let source = SurfaceSourceWaylandSurface {
2303                            display: Some(display.display.cast()),
2304                            surface: Some(window.surface.cast()),
2305                        };
2306                        desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2307                        let surface = self.inner.create_surface(&desc);
2308                        let dawn_surface = DawnSurface { inner: surface };
2309                        Ok(dispatch_surface(dawn_surface))
2310                    }
2311                    (RawDisplayHandle::Xlib(display), RawWindowHandle::Xlib(window)) => {
2312                        let mut desc = SurfaceDescriptor::new();
2313                        let source = SurfaceSourceXlibWindow {
2314                            display: Some(display.display.cast()),
2315                            window: Some(window.window as u64),
2316                        };
2317                        desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2318                        let surface = self.inner.create_surface(&desc);
2319                        let dawn_surface = DawnSurface { inner: surface };
2320                        Ok(dispatch_surface(dawn_surface))
2321                    }
2322                    (RawDisplayHandle::Xcb(display), RawWindowHandle::Xcb(window)) => {
2323                        let mut desc = SurfaceDescriptor::new();
2324                        let source = SurfaceSourceXCBWindow {
2325                            connection: Some(display.connection.cast()),
2326                            window: Some(window.window),
2327                        };
2328                        desc = desc.with_extension(SurfaceDescriptorExtension::from(source));
2329                        let surface = self.inner.create_surface(&desc);
2330                        let dawn_surface = DawnSurface { inner: surface };
2331                        Ok(dispatch_surface(dawn_surface))
2332                    }
2333                    _ => panic!("wgpu-compat: unsupported raw window handle on unix"),
2334                }
2335            }
2336            _ => panic!("wgpu-compat: unsupported surface target"),
2337        }
2338    }
2339
2340    fn request_adapter(
2341        &self,
2342        options: &wgpu::RequestAdapterOptions<'_, '_>,
2343    ) -> Pin<Box<dyn wgpu::custom::RequestAdapterFuture>> {
2344        let (future, shared) = CallbackFuture::new();
2345        let mut dawn_options = RequestAdapterOptions::new();
2346        dawn_options.power_preference = Some(map_power_preference(options.power_preference));
2347        dawn_options.force_fallback_adapter = Some(options.force_fallback_adapter);
2348        if let Some(surface) = options.compatible_surface {
2349            dawn_options.compatible_surface = Some(expect_surface_from_api(surface).inner);
2350        }
2351        let future_handle =
2352            self.inner
2353                .request_adapter(Some(&dawn_options), move |status, adapter, _message| {
2354                    if status == RequestAdapterStatus::Success {
2355                        let adapter = adapter.expect("wgpu-compat: missing adapter");
2356                        complete_shared(&shared, Ok(dispatch_adapter(adapter)));
2357                    } else {
2358                        complete_shared(
2359                            &shared,
2360                            Err(wgpu::RequestAdapterError::NotFound {
2361                                active_backends: wgpu::Backends::empty(),
2362                                requested_backends: wgpu::Backends::empty(),
2363                                supported_backends: wgpu::Backends::empty(),
2364                                no_fallback_backends: wgpu::Backends::empty(),
2365                                no_adapter_backends: wgpu::Backends::empty(),
2366                                incompatible_surface_backends: wgpu::Backends::empty(),
2367                            }),
2368                        );
2369                    }
2370                });
2371        let _ = self.inner.wait_any(
2372            Some(&mut [FutureWaitInfo {
2373                future: Some(future_handle),
2374                completed: None,
2375            }]),
2376            0,
2377        );
2378        Box::pin(future)
2379    }
2380
2381    fn poll_all_devices(&self, _force_wait: bool) -> bool {
2382        self.inner.process_events();
2383        true
2384    }
2385
2386    fn wgsl_language_features(&self) -> wgpu::WgslLanguageFeatures {
2387        let mut features = SupportedWGSLLanguageFeatures::new();
2388        self.inner.get_wgsl_language_features(&mut features);
2389        let mut out = wgpu::WgslLanguageFeatures::empty();
2390        if let Some(list) = features.features.as_ref() {
2391            for feature in list {
2392                if *feature == WGSLLanguageFeatureName::ReadonlyAndReadwriteStorageTextures {
2393                    out |= wgpu::WgslLanguageFeatures::ReadOnlyAndReadWriteStorageTextures;
2394                }
2395            }
2396        }
2397        out
2398    }
2399
2400    fn enumerate_adapters(
2401        &self,
2402        _backends: wgpu::Backends,
2403    ) -> Pin<Box<dyn wgpu::custom::EnumerateAdapterFuture>> {
2404        let (future, shared) = CallbackFuture::new();
2405        complete_shared(&shared, Vec::new());
2406        Box::pin(future)
2407    }
2408}
2409
2410impl AdapterInterface for DawnAdapter {
2411    fn request_device(
2412        &self,
2413        desc: &wgpu::DeviceDescriptor<'_>,
2414    ) -> Pin<Box<dyn wgpu::custom::RequestDeviceFuture>> {
2415        let (future, shared) = CallbackFuture::new();
2416        let mut dawn_desc = DeviceDescriptor::new();
2417        dawn_desc.label = label_to_string(desc.label);
2418        if !desc.required_features.is_empty() {
2419            dawn_desc.required_features = Some(map_features_to_dawn(desc.required_features));
2420        }
2421        if desc.required_limits != wgpu::Limits::default() {
2422            dawn_desc.required_limits = Some(map_limits_to_dawn(&desc.required_limits));
2423        }
2424        let error_info = dawn_rs::UncapturedErrorCallbackInfo::new();
2425        error_info
2426            .callback
2427            .replace(Some(Box::new(|_devices, ty, message| {
2428                panic!("Uncaptured error {:?}: {}", ty, message);
2429            })));
2430        dawn_desc.uncaptured_error_callback_info = Some(error_info);
2431        let instance = self.inner.get_instance();
2432        let future_handle =
2433            self.inner
2434                .request_device(Some(&dawn_desc), move |status, device, message| {
2435                    if status == RequestDeviceStatus::Success {
2436                        let device = device.expect("wgpu-compat: missing device");
2437                        let queue = device.get_queue();
2438                        complete_shared(
2439                            &shared,
2440                            Ok((dispatch_device(device), dispatch_queue(queue))),
2441                        );
2442                    } else {
2443                        panic!("wgpu-compat: request_device failed {}", message);
2444                    }
2445                });
2446        let _ = instance.wait_any(
2447            Some(&mut [FutureWaitInfo {
2448                future: Some(future_handle),
2449                completed: None,
2450            }]),
2451            0,
2452        );
2453        Box::pin(future)
2454    }
2455
2456    fn is_surface_supported(&self, surface: &DispatchSurface) -> bool {
2457        surface.as_custom::<DawnSurface>().is_some()
2458    }
2459
2460    fn features(&self) -> wgpu::Features {
2461        let mut features = SupportedFeatures::new();
2462        self.inner.get_features(&mut features);
2463        map_features_to_wgpu(&features)
2464    }
2465
2466    fn limits(&self) -> wgpu::Limits {
2467        let mut limits = Limits::new();
2468        let _ = self.inner.get_limits(&mut limits);
2469        map_limits_to_wgpu(&limits)
2470    }
2471
2472    fn downlevel_capabilities(&self) -> wgpu::DownlevelCapabilities {
2473        wgpu::DownlevelCapabilities::default()
2474    }
2475
2476    fn get_info(&self) -> wgpu::AdapterInfo {
2477        let mut info = AdapterInfo::new();
2478        let _ = self.inner.get_info(&mut info);
2479        wgpu::AdapterInfo {
2480            name: info.description.clone().unwrap_or_default(),
2481            vendor: info.vendor_id.unwrap_or(0),
2482            device: info.device_id.unwrap_or(0),
2483            device_type: match info.adapter_type.unwrap_or(AdapterType::Unknown) {
2484                AdapterType::DiscreteGpu => wgpu::DeviceType::DiscreteGpu,
2485                AdapterType::IntegratedGpu => wgpu::DeviceType::IntegratedGpu,
2486                AdapterType::Cpu => wgpu::DeviceType::Cpu,
2487                AdapterType::Unknown => wgpu::DeviceType::Other,
2488            },
2489            backend: map_backend_type_to_wgpu(info.backend_type.unwrap_or(BackendType::Undefined)),
2490            driver: info.architecture.clone().unwrap_or_default(),
2491            driver_info: info.device.clone().unwrap_or_default(),
2492            device_pci_bus_id: String::new(),
2493            subgroup_min_size: wgpu::MINIMUM_SUBGROUP_MIN_SIZE,
2494            subgroup_max_size: wgpu::MAXIMUM_SUBGROUP_MAX_SIZE,
2495            transient_saves_memory: false,
2496        }
2497    }
2498
2499    fn get_texture_format_features(
2500        &self,
2501        _format: wgpu::TextureFormat,
2502    ) -> wgpu::TextureFormatFeatures {
2503        wgpu::TextureFormatFeatures {
2504            allowed_usages: wgpu::TextureUsages::empty(),
2505            flags: wgpu::TextureFormatFeatureFlags::empty(),
2506        }
2507    }
2508
2509    fn get_presentation_timestamp(&self) -> wgpu::PresentationTimestamp {
2510        wgpu::PresentationTimestamp::INVALID_TIMESTAMP
2511    }
2512}
2513
2514impl DeviceInterface for DawnDevice {
2515    fn features(&self) -> wgpu::Features {
2516        let adapter = self.inner.get_adapter();
2517        DawnAdapter { inner: adapter }.features()
2518    }
2519
2520    fn limits(&self) -> wgpu::Limits {
2521        let adapter = self.inner.get_adapter();
2522        DawnAdapter { inner: adapter }.limits()
2523    }
2524
2525    fn create_shader_module(
2526        &self,
2527        desc: wgpu::ShaderModuleDescriptor<'_>,
2528        _shader_bound_checks: wgpu::ShaderRuntimeChecks,
2529    ) -> DispatchShaderModule {
2530        let dawn_desc = map_shader_module_descriptor(desc);
2531        let module = self.inner.create_shader_module(&dawn_desc);
2532        dispatch_shader_module(module)
2533    }
2534
2535    unsafe fn create_shader_module_passthrough(
2536        &self,
2537        _desc: &wgpu::ShaderModuleDescriptorPassthrough<'_>,
2538    ) -> DispatchShaderModule {
2539        panic!("wgpu-compat: create_shader_module_passthrough not supported");
2540    }
2541
2542    fn create_bind_group_layout(
2543        &self,
2544        desc: &wgpu::BindGroupLayoutDescriptor<'_>,
2545    ) -> DispatchBindGroupLayout {
2546        let dawn_desc = map_bind_group_layout_descriptor(desc);
2547        let layout = self.inner.create_bind_group_layout(&dawn_desc);
2548        dispatch_bind_group_layout(layout)
2549    }
2550
2551    fn create_bind_group(&self, desc: &wgpu::BindGroupDescriptor<'_>) -> DispatchBindGroup {
2552        let dawn_desc = map_bind_group_descriptor(desc);
2553        let group = self.inner.create_bind_group(&dawn_desc);
2554        dispatch_bind_group(group)
2555    }
2556
2557    fn create_pipeline_layout(
2558        &self,
2559        desc: &wgpu::PipelineLayoutDescriptor<'_>,
2560    ) -> DispatchPipelineLayout {
2561        let dawn_desc = map_pipeline_layout_descriptor(desc);
2562        let layout = self.inner.create_pipeline_layout(&dawn_desc);
2563        dispatch_pipeline_layout(layout)
2564    }
2565
2566    fn create_render_pipeline(
2567        &self,
2568        desc: &wgpu::RenderPipelineDescriptor<'_>,
2569    ) -> DispatchRenderPipeline {
2570        let dawn_desc = map_render_pipeline_descriptor(desc);
2571        let pipeline = self.inner.create_render_pipeline(&dawn_desc);
2572        dispatch_render_pipeline(pipeline)
2573    }
2574
2575    fn create_mesh_pipeline(
2576        &self,
2577        _desc: &wgpu::MeshPipelineDescriptor<'_>,
2578    ) -> DispatchRenderPipeline {
2579        panic!("wgpu-compat: mesh pipelines not supported");
2580    }
2581
2582    fn create_compute_pipeline(
2583        &self,
2584        desc: &wgpu::ComputePipelineDescriptor<'_>,
2585    ) -> DispatchComputePipeline {
2586        let dawn_desc = map_compute_pipeline_descriptor(desc);
2587        let pipeline = self.inner.create_compute_pipeline(&dawn_desc);
2588        dispatch_compute_pipeline(pipeline)
2589    }
2590
2591    unsafe fn create_pipeline_cache(
2592        &self,
2593        _desc: &wgpu::PipelineCacheDescriptor<'_>,
2594    ) -> DispatchPipelineCache {
2595        dispatch_pipeline_cache()
2596    }
2597
2598    fn create_buffer(&self, desc: &wgpu::BufferDescriptor<'_>) -> DispatchBuffer {
2599        let dawn_desc = map_buffer_descriptor(desc);
2600        let buffer = self
2601            .inner
2602            .create_buffer(&dawn_desc)
2603            .expect("wgpu-compat: create_buffer returned null");
2604        dispatch_buffer(buffer)
2605    }
2606
2607    fn create_texture(&self, desc: &wgpu::TextureDescriptor<'_>) -> DispatchTexture {
2608        let dawn_desc = map_texture_descriptor(desc);
2609        let texture = self.inner.create_texture(&dawn_desc);
2610        dispatch_texture(texture)
2611    }
2612
2613    fn create_external_texture(
2614        &self,
2615        desc: &wgpu::ExternalTextureDescriptor<'_>,
2616        _planes: &[&wgpu::TextureView],
2617    ) -> DispatchExternalTexture {
2618        let mut dawn_desc = ExternalTextureDescriptor::new();
2619        dawn_desc.label = label_to_string(desc.label);
2620        let texture = self.inner.create_external_texture(&dawn_desc);
2621        dispatch_external_texture(texture)
2622    }
2623
2624    fn create_blas(
2625        &self,
2626        _desc: &wgpu::CreateBlasDescriptor<'_>,
2627        _sizes: wgpu::BlasGeometrySizeDescriptors,
2628    ) -> (Option<u64>, DispatchBlas) {
2629        (None, dispatch_blas())
2630    }
2631
2632    fn create_tlas(&self, _desc: &wgpu::CreateTlasDescriptor<'_>) -> DispatchTlas {
2633        dispatch_tlas()
2634    }
2635
2636    fn create_sampler(&self, desc: &wgpu::SamplerDescriptor<'_>) -> DispatchSampler {
2637        let dawn_desc = map_sampler_descriptor(desc);
2638        let sampler = self.inner.create_sampler(Some(&dawn_desc));
2639        dispatch_sampler(sampler)
2640    }
2641
2642    fn create_query_set(&self, desc: &wgpu::QuerySetDescriptor<'_>) -> DispatchQuerySet {
2643        let ty = match desc.ty {
2644            wgpu::QueryType::Occlusion => QueryType::Occlusion,
2645            wgpu::QueryType::Timestamp => QueryType::Timestamp,
2646            _ => panic!("wgpu-compat: query type not supported"),
2647        };
2648        let mut dawn_desc = QuerySetDescriptor::new();
2649        dawn_desc.label = label_to_string(desc.label);
2650        dawn_desc.r#type = Some(ty);
2651        dawn_desc.count = Some(desc.count);
2652        let set = self.inner.create_query_set(&dawn_desc);
2653        dispatch_query_set(set)
2654    }
2655
2656    fn create_command_encoder(
2657        &self,
2658        desc: &wgpu::CommandEncoderDescriptor<'_>,
2659    ) -> DispatchCommandEncoder {
2660        let dawn_desc = map_command_encoder_descriptor(desc);
2661        let encoder = self.inner.create_command_encoder(Some(&dawn_desc));
2662        dispatch_command_encoder(encoder)
2663    }
2664
2665    fn create_render_bundle_encoder(
2666        &self,
2667        desc: &wgpu::RenderBundleEncoderDescriptor<'_>,
2668    ) -> DispatchRenderBundleEncoder {
2669        let dawn_desc = map_render_bundle_encoder_descriptor(desc);
2670        let encoder = self.inner.create_render_bundle_encoder(&dawn_desc);
2671        dispatch_render_bundle_encoder(encoder)
2672    }
2673
2674    fn set_device_lost_callback(&self, _device_lost_callback: wgpu::custom::BoxDeviceLostCallback) {
2675    }
2676
2677    fn on_uncaptured_error(&self, _handler: Arc<dyn wgpu::UncapturedErrorHandler>) {}
2678
2679    fn push_error_scope(&self, filter: wgpu::ErrorFilter) -> u32 {
2680        let filter = match filter {
2681            wgpu::ErrorFilter::Validation => ErrorFilter::Validation,
2682            wgpu::ErrorFilter::OutOfMemory => ErrorFilter::OutOfMemory,
2683            wgpu::ErrorFilter::Internal => ErrorFilter::Internal,
2684        };
2685        self.inner.push_error_scope(filter);
2686        0
2687    }
2688
2689    fn pop_error_scope(&self, _index: u32) -> Pin<Box<dyn wgpu::custom::PopErrorScopeFuture>> {
2690        let (future, shared) = CallbackFuture::new();
2691        let _ = self.inner.pop_error_scope(move |status, ty, message| {
2692            if status == PopErrorScopeStatus::Success {
2693                if ty == ErrorType::NoError {
2694                    complete_shared(&shared, None);
2695                } else {
2696                    complete_shared(&shared, Some(map_uncaptured_error(ty, message)));
2697                }
2698            } else {
2699                complete_shared(
2700                    &shared,
2701                    Some(wgpu::Error::Internal {
2702                        source: Box::new(DawnError("pop_error_scope failed".to_string())),
2703                        description: "pop_error_scope failed".to_string(),
2704                    }),
2705                );
2706            }
2707        });
2708        Box::pin(future)
2709    }
2710
2711    unsafe fn start_graphics_debugger_capture(&self) {
2712        let _ = &self.inner;
2713    }
2714
2715    unsafe fn stop_graphics_debugger_capture(&self) {
2716        let _ = &self.inner;
2717    }
2718
2719    fn poll(&self, _poll_type: wgt::PollType<u64>) -> Result<wgpu::PollStatus, wgpu::PollError> {
2720        self.inner.tick();
2721        Ok(wgpu::PollStatus::QueueEmpty)
2722    }
2723
2724    fn get_internal_counters(&self) -> wgpu::InternalCounters {
2725        wgpu::InternalCounters::default()
2726    }
2727
2728    fn generate_allocator_report(&self) -> Option<wgpu::AllocatorReport> {
2729        None
2730    }
2731
2732    fn destroy(&self) {
2733        self.inner.destroy();
2734    }
2735}
2736
2737impl QueueInterface for DawnQueue {
2738    fn write_buffer(&self, buffer: &DispatchBuffer, offset: wgpu::BufferAddress, data: &[u8]) {
2739        let buffer = expect_buffer(buffer);
2740        let data_ptr = data.as_ptr().cast::<std::ffi::c_void>();
2741        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, data.len()) };
2742        self.inner.write_buffer(buffer, offset, data_slice);
2743    }
2744
2745    fn create_staging_buffer(&self, size: wgpu::BufferSize) -> Option<DispatchQueueWriteBuffer> {
2746        Some(dispatch_queue_write_buffer(vec![0; size.get() as usize]))
2747    }
2748
2749    fn validate_write_buffer(
2750        &self,
2751        _buffer: &DispatchBuffer,
2752        _offset: wgpu::BufferAddress,
2753        _size: wgpu::BufferSize,
2754    ) -> Option<()> {
2755        Some(())
2756    }
2757
2758    fn write_staging_buffer(
2759        &self,
2760        buffer: &DispatchBuffer,
2761        offset: wgpu::BufferAddress,
2762        staging_buffer: &DispatchQueueWriteBuffer,
2763    ) {
2764        let buffer = expect_buffer(buffer);
2765        let staging = staging_buffer
2766            .as_custom::<DawnQueueWriteBuffer>()
2767            .expect("wgpu-compat: queue write buffer not dawn");
2768        let data_ptr = staging.inner.as_ptr().cast::<std::ffi::c_void>();
2769        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, staging.inner.len()) };
2770        self.inner.write_buffer(buffer, offset, data_slice);
2771    }
2772
2773    fn write_texture(
2774        &self,
2775        texture: wgpu::TexelCopyTextureInfo<'_>,
2776        data: &[u8],
2777        mut data_layout: wgpu::TexelCopyBufferLayout,
2778        size: wgpu::Extent3d,
2779    ) {
2780        if data_layout.rows_per_image.is_none()
2781            && (size.height > 1 || size.depth_or_array_layers > 1)
2782        {
2783            data_layout.rows_per_image = Some(size.height.max(1));
2784        }
2785        let destination = map_texel_copy_texture_info(texture);
2786        let data_layout = map_texel_copy_buffer_layout(data_layout);
2787        let write_size = map_extent_3d(size);
2788        let data_ptr = data.as_ptr().cast::<std::ffi::c_void>();
2789        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, data.len()) };
2790        self.inner
2791            .write_texture(&destination, data_slice, &data_layout, &write_size);
2792    }
2793
2794    #[cfg(web)]
2795    #[allow(unexpected_cfgs)]
2796    fn copy_external_image_to_texture(
2797        &self,
2798        _source: &wgpu::CopyExternalImageSourceInfo,
2799        _dest: wgpu::CopyExternalImageDestInfo<&wgpu::Texture>,
2800        _size: wgpu::Extent3d,
2801    ) {
2802        unimplemented!();
2803    }
2804
2805    fn submit(&self, command_buffers: &mut dyn Iterator<Item = DispatchCommandBuffer>) -> u64 {
2806        let buffers = command_buffers
2807            .map(|buffer| expect_command_buffer(&buffer))
2808            .collect::<Vec<_>>();
2809        self.inner.submit(&buffers);
2810        0
2811    }
2812
2813    fn get_timestamp_period(&self) -> f32 {
2814        1.0
2815    }
2816
2817    fn on_submitted_work_done(&self, callback: wgpu::custom::BoxSubmittedWorkDoneCallback) {
2818        let mut callback = Some(callback);
2819        let _ = self.inner.on_submitted_work_done(move |status, _message| {
2820            let _ = status;
2821            if let Some(cb) = callback.take() {
2822                cb();
2823            }
2824        });
2825    }
2826
2827    fn compact_blas(&self, _blas: &DispatchBlas) -> (Option<u64>, DispatchBlas) {
2828        (None, dispatch_blas())
2829    }
2830}
2831
2832impl ShaderModuleInterface for DawnShaderModule {
2833    fn get_compilation_info(&self) -> Pin<Box<dyn wgpu::custom::ShaderCompilationInfoFuture>> {
2834        let (future, shared) = CallbackFuture::new();
2835        let _ = self.inner.get_compilation_info(move |status, info| {
2836            if status == CompilationInfoRequestStatus::Success {
2837                complete_shared(&shared, map_compilation_info(info));
2838            } else {
2839                complete_shared(&shared, wgpu::CompilationInfo { messages: vec![] });
2840            }
2841        });
2842        Box::pin(future)
2843    }
2844}
2845
2846impl BindGroupLayoutInterface for DawnBindGroupLayout {}
2847impl BindGroupInterface for DawnBindGroup {}
2848impl TextureViewInterface for DawnTextureView {}
2849impl SamplerInterface for DawnSampler {}
2850
2851impl BufferInterface for DawnBuffer {
2852    fn map_async(
2853        &self,
2854        mode: wgpu::MapMode,
2855        range: std::ops::Range<wgpu::BufferAddress>,
2856        callback: wgpu::custom::BufferMapCallback,
2857    ) {
2858        let mode = match mode {
2859            wgpu::MapMode::Read => MapMode::READ,
2860            wgpu::MapMode::Write => MapMode::WRITE,
2861        };
2862        let mut callback = Some(callback);
2863        let _ = self.inner.map_async(
2864            mode,
2865            range.start as usize,
2866            (range.end - range.start) as usize,
2867            move |status, message| {
2868                let result = match status {
2869                    MapAsyncStatus::Success => Ok(()),
2870                    _ => {
2871                        let _ = message;
2872                        Err(wgpu::BufferAsyncError)
2873                    }
2874                };
2875                if let Some(cb) = callback.take() {
2876                    cb(result);
2877                }
2878            },
2879        );
2880    }
2881
2882    fn get_mapped_range(
2883        &self,
2884        sub_range: std::ops::Range<wgpu::BufferAddress>,
2885    ) -> DispatchBufferMappedRange {
2886        let ptr = self.inner.get_mapped_range(
2887            sub_range.start as usize,
2888            (sub_range.end - sub_range.start) as usize,
2889        );
2890        dispatch_buffer_mapped_range(ptr.cast(), (sub_range.end - sub_range.start) as usize)
2891    }
2892
2893    fn unmap(&self) {
2894        self.inner.unmap();
2895    }
2896
2897    fn destroy(&self) {
2898        self.inner.destroy();
2899    }
2900}
2901
2902impl TextureInterface for DawnTexture {
2903    fn create_view(&self, desc: &wgpu::TextureViewDescriptor<'_>) -> DispatchTextureView {
2904        let desc = map_texture_view_descriptor(desc);
2905        let view = self.inner.create_view(Some(&desc));
2906        dispatch_texture_view(view)
2907    }
2908
2909    fn destroy(&self) {
2910        self.inner.destroy();
2911    }
2912}
2913
2914impl ExternalTextureInterface for DawnExternalTexture {
2915    fn destroy(&self) {
2916        self.inner.destroy();
2917    }
2918}
2919
2920impl BlasInterface for DawnBlas {
2921    fn prepare_compact_async(&self, _callback: wgpu::custom::BlasCompactCallback) {
2922        panic!("wgpu-compat: blas not supported");
2923    }
2924
2925    fn ready_for_compaction(&self) -> bool {
2926        false
2927    }
2928}
2929
2930impl TlasInterface for DawnTlas {}
2931impl QuerySetInterface for DawnQuerySet {}
2932impl PipelineLayoutInterface for DawnPipelineLayout {}
2933
2934impl RenderPipelineInterface for DawnRenderPipeline {
2935    fn get_bind_group_layout(&self, index: u32) -> DispatchBindGroupLayout {
2936        let layout = self.inner.get_bind_group_layout(index);
2937        dispatch_bind_group_layout(layout)
2938    }
2939}
2940
2941impl ComputePipelineInterface for DawnComputePipeline {
2942    fn get_bind_group_layout(&self, index: u32) -> DispatchBindGroupLayout {
2943        let layout = self.inner.get_bind_group_layout(index);
2944        dispatch_bind_group_layout(layout)
2945    }
2946}
2947
2948impl PipelineCacheInterface for DawnPipelineCache {
2949    fn get_data(&self) -> Option<Vec<u8>> {
2950        None
2951    }
2952}
2953
2954impl CommandEncoderInterface for DawnCommandEncoder {
2955    fn copy_buffer_to_buffer(
2956        &self,
2957        source: &DispatchBuffer,
2958        source_offset: wgpu::BufferAddress,
2959        destination: &DispatchBuffer,
2960        destination_offset: wgpu::BufferAddress,
2961        copy_size: Option<wgpu::BufferAddress>,
2962    ) {
2963        let source = expect_buffer(source);
2964        let destination = expect_buffer(destination);
2965        self.inner.copy_buffer_to_buffer(
2966            source,
2967            source_offset,
2968            destination,
2969            destination_offset,
2970            copy_size.unwrap_or(WHOLE_SIZE),
2971        );
2972    }
2973
2974    fn copy_buffer_to_texture(
2975        &self,
2976        source: wgpu::TexelCopyBufferInfo<'_>,
2977        destination: wgpu::TexelCopyTextureInfo<'_>,
2978        copy_size: wgpu::Extent3d,
2979    ) {
2980        let source = map_texel_copy_buffer_info(source);
2981        let dest = map_texel_copy_texture_info(destination);
2982        let size = map_extent_3d(copy_size);
2983        self.inner.copy_buffer_to_texture(&source, &dest, &size);
2984    }
2985
2986    fn copy_texture_to_buffer(
2987        &self,
2988        source: wgpu::TexelCopyTextureInfo<'_>,
2989        destination: wgpu::TexelCopyBufferInfo<'_>,
2990        copy_size: wgpu::Extent3d,
2991    ) {
2992        let source = map_texel_copy_texture_info(source);
2993        let dest = map_texel_copy_buffer_info(destination);
2994        let size = map_extent_3d(copy_size);
2995        self.inner.copy_texture_to_buffer(&source, &dest, &size);
2996    }
2997
2998    fn copy_texture_to_texture(
2999        &self,
3000        source: wgpu::TexelCopyTextureInfo<'_>,
3001        destination: wgpu::TexelCopyTextureInfo<'_>,
3002        copy_size: wgpu::Extent3d,
3003    ) {
3004        let source = map_texel_copy_texture_info(source);
3005        let dest = map_texel_copy_texture_info(destination);
3006        let size = map_extent_3d(copy_size);
3007        self.inner.copy_texture_to_texture(&source, &dest, &size);
3008    }
3009
3010    fn begin_compute_pass(&self, desc: &wgpu::ComputePassDescriptor<'_>) -> DispatchComputePass {
3011        let dawn_desc = map_compute_pass_descriptor(desc);
3012        let pass = self.inner.begin_compute_pass(Some(&dawn_desc));
3013        dispatch_compute_pass(pass)
3014    }
3015
3016    fn begin_render_pass(&self, desc: &wgpu::RenderPassDescriptor<'_>) -> DispatchRenderPass {
3017        let dawn_desc = map_render_pass_descriptor(desc);
3018        let pass = self.inner.begin_render_pass(&dawn_desc);
3019        dispatch_render_pass(pass)
3020    }
3021
3022    fn finish(&mut self) -> DispatchCommandBuffer {
3023        let buffer = self.inner.finish(None);
3024        dispatch_command_buffer(buffer)
3025    }
3026
3027    fn clear_texture(
3028        &self,
3029        texture: &DispatchTexture,
3030        subresource_range: &wgpu::ImageSubresourceRange,
3031    ) {
3032        let _ = texture;
3033        let _ = subresource_range;
3034    }
3035
3036    fn clear_buffer(
3037        &self,
3038        buffer: &DispatchBuffer,
3039        offset: wgpu::BufferAddress,
3040        size: Option<wgpu::BufferAddress>,
3041    ) {
3042        let buffer = expect_buffer(buffer);
3043        self.inner
3044            .clear_buffer(buffer, offset, size.unwrap_or(WHOLE_SIZE));
3045    }
3046
3047    fn insert_debug_marker(&self, label: &str) {
3048        self.inner.insert_debug_marker(label.to_string());
3049    }
3050
3051    fn push_debug_group(&self, label: &str) {
3052        self.inner.push_debug_group(label.to_string());
3053    }
3054
3055    fn pop_debug_group(&self) {
3056        self.inner.pop_debug_group();
3057    }
3058
3059    fn write_timestamp(&self, query_set: &DispatchQuerySet, query_index: u32) {
3060        let set = expect_query_set(query_set);
3061        self.inner.write_timestamp(set, query_index);
3062    }
3063
3064    fn resolve_query_set(
3065        &self,
3066        query_set: &DispatchQuerySet,
3067        first_query: u32,
3068        query_count: u32,
3069        destination: &DispatchBuffer,
3070        destination_offset: wgpu::BufferAddress,
3071    ) {
3072        let set = expect_query_set(query_set);
3073        let buffer = expect_buffer(destination);
3074        self.inner
3075            .resolve_query_set(set, first_query, query_count, buffer, destination_offset);
3076    }
3077
3078    fn mark_acceleration_structures_built<'a>(
3079        &self,
3080        _blas: &mut dyn Iterator<Item = &'a wgpu::Blas>,
3081        _tlas: &mut dyn Iterator<Item = &'a wgpu::Tlas>,
3082    ) {
3083        panic!("wgpu-compat: blas/tlas not supported");
3084    }
3085
3086    fn build_acceleration_structures<'a>(
3087        &self,
3088        _blas: &mut dyn Iterator<Item = &'a wgpu::BlasBuildEntry<'a>>,
3089        _tlas: &mut dyn Iterator<Item = &'a wgpu::Tlas>,
3090    ) {
3091        panic!("wgpu-compat: blas/tlas not supported");
3092    }
3093
3094    fn transition_resources<'a>(
3095        &mut self,
3096        _buffer_transitions: &mut dyn Iterator<Item = wgpu::BufferTransition<&'a DispatchBuffer>>,
3097        _texture_transitions: &mut dyn Iterator<
3098            Item = wgpu::TextureTransition<&'a DispatchTexture>,
3099        >,
3100    ) {
3101    }
3102}
3103
3104impl ComputePassInterface for DawnComputePass {
3105    fn set_pipeline(&mut self, pipeline: &DispatchComputePipeline) {
3106        let pipeline = expect_compute_pipeline(pipeline);
3107        self.inner.set_pipeline(pipeline);
3108    }
3109
3110    fn set_bind_group(
3111        &mut self,
3112        index: u32,
3113        bind_group: Option<&DispatchBindGroup>,
3114        offsets: &[wgpu::DynamicOffset],
3115    ) {
3116        let group = bind_group.map(expect_bind_group);
3117        self.inner.set_bind_group(index, group, offsets);
3118    }
3119
3120    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3121        let data = bytes_to_u32(data);
3122        let data_ptr = data.as_ptr().cast::<std::ffi::c_void>();
3123        let data_len = data.len() * std::mem::size_of::<u32>();
3124        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, data_len) };
3125        self.inner.set_immediates(offset, data_slice);
3126    }
3127
3128    fn insert_debug_marker(&mut self, label: &str) {
3129        self.inner.insert_debug_marker(label.to_string());
3130    }
3131
3132    fn push_debug_group(&mut self, group_label: &str) {
3133        self.inner.push_debug_group(group_label.to_string());
3134    }
3135
3136    fn pop_debug_group(&mut self) {
3137        self.inner.pop_debug_group();
3138    }
3139
3140    fn write_timestamp(&mut self, query_set: &DispatchQuerySet, query_index: u32) {
3141        let set = expect_query_set(query_set);
3142        self.inner.write_timestamp(set, query_index);
3143    }
3144
3145    fn begin_pipeline_statistics_query(
3146        &mut self,
3147        _query_set: &DispatchQuerySet,
3148        _query_index: u32,
3149    ) {
3150        panic!("wgpu-compat: pipeline statistics not supported");
3151    }
3152
3153    fn end_pipeline_statistics_query(&mut self) {
3154        panic!("wgpu-compat: pipeline statistics not supported");
3155    }
3156
3157    fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
3158        self.inner.dispatch_workgroups(x, y, z);
3159    }
3160
3161    fn dispatch_workgroups_indirect(
3162        &mut self,
3163        indirect_buffer: &DispatchBuffer,
3164        indirect_offset: wgpu::BufferAddress,
3165    ) {
3166        let buffer = expect_buffer(indirect_buffer);
3167        self.inner
3168            .dispatch_workgroups_indirect(buffer, indirect_offset);
3169    }
3170
3171    fn end(&mut self) {
3172        if !self.ended {
3173            self.inner.end();
3174            self.ended = true;
3175        }
3176    }
3177}
3178
3179impl Drop for DawnComputePass {
3180    fn drop(&mut self) {
3181        if !self.ended {
3182            self.inner.end();
3183            self.ended = true;
3184        }
3185    }
3186}
3187
3188impl RenderPassInterface for DawnRenderPass {
3189    fn set_pipeline(&mut self, pipeline: &DispatchRenderPipeline) {
3190        let pipeline = expect_render_pipeline(pipeline);
3191        self.inner.set_pipeline(pipeline);
3192    }
3193
3194    fn set_bind_group(
3195        &mut self,
3196        index: u32,
3197        bind_group: Option<&DispatchBindGroup>,
3198        offsets: &[wgpu::DynamicOffset],
3199    ) {
3200        let group = bind_group.map(expect_bind_group);
3201        self.inner.set_bind_group(index, group, offsets);
3202    }
3203
3204    fn set_index_buffer(
3205        &mut self,
3206        buffer: &DispatchBuffer,
3207        index_format: wgpu::IndexFormat,
3208        offset: wgpu::BufferAddress,
3209        size: Option<wgpu::BufferSize>,
3210    ) {
3211        let buffer = expect_buffer(buffer);
3212        let size = size.map(|v| v.get()).unwrap_or(WHOLE_SIZE);
3213        self.inner
3214            .set_index_buffer(buffer, map_index_format(index_format), offset, size);
3215    }
3216
3217    fn set_vertex_buffer(
3218        &mut self,
3219        slot: u32,
3220        buffer: &DispatchBuffer,
3221        offset: wgpu::BufferAddress,
3222        size: Option<wgpu::BufferSize>,
3223    ) {
3224        let buffer = expect_buffer(buffer);
3225        let size = size.map(|v| v.get()).unwrap_or(WHOLE_SIZE);
3226        self.inner
3227            .set_vertex_buffer(slot, Some(buffer), offset, size);
3228    }
3229
3230    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3231        let data = bytes_to_u32(data);
3232        let data_ptr = data.as_ptr().cast::<std::ffi::c_void>();
3233        let data_len = data.len() * std::mem::size_of::<u32>();
3234        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, data_len) };
3235        self.inner.set_immediates(offset, data_slice);
3236    }
3237
3238    fn set_blend_constant(&mut self, color: wgpu::Color) {
3239        let color = map_color(color);
3240        self.inner.set_blend_constant(&color);
3241    }
3242
3243    fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
3244        self.inner.set_scissor_rect(x, y, width, height);
3245    }
3246
3247    fn set_viewport(
3248        &mut self,
3249        x: f32,
3250        y: f32,
3251        width: f32,
3252        height: f32,
3253        min_depth: f32,
3254        max_depth: f32,
3255    ) {
3256        self.inner
3257            .set_viewport(x, y, width, height, min_depth, max_depth);
3258    }
3259
3260    fn set_stencil_reference(&mut self, reference: u32) {
3261        self.inner.set_stencil_reference(reference);
3262    }
3263
3264    fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
3265        self.inner.draw(
3266            vertices.end - vertices.start,
3267            instances.end - instances.start,
3268            vertices.start,
3269            instances.start,
3270        );
3271    }
3272
3273    fn draw_indexed(
3274        &mut self,
3275        indices: std::ops::Range<u32>,
3276        base_vertex: i32,
3277        instances: std::ops::Range<u32>,
3278    ) {
3279        self.inner.draw_indexed(
3280            indices.end - indices.start,
3281            instances.end - instances.start,
3282            indices.start,
3283            base_vertex,
3284            instances.start,
3285        );
3286    }
3287
3288    fn draw_mesh_tasks(&mut self, _group_count_x: u32, _group_count_y: u32, _group_count_z: u32) {
3289        panic!("wgpu-compat: mesh tasks not supported");
3290    }
3291
3292    fn draw_indirect(
3293        &mut self,
3294        indirect_buffer: &DispatchBuffer,
3295        indirect_offset: wgpu::BufferAddress,
3296    ) {
3297        let buffer = expect_buffer(indirect_buffer);
3298        self.inner.draw_indirect(buffer, indirect_offset);
3299    }
3300
3301    fn draw_indexed_indirect(
3302        &mut self,
3303        indirect_buffer: &DispatchBuffer,
3304        indirect_offset: wgpu::BufferAddress,
3305    ) {
3306        let buffer = expect_buffer(indirect_buffer);
3307        self.inner.draw_indexed_indirect(buffer, indirect_offset);
3308    }
3309
3310    fn draw_mesh_tasks_indirect(
3311        &mut self,
3312        _indirect_buffer: &DispatchBuffer,
3313        _indirect_offset: wgpu::BufferAddress,
3314    ) {
3315        panic!("wgpu-compat: mesh tasks not supported");
3316    }
3317
3318    fn multi_draw_indirect(
3319        &mut self,
3320        indirect_buffer: &DispatchBuffer,
3321        indirect_offset: wgpu::BufferAddress,
3322        count: u32,
3323    ) {
3324        let buffer = expect_buffer(indirect_buffer);
3325        self.inner
3326            .multi_draw_indirect(buffer, indirect_offset, count, None, 0);
3327    }
3328
3329    fn multi_draw_indexed_indirect(
3330        &mut self,
3331        indirect_buffer: &DispatchBuffer,
3332        indirect_offset: wgpu::BufferAddress,
3333        count: u32,
3334    ) {
3335        let buffer = expect_buffer(indirect_buffer);
3336        self.inner
3337            .multi_draw_indexed_indirect(buffer, indirect_offset, count, None, 0);
3338    }
3339
3340    fn multi_draw_indirect_count(
3341        &mut self,
3342        _indirect_buffer: &DispatchBuffer,
3343        _indirect_offset: wgpu::BufferAddress,
3344        _count_buffer: &DispatchBuffer,
3345        _count_buffer_offset: wgpu::BufferAddress,
3346        _max_count: u32,
3347    ) {
3348        panic!("wgpu-compat: multi_draw_indirect_count not supported");
3349    }
3350
3351    fn multi_draw_mesh_tasks_indirect(
3352        &mut self,
3353        _indirect_buffer: &DispatchBuffer,
3354        _indirect_offset: wgpu::BufferAddress,
3355        _count: u32,
3356    ) {
3357        panic!("wgpu-compat: mesh tasks not supported");
3358    }
3359
3360    fn multi_draw_indexed_indirect_count(
3361        &mut self,
3362        _indirect_buffer: &DispatchBuffer,
3363        _indirect_offset: wgpu::BufferAddress,
3364        _count_buffer: &DispatchBuffer,
3365        _count_buffer_offset: wgpu::BufferAddress,
3366        _max_count: u32,
3367    ) {
3368        panic!("wgpu-compat: multi_draw_indexed_indirect_count not supported");
3369    }
3370
3371    fn multi_draw_mesh_tasks_indirect_count(
3372        &mut self,
3373        _indirect_buffer: &DispatchBuffer,
3374        _indirect_offset: wgpu::BufferAddress,
3375        _count_buffer: &DispatchBuffer,
3376        _count_buffer_offset: wgpu::BufferAddress,
3377        _max_count: u32,
3378    ) {
3379        panic!("wgpu-compat: mesh tasks not supported");
3380    }
3381
3382    fn insert_debug_marker(&mut self, label: &str) {
3383        self.inner.insert_debug_marker(label.to_string());
3384    }
3385
3386    fn push_debug_group(&mut self, group_label: &str) {
3387        self.inner.push_debug_group(group_label.to_string());
3388    }
3389
3390    fn pop_debug_group(&mut self) {
3391        self.inner.pop_debug_group();
3392    }
3393
3394    fn write_timestamp(&mut self, query_set: &DispatchQuerySet, query_index: u32) {
3395        let set = expect_query_set(query_set);
3396        self.inner.write_timestamp(set, query_index);
3397    }
3398
3399    fn begin_occlusion_query(&mut self, query_index: u32) {
3400        self.inner.begin_occlusion_query(query_index);
3401    }
3402
3403    fn end_occlusion_query(&mut self) {
3404        self.inner.end_occlusion_query();
3405    }
3406
3407    fn begin_pipeline_statistics_query(
3408        &mut self,
3409        _query_set: &DispatchQuerySet,
3410        _query_index: u32,
3411    ) {
3412        panic!("wgpu-compat: pipeline statistics not supported");
3413    }
3414
3415    fn end_pipeline_statistics_query(&mut self) {
3416        panic!("wgpu-compat: pipeline statistics not supported");
3417    }
3418
3419    fn execute_bundles(&mut self, render_bundles: &mut dyn Iterator<Item = &DispatchRenderBundle>) {
3420        let bundles = render_bundles.map(expect_render_bundle).collect::<Vec<_>>();
3421        self.inner.execute_bundles(&bundles);
3422    }
3423
3424    fn end(&mut self) {
3425        if !self.ended {
3426            self.inner.end();
3427            self.ended = true;
3428        }
3429    }
3430}
3431
3432impl Drop for DawnRenderPass {
3433    fn drop(&mut self) {
3434        if !self.ended {
3435            self.inner.end();
3436            self.ended = true;
3437        }
3438    }
3439}
3440
3441impl RenderBundleEncoderInterface for DawnRenderBundleEncoder {
3442    fn set_pipeline(&mut self, pipeline: &DispatchRenderPipeline) {
3443        let pipeline = expect_render_pipeline(pipeline);
3444        self.inner.set_pipeline(pipeline);
3445    }
3446
3447    fn set_bind_group(
3448        &mut self,
3449        index: u32,
3450        bind_group: Option<&DispatchBindGroup>,
3451        offsets: &[wgpu::DynamicOffset],
3452    ) {
3453        let group = bind_group.map(expect_bind_group);
3454        self.inner.set_bind_group(index, group, offsets);
3455    }
3456
3457    fn set_index_buffer(
3458        &mut self,
3459        buffer: &DispatchBuffer,
3460        index_format: wgpu::IndexFormat,
3461        offset: wgpu::BufferAddress,
3462        size: Option<wgpu::BufferSize>,
3463    ) {
3464        let buffer = expect_buffer(buffer);
3465        let size = size.map(|v| v.get()).unwrap_or(WHOLE_SIZE);
3466        self.inner
3467            .set_index_buffer(buffer, map_index_format(index_format), offset, size);
3468    }
3469
3470    fn set_vertex_buffer(
3471        &mut self,
3472        slot: u32,
3473        buffer: &DispatchBuffer,
3474        offset: wgpu::BufferAddress,
3475        size: Option<wgpu::BufferSize>,
3476    ) {
3477        let buffer = expect_buffer(buffer);
3478        let size = size.map(|v| v.get()).unwrap_or(WHOLE_SIZE);
3479        self.inner
3480            .set_vertex_buffer(slot, Some(buffer), offset, size);
3481    }
3482
3483    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3484        let data = bytes_to_u32(data);
3485        let data_ptr = data.as_ptr().cast::<std::ffi::c_void>();
3486        let data_len = data.len() * std::mem::size_of::<u32>();
3487        let data_slice = unsafe { std::slice::from_raw_parts(data_ptr, data_len) };
3488        self.inner.set_immediates(offset, data_slice);
3489    }
3490
3491    fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
3492        self.inner.draw(
3493            vertices.end - vertices.start,
3494            instances.end - instances.start,
3495            vertices.start,
3496            instances.start,
3497        );
3498    }
3499
3500    fn draw_indexed(
3501        &mut self,
3502        indices: std::ops::Range<u32>,
3503        base_vertex: i32,
3504        instances: std::ops::Range<u32>,
3505    ) {
3506        self.inner.draw_indexed(
3507            indices.end - indices.start,
3508            instances.end - instances.start,
3509            indices.start,
3510            base_vertex,
3511            instances.start,
3512        );
3513    }
3514
3515    fn draw_indirect(
3516        &mut self,
3517        indirect_buffer: &DispatchBuffer,
3518        indirect_offset: wgpu::BufferAddress,
3519    ) {
3520        let buffer = expect_buffer(indirect_buffer);
3521        self.inner.draw_indirect(buffer, indirect_offset);
3522    }
3523
3524    fn draw_indexed_indirect(
3525        &mut self,
3526        indirect_buffer: &DispatchBuffer,
3527        indirect_offset: wgpu::BufferAddress,
3528    ) {
3529        let buffer = expect_buffer(indirect_buffer);
3530        self.inner.draw_indexed_indirect(buffer, indirect_offset);
3531    }
3532
3533    fn finish(self, desc: &wgpu::RenderBundleDescriptor<'_>) -> DispatchRenderBundle {
3534        let mut dawn_desc = RenderBundleDescriptor::new();
3535        dawn_desc.label = label_to_string(desc.label);
3536        let bundle = self.inner.finish(Some(&dawn_desc));
3537        dispatch_render_bundle(bundle)
3538    }
3539}
3540
3541impl CommandBufferInterface for DawnCommandBuffer {}
3542impl RenderBundleInterface for DawnRenderBundle {}
3543
3544impl SurfaceInterface for DawnSurface {
3545    fn get_capabilities(&self, adapter: &DispatchAdapter) -> wgpu::SurfaceCapabilities {
3546        let adapter = expect_adapter(adapter);
3547        let mut caps = SurfaceCapabilities::new();
3548        let _ = self.inner.get_capabilities(adapter, &mut caps);
3549        map_surface_capabilities(caps)
3550    }
3551
3552    fn configure(&self, device: &DispatchDevice, config: &wgpu::SurfaceConfiguration) {
3553        let mut config = map_surface_configuration(config);
3554        config.device = Some(expect_device(device));
3555        self.inner.configure(&config);
3556    }
3557
3558    fn get_current_texture(
3559        &self,
3560    ) -> (
3561        Option<DispatchTexture>,
3562        wgpu::SurfaceStatus,
3563        DispatchSurfaceOutputDetail,
3564    ) {
3565        let mut surface_texture = SurfaceTexture::new();
3566        self.inner.get_current_texture(&mut surface_texture);
3567        let status = match surface_texture
3568            .status
3569            .unwrap_or(SurfaceGetCurrentTextureStatus::Error)
3570        {
3571            SurfaceGetCurrentTextureStatus::SuccessOptimal => wgpu::SurfaceStatus::Good,
3572            SurfaceGetCurrentTextureStatus::SuccessSuboptimal => wgpu::SurfaceStatus::Suboptimal,
3573            SurfaceGetCurrentTextureStatus::Timeout => wgpu::SurfaceStatus::Timeout,
3574            SurfaceGetCurrentTextureStatus::Outdated => wgpu::SurfaceStatus::Outdated,
3575            SurfaceGetCurrentTextureStatus::Lost => wgpu::SurfaceStatus::Lost,
3576            SurfaceGetCurrentTextureStatus::Error => wgpu::SurfaceStatus::Unknown,
3577        };
3578        (
3579            surface_texture.texture.map(dispatch_texture),
3580            status,
3581            dispatch_surface_output_detail(self.inner.clone()),
3582        )
3583    }
3584}
3585
3586impl SurfaceOutputDetailInterface for DawnSurfaceOutputDetail {
3587    fn present(&self) {
3588        let _ = self.surface.present();
3589    }
3590
3591    fn texture_discard(&self) {
3592        // Dawn does not expose an explicit surface texture discard API.
3593    }
3594}
3595
3596impl QueueWriteBufferInterface for DawnQueueWriteBuffer {
3597    fn slice(&self) -> &[u8] {
3598        &self.inner
3599    }
3600
3601    fn slice_mut(&mut self) -> &mut [u8] {
3602        &mut self.inner
3603    }
3604}
3605
3606impl BufferMappedRangeInterface for DawnBufferMappedRange {
3607    fn slice(&self) -> &[u8] {
3608        if self.data.is_null() || self.size == 0 {
3609            return &[];
3610        }
3611        unsafe { std::slice::from_raw_parts(self.data, self.size) }
3612    }
3613
3614    fn slice_mut(&mut self) -> &mut [u8] {
3615        if self.data.is_null() || self.size == 0 {
3616            return &mut [];
3617        }
3618        unsafe { std::slice::from_raw_parts_mut(self.data, self.size) }
3619    }
3620
3621    #[cfg(web)]
3622    #[allow(unexpected_cfgs)]
3623    fn as_uint8array(&self) -> &js_sys::Uint8Array {
3624        unimplemented!();
3625    }
3626}
3627
3628pub fn to_wgpu_instance(instance: Instance) -> wgpu::Instance {
3629    wgpu::Instance::from_custom(DawnInstance { inner: instance })
3630}
3631
3632pub fn from_wgpu_instance(instance: &wgpu::Instance) -> Result<Instance, WgpuCompatError> {
3633    instance
3634        .as_custom::<DawnInstance>()
3635        .map(|i| i.inner.clone())
3636        .ok_or(WgpuCompatError::NotDawnBackend)
3637}
3638
3639pub fn to_wgpu_adapter(adapter: Adapter) -> wgpu::Adapter {
3640    wgpu::Adapter::from_custom(DawnAdapter { inner: adapter })
3641}
3642
3643pub fn from_wgpu_adapter(adapter: &wgpu::Adapter) -> Result<Adapter, WgpuCompatError> {
3644    adapter
3645        .as_custom::<DawnAdapter>()
3646        .map(|a| a.inner.clone())
3647        .ok_or(WgpuCompatError::NotDawnBackend)
3648}
3649
3650pub fn to_wgpu_device(device: Device) -> wgpu::Device {
3651    wgpu::Device::from_custom(DawnDevice { inner: device })
3652}
3653
3654pub fn from_wgpu_device(device: &wgpu::Device) -> Result<Device, WgpuCompatError> {
3655    device
3656        .as_custom::<DawnDevice>()
3657        .map(|d| d.inner.clone())
3658        .ok_or(WgpuCompatError::NotDawnBackend)
3659}
3660
3661pub fn to_wgpu_queue(queue: Queue) -> wgpu::Queue {
3662    wgpu::Queue::from_custom(DawnQueue { inner: queue })
3663}
3664
3665pub fn from_wgpu_queue(queue: &wgpu::Queue) -> Result<Queue, WgpuCompatError> {
3666    queue
3667        .as_custom::<DawnQueue>()
3668        .map(|q| q.inner.clone())
3669        .ok_or(WgpuCompatError::NotDawnBackend)
3670}
3671
3672pub fn from_wgpu_surface(surface: &wgpu::Surface) -> Result<Surface, WgpuCompatError> {
3673    surface
3674        .as_custom::<DawnSurface>()
3675        .map(|s| s.inner.clone())
3676        .ok_or(WgpuCompatError::NotDawnBackend)
3677}
3678
3679pub fn from_wgpu_buffer(buffer: &wgpu::Buffer) -> Result<Buffer, WgpuCompatError> {
3680    buffer
3681        .as_custom::<DawnBuffer>()
3682        .map(|b| b.inner.clone())
3683        .ok_or(WgpuCompatError::NotDawnBackend)
3684}
3685
3686pub fn to_wgpu_texture(texture: Texture, desc: &wgpu::TextureDescriptor<'_>) -> wgpu::Texture {
3687    wgpu::Texture::from_custom(DawnTexture { inner: texture }, desc)
3688}
3689
3690pub fn from_wgpu_texture(texture: &wgpu::Texture) -> Result<Texture, WgpuCompatError> {
3691    texture
3692        .as_custom::<DawnTexture>()
3693        .map(|t| t.inner.clone())
3694        .ok_or(WgpuCompatError::NotDawnBackend)
3695}
3696
3697pub fn from_wgpu_texture_view(view: &wgpu::TextureView) -> Result<TextureView, WgpuCompatError> {
3698    view.as_custom::<DawnTextureView>()
3699        .map(|v| v.inner.clone())
3700        .ok_or(WgpuCompatError::NotDawnBackend)
3701}
3702
3703pub fn from_wgpu_sampler(sampler: &wgpu::Sampler) -> Result<Sampler, WgpuCompatError> {
3704    sampler
3705        .as_custom::<DawnSampler>()
3706        .map(|s| s.inner.clone())
3707        .ok_or(WgpuCompatError::NotDawnBackend)
3708}
3709
3710pub fn from_wgpu_bind_group_layout(
3711    layout: &wgpu::BindGroupLayout,
3712) -> Result<BindGroupLayout, WgpuCompatError> {
3713    layout
3714        .as_custom::<DawnBindGroupLayout>()
3715        .map(|l| l.inner.clone())
3716        .ok_or(WgpuCompatError::NotDawnBackend)
3717}
3718
3719pub fn from_wgpu_bind_group(group: &wgpu::BindGroup) -> Result<BindGroup, WgpuCompatError> {
3720    group
3721        .as_custom::<DawnBindGroup>()
3722        .map(|g| g.inner.clone())
3723        .ok_or(WgpuCompatError::NotDawnBackend)
3724}
3725
3726pub fn from_wgpu_pipeline_layout(
3727    layout: &wgpu::PipelineLayout,
3728) -> Result<PipelineLayout, WgpuCompatError> {
3729    layout
3730        .as_custom::<DawnPipelineLayout>()
3731        .map(|l| l.inner.clone())
3732        .ok_or(WgpuCompatError::NotDawnBackend)
3733}
3734
3735pub fn from_wgpu_render_pipeline(
3736    pipeline: &wgpu::RenderPipeline,
3737) -> Result<RenderPipeline, WgpuCompatError> {
3738    pipeline
3739        .as_custom::<DawnRenderPipeline>()
3740        .map(|p| p.inner.clone())
3741        .ok_or(WgpuCompatError::NotDawnBackend)
3742}
3743
3744pub fn from_wgpu_compute_pipeline(
3745    pipeline: &wgpu::ComputePipeline,
3746) -> Result<ComputePipeline, WgpuCompatError> {
3747    pipeline
3748        .as_custom::<DawnComputePipeline>()
3749        .map(|p| p.inner.clone())
3750        .ok_or(WgpuCompatError::NotDawnBackend)
3751}
3752
3753pub fn from_wgpu_shader_module(
3754    module: &wgpu::ShaderModule,
3755) -> Result<ShaderModule, WgpuCompatError> {
3756    module
3757        .as_custom::<DawnShaderModule>()
3758        .map(|m| m.inner.clone())
3759        .ok_or(WgpuCompatError::NotDawnBackend)
3760}
3761
3762pub fn from_wgpu_command_encoder(
3763    encoder: &wgpu::CommandEncoder,
3764) -> Result<CommandEncoder, WgpuCompatError> {
3765    encoder
3766        .as_custom::<DawnCommandEncoder>()
3767        .map(|e| e.inner.clone())
3768        .ok_or(WgpuCompatError::NotDawnBackend)
3769}
3770
3771pub fn from_wgpu_command_buffer(
3772    buffer: &wgpu::CommandBuffer,
3773) -> Result<CommandBuffer, WgpuCompatError> {
3774    buffer
3775        .as_custom::<DawnCommandBuffer>()
3776        .map(|b| b.inner.clone())
3777        .ok_or(WgpuCompatError::NotDawnBackend)
3778}
3779
3780pub fn from_wgpu_render_bundle(
3781    bundle: &wgpu::RenderBundle,
3782) -> Result<RenderBundle, WgpuCompatError> {
3783    bundle
3784        .as_custom::<DawnRenderBundle>()
3785        .map(|b| b.inner.clone())
3786        .ok_or(WgpuCompatError::NotDawnBackend)
3787}
3788
3789pub fn from_wgpu_query_set(query_set: &wgpu::QuerySet) -> Result<QuerySet, WgpuCompatError> {
3790    query_set
3791        .as_custom::<DawnQuerySet>()
3792        .map(|q| q.inner.clone())
3793        .ok_or(WgpuCompatError::NotDawnBackend)
3794}