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
176impl<D: Device + DynResource> DynDevice for D {
177    unsafe fn create_buffer(
178        &self,
179        desc: &BufferDescriptor,
180    ) -> Result<Box<dyn DynBuffer>, DeviceError> {
181        unsafe { D::create_buffer(self, desc) }.map(|b| -> Box<dyn DynBuffer> { Box::new(b) })
182    }
183
184    unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>) {
185        unsafe { D::destroy_buffer(self, buffer.unbox()) };
186    }
187    unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer) {
188        let buffer = buffer.expect_downcast_ref();
189        unsafe { D::add_raw_buffer(self, buffer) };
190    }
191
192    unsafe fn map_buffer(
193        &self,
194        buffer: &dyn DynBuffer,
195        range: MemoryRange,
196    ) -> Result<BufferMapping, DeviceError> {
197        let buffer = buffer.expect_downcast_ref();
198        unsafe { D::map_buffer(self, buffer, range) }
199    }
200
201    unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer) {
202        let buffer = buffer.expect_downcast_ref();
203        unsafe { D::unmap_buffer(self, buffer) }
204    }
205
206    unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
207        let buffer = buffer.expect_downcast_ref();
208        unsafe { D::flush_mapped_ranges(self, buffer, ranges.iter().cloned()) }
209    }
210
211    unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
212        let buffer = buffer.expect_downcast_ref();
213        unsafe { D::invalidate_mapped_ranges(self, buffer, ranges.iter().cloned()) }
214    }
215
216    unsafe fn create_texture(
217        &self,
218        desc: &TextureDescriptor,
219    ) -> Result<Box<dyn DynTexture>, DeviceError> {
220        unsafe { D::create_texture(self, desc) }.map(|b| {
221            let boxed_texture: Box<<D::A as Api>::Texture> = Box::new(b);
222            let boxed_texture: Box<dyn DynTexture> = boxed_texture;
223            boxed_texture
224        })
225    }
226
227    unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>) {
228        unsafe { D::destroy_texture(self, texture.unbox()) };
229    }
230
231    unsafe fn add_raw_texture(&self, texture: &dyn DynTexture) {
232        let texture = texture.expect_downcast_ref();
233        unsafe { D::add_raw_texture(self, texture) };
234    }
235
236    unsafe fn create_texture_view(
237        &self,
238        texture: &dyn DynTexture,
239        desc: &TextureViewDescriptor,
240    ) -> Result<Box<dyn DynTextureView>, DeviceError> {
241        let texture = texture.expect_downcast_ref();
242        unsafe { D::create_texture_view(self, texture, desc) }.map(|b| {
243            let boxed_texture_view: Box<<D::A as Api>::TextureView> = Box::new(b);
244            let boxed_texture_view: Box<dyn DynTextureView> = boxed_texture_view;
245            boxed_texture_view
246        })
247    }
248
249    unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>) {
250        unsafe { D::destroy_texture_view(self, view.unbox()) };
251    }
252
253    unsafe fn create_sampler(
254        &self,
255        desc: &SamplerDescriptor,
256    ) -> Result<Box<dyn DynSampler>, DeviceError> {
257        unsafe { D::create_sampler(self, desc) }.map(|b| {
258            let boxed_sampler: Box<<D::A as Api>::Sampler> = Box::new(b);
259            let boxed_sampler: Box<dyn DynSampler> = boxed_sampler;
260            boxed_sampler
261        })
262    }
263
264    unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>) {
265        unsafe { D::destroy_sampler(self, sampler.unbox()) };
266    }
267
268    unsafe fn create_command_encoder(
269        &self,
270        desc: &CommandEncoderDescriptor<'_, dyn DynQueue>,
271    ) -> Result<Box<dyn DynCommandEncoder>, DeviceError> {
272        let desc = CommandEncoderDescriptor {
273            label: desc.label,
274            queue: desc.queue.expect_downcast_ref(),
275        };
276        unsafe { D::create_command_encoder(self, &desc) }
277            .map(|b| -> Box<dyn DynCommandEncoder> { Box::new(b) })
278    }
279
280    unsafe fn create_bind_group_layout(
281        &self,
282        desc: &BindGroupLayoutDescriptor,
283    ) -> Result<Box<dyn DynBindGroupLayout>, DeviceError> {
284        unsafe { D::create_bind_group_layout(self, desc) }
285            .map(|b| -> Box<dyn DynBindGroupLayout> { Box::new(b) })
286    }
287
288    unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>) {
289        unsafe { D::destroy_bind_group_layout(self, bg_layout.unbox()) };
290    }
291
292    unsafe fn create_pipeline_layout(
293        &self,
294        desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
295    ) -> Result<Box<dyn DynPipelineLayout>, DeviceError> {
296        let bind_group_layouts: Vec<_> = desc
297            .bind_group_layouts
298            .iter()
299            .map(|bgl| bgl.expect_downcast_ref())
300            .collect();
301        let desc = PipelineLayoutDescriptor {
302            label: desc.label,
303            bind_group_layouts: &bind_group_layouts,
304            push_constant_ranges: desc.push_constant_ranges,
305            flags: desc.flags,
306        };
307
308        unsafe { D::create_pipeline_layout(self, &desc) }
309            .map(|b| -> Box<dyn DynPipelineLayout> { Box::new(b) })
310    }
311
312    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>) {
313        unsafe { D::destroy_pipeline_layout(self, pipeline_layout.unbox()) };
314    }
315
316    unsafe fn create_bind_group(
317        &self,
318        desc: &BindGroupDescriptor<
319            dyn DynBindGroupLayout,
320            dyn DynBuffer,
321            dyn DynSampler,
322            dyn DynTextureView,
323            dyn DynAccelerationStructure,
324        >,
325    ) -> Result<Box<dyn DynBindGroup>, DeviceError> {
326        let buffers: Vec<_> = desc
327            .buffers
328            .iter()
329            .map(|b| b.clone().expect_downcast())
330            .collect();
331        let samplers: Vec<_> = desc
332            .samplers
333            .iter()
334            .map(|s| s.expect_downcast_ref())
335            .collect();
336        let textures: Vec<_> = desc
337            .textures
338            .iter()
339            .map(|t| t.clone().expect_downcast())
340            .collect();
341        let acceleration_structures: Vec<_> = desc
342            .acceleration_structures
343            .iter()
344            .map(|a| a.expect_downcast_ref())
345            .collect();
346
347        let desc = BindGroupDescriptor {
348            label: desc.label.to_owned(),
349            layout: desc.layout.expect_downcast_ref(),
350            buffers: &buffers,
351            samplers: &samplers,
352            textures: &textures,
353            entries: desc.entries,
354            acceleration_structures: &acceleration_structures,
355        };
356
357        unsafe { D::create_bind_group(self, &desc) }
358            .map(|b| -> Box<dyn DynBindGroup> { Box::new(b) })
359    }
360
361    unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>) {
362        unsafe { D::destroy_bind_group(self, group.unbox()) };
363    }
364
365    unsafe fn create_shader_module(
366        &self,
367        desc: &ShaderModuleDescriptor,
368        shader: ShaderInput,
369    ) -> Result<Box<dyn DynShaderModule>, ShaderError> {
370        unsafe { D::create_shader_module(self, desc, shader) }
371            .map(|b| -> Box<dyn DynShaderModule> { Box::new(b) })
372    }
373
374    unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>) {
375        unsafe { D::destroy_shader_module(self, module.unbox()) };
376    }
377
378    unsafe fn create_render_pipeline(
379        &self,
380        desc: &RenderPipelineDescriptor<
381            dyn DynPipelineLayout,
382            dyn DynShaderModule,
383            dyn DynPipelineCache,
384        >,
385    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
386        let desc = RenderPipelineDescriptor {
387            label: desc.label,
388            layout: desc.layout.expect_downcast_ref(),
389            vertex_buffers: desc.vertex_buffers,
390            vertex_stage: desc.vertex_stage.clone().expect_downcast(),
391            primitive: desc.primitive,
392            depth_stencil: desc.depth_stencil.clone(),
393            multisample: desc.multisample,
394            fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
395            color_targets: desc.color_targets,
396            multiview: desc.multiview,
397            cache: desc.cache.map(|c| c.expect_downcast_ref()),
398        };
399
400        unsafe { D::create_render_pipeline(self, &desc) }
401            .map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
402    }
403
404    unsafe fn create_mesh_pipeline(
405        &self,
406        desc: &MeshPipelineDescriptor<
407            dyn DynPipelineLayout,
408            dyn DynShaderModule,
409            dyn DynPipelineCache,
410        >,
411    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
412        let desc = MeshPipelineDescriptor {
413            label: desc.label,
414            layout: desc.layout.expect_downcast_ref(),
415            task_stage: desc.task_stage.clone().map(|f| f.expect_downcast()),
416            mesh_stage: desc.mesh_stage.clone().expect_downcast(),
417            primitive: desc.primitive,
418            depth_stencil: desc.depth_stencil.clone(),
419            multisample: desc.multisample,
420            fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
421            color_targets: desc.color_targets,
422            multiview: desc.multiview,
423            cache: desc.cache.map(|c| c.expect_downcast_ref()),
424        };
425
426        unsafe { D::create_mesh_pipeline(self, &desc) }
427            .map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
428    }
429
430    unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
431        unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
432    }
433
434    unsafe fn create_compute_pipeline(
435        &self,
436        desc: &ComputePipelineDescriptor<
437            dyn DynPipelineLayout,
438            dyn DynShaderModule,
439            dyn DynPipelineCache,
440        >,
441    ) -> Result<Box<dyn DynComputePipeline>, PipelineError> {
442        let desc = ComputePipelineDescriptor {
443            label: desc.label,
444            layout: desc.layout.expect_downcast_ref(),
445            stage: desc.stage.clone().expect_downcast(),
446            cache: desc.cache.as_ref().map(|c| c.expect_downcast_ref()),
447        };
448
449        unsafe { D::create_compute_pipeline(self, &desc) }
450            .map(|b| -> Box<dyn DynComputePipeline> { Box::new(b) })
451    }
452
453    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>) {
454        unsafe { D::destroy_compute_pipeline(self, pipeline.unbox()) };
455    }
456
457    unsafe fn create_pipeline_cache(
458        &self,
459        desc: &PipelineCacheDescriptor<'_>,
460    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError> {
461        unsafe { D::create_pipeline_cache(self, desc) }
462            .map(|b| -> Box<dyn DynPipelineCache> { Box::new(b) })
463    }
464
465    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
466        D::pipeline_cache_validation_key(self)
467    }
468
469    unsafe fn destroy_pipeline_cache(&self, pipeline_cache: Box<dyn DynPipelineCache>) {
470        unsafe { D::destroy_pipeline_cache(self, pipeline_cache.unbox()) };
471    }
472
473    unsafe fn create_query_set(
474        &self,
475        desc: &wgt::QuerySetDescriptor<Label>,
476    ) -> Result<Box<dyn DynQuerySet>, DeviceError> {
477        unsafe { D::create_query_set(self, desc) }.map(|b| -> Box<dyn DynQuerySet> { Box::new(b) })
478    }
479
480    unsafe fn destroy_query_set(&self, query_set: Box<dyn DynQuerySet>) {
481        unsafe { D::destroy_query_set(self, query_set.unbox()) };
482    }
483
484    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError> {
485        unsafe { D::create_fence(self) }.map(|b| -> Box<dyn DynFence> { Box::new(b) })
486    }
487
488    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>) {
489        unsafe { D::destroy_fence(self, fence.unbox()) };
490    }
491
492    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError> {
493        let fence = fence.expect_downcast_ref();
494        unsafe { D::get_fence_value(self, fence) }
495    }
496
497    unsafe fn wait(
498        &self,
499        fence: &dyn DynFence,
500        value: FenceValue,
501        timeout_ms: u32,
502    ) -> Result<bool, DeviceError> {
503        let fence = fence.expect_downcast_ref();
504        unsafe { D::wait(self, fence, value, timeout_ms) }
505    }
506
507    unsafe fn start_graphics_debugger_capture(&self) -> bool {
508        unsafe { D::start_graphics_debugger_capture(self) }
509    }
510
511    unsafe fn stop_graphics_debugger_capture(&self) {
512        unsafe { D::stop_graphics_debugger_capture(self) }
513    }
514
515    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>> {
516        let cache = cache.expect_downcast_ref();
517        unsafe { D::pipeline_cache_get_data(self, cache) }
518    }
519
520    unsafe fn create_acceleration_structure(
521        &self,
522        desc: &AccelerationStructureDescriptor,
523    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError> {
524        unsafe { D::create_acceleration_structure(self, desc) }
525            .map(|b| -> Box<dyn DynAccelerationStructure> { Box::new(b) })
526    }
527
528    unsafe fn get_acceleration_structure_build_sizes(
529        &self,
530        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
531    ) -> AccelerationStructureBuildSizes {
532        let entries = desc.entries.expect_downcast();
533        let desc = GetAccelerationStructureBuildSizesDescriptor {
534            entries: &entries,
535            flags: desc.flags,
536        };
537        unsafe { D::get_acceleration_structure_build_sizes(self, &desc) }
538    }
539
540    unsafe fn get_acceleration_structure_device_address(
541        &self,
542        acceleration_structure: &dyn DynAccelerationStructure,
543    ) -> wgt::BufferAddress {
544        let acceleration_structure = acceleration_structure.expect_downcast_ref();
545        unsafe { D::get_acceleration_structure_device_address(self, acceleration_structure) }
546    }
547
548    unsafe fn destroy_acceleration_structure(
549        &self,
550        acceleration_structure: Box<dyn DynAccelerationStructure>,
551    ) {
552        unsafe { D::destroy_acceleration_structure(self, acceleration_structure.unbox()) }
553    }
554
555    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
556        D::tlas_instance_to_bytes(self, instance)
557    }
558
559    fn get_internal_counters(&self) -> wgt::HalCounters {
560        D::get_internal_counters(self)
561    }
562
563    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
564        D::generate_allocator_report(self)
565    }
566}