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}