wgpu_hal/dynamic/
device.rs

1use alloc::{borrow::ToOwned as _, boxed::Box, vec::Vec};
2
3use crate::{
4    AccelerationStructureBuildSizes, AccelerationStructureDescriptor, Api, BindGroupDescriptor,
5    BindGroupLayoutDescriptor, BufferDescriptor, BufferMapping, CommandEncoderDescriptor,
6    ComputePipelineDescriptor, Device, DeviceError, FenceValue,
7    GetAccelerationStructureBuildSizesDescriptor, Label, MemoryRange, MeshPipelineDescriptor,
8    PipelineCacheDescriptor, PipelineCacheError, PipelineError, PipelineLayoutDescriptor,
9    RenderPipelineDescriptor, SamplerDescriptor, ShaderError, ShaderInput, ShaderModuleDescriptor,
10    TextureDescriptor, TextureViewDescriptor, TlasInstance,
11};
12
13use super::{
14    DynAccelerationStructure, DynBindGroup, DynBindGroupLayout, DynBuffer, DynCommandEncoder,
15    DynComputePipeline, DynFence, DynPipelineCache, DynPipelineLayout, DynQuerySet, DynQueue,
16    DynRenderPipeline, DynResource, DynResourceExt as _, DynSampler, DynShaderModule, DynTexture,
17    DynTextureView,
18};
19
20pub trait DynDevice: DynResource {
21    unsafe fn create_buffer(
22        &self,
23        desc: &BufferDescriptor,
24    ) -> Result<Box<dyn DynBuffer>, DeviceError>;
25
26    unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>);
27    unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer);
28
29    unsafe fn map_buffer(
30        &self,
31        buffer: &dyn DynBuffer,
32        range: MemoryRange,
33    ) -> Result<BufferMapping, DeviceError>;
34
35    unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer);
36
37    unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]);
38    unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]);
39
40    unsafe fn create_texture(
41        &self,
42        desc: &TextureDescriptor,
43    ) -> Result<Box<dyn DynTexture>, DeviceError>;
44    unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>);
45    unsafe fn add_raw_texture(&self, texture: &dyn DynTexture);
46
47    unsafe fn create_texture_view(
48        &self,
49        texture: &dyn DynTexture,
50        desc: &TextureViewDescriptor,
51    ) -> Result<Box<dyn DynTextureView>, DeviceError>;
52    unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>);
53    unsafe fn create_sampler(
54        &self,
55        desc: &SamplerDescriptor,
56    ) -> Result<Box<dyn DynSampler>, DeviceError>;
57    unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>);
58
59    unsafe fn create_command_encoder(
60        &self,
61        desc: &CommandEncoderDescriptor<dyn DynQueue>,
62    ) -> Result<Box<dyn DynCommandEncoder>, DeviceError>;
63
64    unsafe fn create_bind_group_layout(
65        &self,
66        desc: &BindGroupLayoutDescriptor,
67    ) -> Result<Box<dyn DynBindGroupLayout>, DeviceError>;
68    unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>);
69
70    unsafe fn create_pipeline_layout(
71        &self,
72        desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
73    ) -> Result<Box<dyn DynPipelineLayout>, DeviceError>;
74    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>);
75
76    unsafe fn create_bind_group(
77        &self,
78        desc: &BindGroupDescriptor<
79            dyn DynBindGroupLayout,
80            dyn DynBuffer,
81            dyn DynSampler,
82            dyn DynTextureView,
83            dyn DynAccelerationStructure,
84        >,
85    ) -> Result<Box<dyn DynBindGroup>, DeviceError>;
86    unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>);
87
88    unsafe fn create_shader_module(
89        &self,
90        desc: &ShaderModuleDescriptor,
91        shader: ShaderInput,
92    ) -> Result<Box<dyn DynShaderModule>, ShaderError>;
93    unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>);
94
95    unsafe fn create_render_pipeline(
96        &self,
97        desc: &RenderPipelineDescriptor<
98            dyn DynPipelineLayout,
99            dyn DynShaderModule,
100            dyn DynPipelineCache,
101        >,
102    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
103    unsafe fn create_mesh_pipeline(
104        &self,
105        desc: &MeshPipelineDescriptor<
106            dyn DynPipelineLayout,
107            dyn DynShaderModule,
108            dyn DynPipelineCache,
109        >,
110    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
111    unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>);
112
113    unsafe fn create_compute_pipeline(
114        &self,
115        desc: &ComputePipelineDescriptor<
116            dyn DynPipelineLayout,
117            dyn DynShaderModule,
118            dyn DynPipelineCache,
119        >,
120    ) -> Result<Box<dyn DynComputePipeline>, PipelineError>;
121    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>);
122
123    unsafe fn create_pipeline_cache(
124        &self,
125        desc: &PipelineCacheDescriptor<'_>,
126    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError>;
127    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
128        None
129    }
130    unsafe fn destroy_pipeline_cache(&self, cache: Box<dyn DynPipelineCache>);
131
132    unsafe fn create_query_set(
133        &self,
134        desc: &wgt::QuerySetDescriptor<Label>,
135    ) -> Result<Box<dyn DynQuerySet>, DeviceError>;
136    unsafe fn destroy_query_set(&self, set: Box<dyn DynQuerySet>);
137
138    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError>;
139    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>);
140    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError>;
141
142    unsafe fn wait(
143        &self,
144        fence: &dyn DynFence,
145        value: FenceValue,
146        timeout_ms: u32,
147    ) -> Result<bool, DeviceError>;
148
149    unsafe fn start_graphics_debugger_capture(&self) -> bool;
150    unsafe fn stop_graphics_debugger_capture(&self);
151
152    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>>;
153
154    unsafe fn create_acceleration_structure(
155        &self,
156        desc: &AccelerationStructureDescriptor,
157    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError>;
158    unsafe fn get_acceleration_structure_build_sizes(
159        &self,
160        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
161    ) -> AccelerationStructureBuildSizes;
162    unsafe fn get_acceleration_structure_device_address(
163        &self,
164        acceleration_structure: &dyn DynAccelerationStructure,
165    ) -> wgt::BufferAddress;
166    unsafe fn destroy_acceleration_structure(
167        &self,
168        acceleration_structure: Box<dyn DynAccelerationStructure>,
169    );
170    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8>;
171
172    fn get_internal_counters(&self) -> wgt::HalCounters;
173    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport>;
174
175    fn check_if_oom(&self) -> Result<(), DeviceError>;
176}
177
178impl<D: Device + DynResource> DynDevice for D {
179    unsafe fn create_buffer(
180        &self,
181        desc: &BufferDescriptor,
182    ) -> Result<Box<dyn DynBuffer>, DeviceError> {
183        unsafe { D::create_buffer(self, desc) }.map(|b| -> Box<dyn DynBuffer> { Box::new(b) })
184    }
185
186    unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>) {
187        unsafe { D::destroy_buffer(self, buffer.unbox()) };
188    }
189    unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer) {
190        let buffer = buffer.expect_downcast_ref();
191        unsafe { D::add_raw_buffer(self, buffer) };
192    }
193
194    unsafe fn map_buffer(
195        &self,
196        buffer: &dyn DynBuffer,
197        range: MemoryRange,
198    ) -> Result<BufferMapping, DeviceError> {
199        let buffer = buffer.expect_downcast_ref();
200        unsafe { D::map_buffer(self, buffer, range) }
201    }
202
203    unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer) {
204        let buffer = buffer.expect_downcast_ref();
205        unsafe { D::unmap_buffer(self, buffer) }
206    }
207
208    unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
209        let buffer = buffer.expect_downcast_ref();
210        unsafe { D::flush_mapped_ranges(self, buffer, ranges.iter().cloned()) }
211    }
212
213    unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
214        let buffer = buffer.expect_downcast_ref();
215        unsafe { D::invalidate_mapped_ranges(self, buffer, ranges.iter().cloned()) }
216    }
217
218    unsafe fn create_texture(
219        &self,
220        desc: &TextureDescriptor,
221    ) -> Result<Box<dyn DynTexture>, DeviceError> {
222        unsafe { D::create_texture(self, desc) }.map(|b| {
223            let boxed_texture: Box<<D::A as Api>::Texture> = Box::new(b);
224            let boxed_texture: Box<dyn DynTexture> = boxed_texture;
225            boxed_texture
226        })
227    }
228
229    unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>) {
230        unsafe { D::destroy_texture(self, texture.unbox()) };
231    }
232
233    unsafe fn add_raw_texture(&self, texture: &dyn DynTexture) {
234        let texture = texture.expect_downcast_ref();
235        unsafe { D::add_raw_texture(self, texture) };
236    }
237
238    unsafe fn create_texture_view(
239        &self,
240        texture: &dyn DynTexture,
241        desc: &TextureViewDescriptor,
242    ) -> Result<Box<dyn DynTextureView>, DeviceError> {
243        let texture = texture.expect_downcast_ref();
244        unsafe { D::create_texture_view(self, texture, desc) }.map(|b| {
245            let boxed_texture_view: Box<<D::A as Api>::TextureView> = Box::new(b);
246            let boxed_texture_view: Box<dyn DynTextureView> = boxed_texture_view;
247            boxed_texture_view
248        })
249    }
250
251    unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>) {
252        unsafe { D::destroy_texture_view(self, view.unbox()) };
253    }
254
255    unsafe fn create_sampler(
256        &self,
257        desc: &SamplerDescriptor,
258    ) -> Result<Box<dyn DynSampler>, DeviceError> {
259        unsafe { D::create_sampler(self, desc) }.map(|b| {
260            let boxed_sampler: Box<<D::A as Api>::Sampler> = Box::new(b);
261            let boxed_sampler: Box<dyn DynSampler> = boxed_sampler;
262            boxed_sampler
263        })
264    }
265
266    unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>) {
267        unsafe { D::destroy_sampler(self, sampler.unbox()) };
268    }
269
270    unsafe fn create_command_encoder(
271        &self,
272        desc: &CommandEncoderDescriptor<'_, dyn DynQueue>,
273    ) -> Result<Box<dyn DynCommandEncoder>, DeviceError> {
274        let desc = CommandEncoderDescriptor {
275            label: desc.label,
276            queue: desc.queue.expect_downcast_ref(),
277        };
278        unsafe { D::create_command_encoder(self, &desc) }
279            .map(|b| -> Box<dyn DynCommandEncoder> { Box::new(b) })
280    }
281
282    unsafe fn create_bind_group_layout(
283        &self,
284        desc: &BindGroupLayoutDescriptor,
285    ) -> Result<Box<dyn DynBindGroupLayout>, DeviceError> {
286        unsafe { D::create_bind_group_layout(self, desc) }
287            .map(|b| -> Box<dyn DynBindGroupLayout> { Box::new(b) })
288    }
289
290    unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>) {
291        unsafe { D::destroy_bind_group_layout(self, bg_layout.unbox()) };
292    }
293
294    unsafe fn create_pipeline_layout(
295        &self,
296        desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
297    ) -> Result<Box<dyn DynPipelineLayout>, DeviceError> {
298        let bind_group_layouts: Vec<_> = desc
299            .bind_group_layouts
300            .iter()
301            .map(|bgl| bgl.expect_downcast_ref())
302            .collect();
303        let desc = PipelineLayoutDescriptor {
304            label: desc.label,
305            bind_group_layouts: &bind_group_layouts,
306            push_constant_ranges: desc.push_constant_ranges,
307            flags: desc.flags,
308        };
309
310        unsafe { D::create_pipeline_layout(self, &desc) }
311            .map(|b| -> Box<dyn DynPipelineLayout> { Box::new(b) })
312    }
313
314    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>) {
315        unsafe { D::destroy_pipeline_layout(self, pipeline_layout.unbox()) };
316    }
317
318    unsafe fn create_bind_group(
319        &self,
320        desc: &BindGroupDescriptor<
321            dyn DynBindGroupLayout,
322            dyn DynBuffer,
323            dyn DynSampler,
324            dyn DynTextureView,
325            dyn DynAccelerationStructure,
326        >,
327    ) -> Result<Box<dyn DynBindGroup>, DeviceError> {
328        let buffers: Vec<_> = desc
329            .buffers
330            .iter()
331            .map(|b| b.clone().expect_downcast())
332            .collect();
333        let samplers: Vec<_> = desc
334            .samplers
335            .iter()
336            .map(|s| s.expect_downcast_ref())
337            .collect();
338        let textures: Vec<_> = desc
339            .textures
340            .iter()
341            .map(|t| t.clone().expect_downcast())
342            .collect();
343        let acceleration_structures: Vec<_> = desc
344            .acceleration_structures
345            .iter()
346            .map(|a| a.expect_downcast_ref())
347            .collect();
348
349        let desc = BindGroupDescriptor {
350            label: desc.label.to_owned(),
351            layout: desc.layout.expect_downcast_ref(),
352            buffers: &buffers,
353            samplers: &samplers,
354            textures: &textures,
355            entries: desc.entries,
356            acceleration_structures: &acceleration_structures,
357        };
358
359        unsafe { D::create_bind_group(self, &desc) }
360            .map(|b| -> Box<dyn DynBindGroup> { Box::new(b) })
361    }
362
363    unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>) {
364        unsafe { D::destroy_bind_group(self, group.unbox()) };
365    }
366
367    unsafe fn create_shader_module(
368        &self,
369        desc: &ShaderModuleDescriptor,
370        shader: ShaderInput,
371    ) -> Result<Box<dyn DynShaderModule>, ShaderError> {
372        unsafe { D::create_shader_module(self, desc, shader) }
373            .map(|b| -> Box<dyn DynShaderModule> { Box::new(b) })
374    }
375
376    unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>) {
377        unsafe { D::destroy_shader_module(self, module.unbox()) };
378    }
379
380    unsafe fn create_render_pipeline(
381        &self,
382        desc: &RenderPipelineDescriptor<
383            dyn DynPipelineLayout,
384            dyn DynShaderModule,
385            dyn DynPipelineCache,
386        >,
387    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
388        let desc = RenderPipelineDescriptor {
389            label: desc.label,
390            layout: desc.layout.expect_downcast_ref(),
391            vertex_buffers: desc.vertex_buffers,
392            vertex_stage: desc.vertex_stage.clone().expect_downcast(),
393            primitive: desc.primitive,
394            depth_stencil: desc.depth_stencil.clone(),
395            multisample: desc.multisample,
396            fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
397            color_targets: desc.color_targets,
398            multiview: desc.multiview,
399            cache: desc.cache.map(|c| c.expect_downcast_ref()),
400        };
401
402        unsafe { D::create_render_pipeline(self, &desc) }
403            .map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
404    }
405
406    unsafe fn create_mesh_pipeline(
407        &self,
408        desc: &MeshPipelineDescriptor<
409            dyn DynPipelineLayout,
410            dyn DynShaderModule,
411            dyn DynPipelineCache,
412        >,
413    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
414        let desc = MeshPipelineDescriptor {
415            label: desc.label,
416            layout: desc.layout.expect_downcast_ref(),
417            task_stage: desc.task_stage.clone().map(|f| f.expect_downcast()),
418            mesh_stage: desc.mesh_stage.clone().expect_downcast(),
419            primitive: desc.primitive,
420            depth_stencil: desc.depth_stencil.clone(),
421            multisample: desc.multisample,
422            fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
423            color_targets: desc.color_targets,
424            multiview: desc.multiview,
425            cache: desc.cache.map(|c| c.expect_downcast_ref()),
426        };
427
428        unsafe { D::create_mesh_pipeline(self, &desc) }
429            .map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
430    }
431
432    unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
433        unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
434    }
435
436    unsafe fn create_compute_pipeline(
437        &self,
438        desc: &ComputePipelineDescriptor<
439            dyn DynPipelineLayout,
440            dyn DynShaderModule,
441            dyn DynPipelineCache,
442        >,
443    ) -> Result<Box<dyn DynComputePipeline>, PipelineError> {
444        let desc = ComputePipelineDescriptor {
445            label: desc.label,
446            layout: desc.layout.expect_downcast_ref(),
447            stage: desc.stage.clone().expect_downcast(),
448            cache: desc.cache.as_ref().map(|c| c.expect_downcast_ref()),
449        };
450
451        unsafe { D::create_compute_pipeline(self, &desc) }
452            .map(|b| -> Box<dyn DynComputePipeline> { Box::new(b) })
453    }
454
455    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>) {
456        unsafe { D::destroy_compute_pipeline(self, pipeline.unbox()) };
457    }
458
459    unsafe fn create_pipeline_cache(
460        &self,
461        desc: &PipelineCacheDescriptor<'_>,
462    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError> {
463        unsafe { D::create_pipeline_cache(self, desc) }
464            .map(|b| -> Box<dyn DynPipelineCache> { Box::new(b) })
465    }
466
467    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
468        D::pipeline_cache_validation_key(self)
469    }
470
471    unsafe fn destroy_pipeline_cache(&self, pipeline_cache: Box<dyn DynPipelineCache>) {
472        unsafe { D::destroy_pipeline_cache(self, pipeline_cache.unbox()) };
473    }
474
475    unsafe fn create_query_set(
476        &self,
477        desc: &wgt::QuerySetDescriptor<Label>,
478    ) -> Result<Box<dyn DynQuerySet>, DeviceError> {
479        unsafe { D::create_query_set(self, desc) }.map(|b| -> Box<dyn DynQuerySet> { Box::new(b) })
480    }
481
482    unsafe fn destroy_query_set(&self, query_set: Box<dyn DynQuerySet>) {
483        unsafe { D::destroy_query_set(self, query_set.unbox()) };
484    }
485
486    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError> {
487        unsafe { D::create_fence(self) }.map(|b| -> Box<dyn DynFence> { Box::new(b) })
488    }
489
490    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>) {
491        unsafe { D::destroy_fence(self, fence.unbox()) };
492    }
493
494    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError> {
495        let fence = fence.expect_downcast_ref();
496        unsafe { D::get_fence_value(self, fence) }
497    }
498
499    unsafe fn wait(
500        &self,
501        fence: &dyn DynFence,
502        value: FenceValue,
503        timeout_ms: u32,
504    ) -> Result<bool, DeviceError> {
505        let fence = fence.expect_downcast_ref();
506        unsafe { D::wait(self, fence, value, timeout_ms) }
507    }
508
509    unsafe fn start_graphics_debugger_capture(&self) -> bool {
510        unsafe { D::start_graphics_debugger_capture(self) }
511    }
512
513    unsafe fn stop_graphics_debugger_capture(&self) {
514        unsafe { D::stop_graphics_debugger_capture(self) }
515    }
516
517    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>> {
518        let cache = cache.expect_downcast_ref();
519        unsafe { D::pipeline_cache_get_data(self, cache) }
520    }
521
522    unsafe fn create_acceleration_structure(
523        &self,
524        desc: &AccelerationStructureDescriptor,
525    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError> {
526        unsafe { D::create_acceleration_structure(self, desc) }
527            .map(|b| -> Box<dyn DynAccelerationStructure> { Box::new(b) })
528    }
529
530    unsafe fn get_acceleration_structure_build_sizes(
531        &self,
532        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
533    ) -> AccelerationStructureBuildSizes {
534        let entries = desc.entries.expect_downcast();
535        let desc = GetAccelerationStructureBuildSizesDescriptor {
536            entries: &entries,
537            flags: desc.flags,
538        };
539        unsafe { D::get_acceleration_structure_build_sizes(self, &desc) }
540    }
541
542    unsafe fn get_acceleration_structure_device_address(
543        &self,
544        acceleration_structure: &dyn DynAccelerationStructure,
545    ) -> wgt::BufferAddress {
546        let acceleration_structure = acceleration_structure.expect_downcast_ref();
547        unsafe { D::get_acceleration_structure_device_address(self, acceleration_structure) }
548    }
549
550    unsafe fn destroy_acceleration_structure(
551        &self,
552        acceleration_structure: Box<dyn DynAccelerationStructure>,
553    ) {
554        unsafe { D::destroy_acceleration_structure(self, acceleration_structure.unbox()) }
555    }
556
557    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
558        D::tlas_instance_to_bytes(self, instance)
559    }
560
561    fn get_internal_counters(&self) -> wgt::HalCounters {
562        D::get_internal_counters(self)
563    }
564
565    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
566        D::generate_allocator_report(self)
567    }
568
569    fn check_if_oom(&self) -> Result<(), DeviceError> {
570        D::check_if_oom(self)
571    }
572}