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, PipelineCacheDescriptor,
8    PipelineCacheError, PipelineError, PipelineLayoutDescriptor, RenderPipelineDescriptor,
9    SamplerDescriptor, ShaderError, ShaderInput, ShaderModuleDescriptor, TextureDescriptor,
10    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 destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>);
104
105    unsafe fn create_compute_pipeline(
106        &self,
107        desc: &ComputePipelineDescriptor<
108            dyn DynPipelineLayout,
109            dyn DynShaderModule,
110            dyn DynPipelineCache,
111        >,
112    ) -> Result<Box<dyn DynComputePipeline>, PipelineError>;
113    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>);
114
115    unsafe fn create_pipeline_cache(
116        &self,
117        desc: &PipelineCacheDescriptor<'_>,
118    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError>;
119    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
120        None
121    }
122    unsafe fn destroy_pipeline_cache(&self, cache: Box<dyn DynPipelineCache>);
123
124    unsafe fn create_query_set(
125        &self,
126        desc: &wgt::QuerySetDescriptor<Label>,
127    ) -> Result<Box<dyn DynQuerySet>, DeviceError>;
128    unsafe fn destroy_query_set(&self, set: Box<dyn DynQuerySet>);
129
130    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError>;
131    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>);
132    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError>;
133
134    unsafe fn wait(
135        &self,
136        fence: &dyn DynFence,
137        value: FenceValue,
138        timeout_ms: u32,
139    ) -> Result<bool, DeviceError>;
140
141    unsafe fn start_graphics_debugger_capture(&self) -> bool;
142    unsafe fn stop_graphics_debugger_capture(&self);
143
144    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>>;
145
146    unsafe fn create_acceleration_structure(
147        &self,
148        desc: &AccelerationStructureDescriptor,
149    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError>;
150    unsafe fn get_acceleration_structure_build_sizes(
151        &self,
152        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
153    ) -> AccelerationStructureBuildSizes;
154    unsafe fn get_acceleration_structure_device_address(
155        &self,
156        acceleration_structure: &dyn DynAccelerationStructure,
157    ) -> wgt::BufferAddress;
158    unsafe fn destroy_acceleration_structure(
159        &self,
160        acceleration_structure: Box<dyn DynAccelerationStructure>,
161    );
162    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8>;
163
164    fn get_internal_counters(&self) -> wgt::HalCounters;
165    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport>;
166
167    fn check_if_oom(&self) -> Result<(), DeviceError>;
168}
169
170impl<D: Device + DynResource> DynDevice for D {
171    unsafe fn create_buffer(
172        &self,
173        desc: &BufferDescriptor,
174    ) -> Result<Box<dyn DynBuffer>, DeviceError> {
175        unsafe { D::create_buffer(self, desc) }.map(|b| -> Box<dyn DynBuffer> { Box::new(b) })
176    }
177
178    unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>) {
179        unsafe { D::destroy_buffer(self, buffer.unbox()) };
180    }
181    unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer) {
182        let buffer = buffer.expect_downcast_ref();
183        unsafe { D::add_raw_buffer(self, buffer) };
184    }
185
186    unsafe fn map_buffer(
187        &self,
188        buffer: &dyn DynBuffer,
189        range: MemoryRange,
190    ) -> Result<BufferMapping, DeviceError> {
191        let buffer = buffer.expect_downcast_ref();
192        unsafe { D::map_buffer(self, buffer, range) }
193    }
194
195    unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer) {
196        let buffer = buffer.expect_downcast_ref();
197        unsafe { D::unmap_buffer(self, buffer) }
198    }
199
200    unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
201        let buffer = buffer.expect_downcast_ref();
202        unsafe { D::flush_mapped_ranges(self, buffer, ranges.iter().cloned()) }
203    }
204
205    unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
206        let buffer = buffer.expect_downcast_ref();
207        unsafe { D::invalidate_mapped_ranges(self, buffer, ranges.iter().cloned()) }
208    }
209
210    unsafe fn create_texture(
211        &self,
212        desc: &TextureDescriptor,
213    ) -> Result<Box<dyn DynTexture>, DeviceError> {
214        unsafe { D::create_texture(self, desc) }.map(|b| {
215            let boxed_texture: Box<<D::A as Api>::Texture> = Box::new(b);
216            let boxed_texture: Box<dyn DynTexture> = boxed_texture;
217            boxed_texture
218        })
219    }
220
221    unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>) {
222        unsafe { D::destroy_texture(self, texture.unbox()) };
223    }
224
225    unsafe fn add_raw_texture(&self, texture: &dyn DynTexture) {
226        let texture = texture.expect_downcast_ref();
227        unsafe { D::add_raw_texture(self, texture) };
228    }
229
230    unsafe fn create_texture_view(
231        &self,
232        texture: &dyn DynTexture,
233        desc: &TextureViewDescriptor,
234    ) -> Result<Box<dyn DynTextureView>, DeviceError> {
235        let texture = texture.expect_downcast_ref();
236        unsafe { D::create_texture_view(self, texture, desc) }.map(|b| {
237            let boxed_texture_view: Box<<D::A as Api>::TextureView> = Box::new(b);
238            let boxed_texture_view: Box<dyn DynTextureView> = boxed_texture_view;
239            boxed_texture_view
240        })
241    }
242
243    unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>) {
244        unsafe { D::destroy_texture_view(self, view.unbox()) };
245    }
246
247    unsafe fn create_sampler(
248        &self,
249        desc: &SamplerDescriptor,
250    ) -> Result<Box<dyn DynSampler>, DeviceError> {
251        unsafe { D::create_sampler(self, desc) }.map(|b| {
252            let boxed_sampler: Box<<D::A as Api>::Sampler> = Box::new(b);
253            let boxed_sampler: Box<dyn DynSampler> = boxed_sampler;
254            boxed_sampler
255        })
256    }
257
258    unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>) {
259        unsafe { D::destroy_sampler(self, sampler.unbox()) };
260    }
261
262    unsafe fn create_command_encoder(
263        &self,
264        desc: &CommandEncoderDescriptor<'_, dyn DynQueue>,
265    ) -> Result<Box<dyn DynCommandEncoder>, DeviceError> {
266        let desc = CommandEncoderDescriptor {
267            label: desc.label,
268            queue: desc.queue.expect_downcast_ref(),
269        };
270        unsafe { D::create_command_encoder(self, &desc) }
271            .map(|b| -> Box<dyn DynCommandEncoder> { Box::new(b) })
272    }
273
274    unsafe fn create_bind_group_layout(
275        &self,
276        desc: &BindGroupLayoutDescriptor,
277    ) -> Result<Box<dyn DynBindGroupLayout>, DeviceError> {
278        unsafe { D::create_bind_group_layout(self, desc) }
279            .map(|b| -> Box<dyn DynBindGroupLayout> { Box::new(b) })
280    }
281
282    unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>) {
283        unsafe { D::destroy_bind_group_layout(self, bg_layout.unbox()) };
284    }
285
286    unsafe fn create_pipeline_layout(
287        &self,
288        desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
289    ) -> Result<Box<dyn DynPipelineLayout>, DeviceError> {
290        let bind_group_layouts: Vec<_> = desc
291            .bind_group_layouts
292            .iter()
293            .map(|bgl| bgl.expect_downcast_ref())
294            .collect();
295        let desc = PipelineLayoutDescriptor {
296            label: desc.label,
297            bind_group_layouts: &bind_group_layouts,
298            push_constant_ranges: desc.push_constant_ranges,
299            flags: desc.flags,
300        };
301
302        unsafe { D::create_pipeline_layout(self, &desc) }
303            .map(|b| -> Box<dyn DynPipelineLayout> { Box::new(b) })
304    }
305
306    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>) {
307        unsafe { D::destroy_pipeline_layout(self, pipeline_layout.unbox()) };
308    }
309
310    unsafe fn create_bind_group(
311        &self,
312        desc: &BindGroupDescriptor<
313            dyn DynBindGroupLayout,
314            dyn DynBuffer,
315            dyn DynSampler,
316            dyn DynTextureView,
317            dyn DynAccelerationStructure,
318        >,
319    ) -> Result<Box<dyn DynBindGroup>, DeviceError> {
320        let buffers: Vec<_> = desc
321            .buffers
322            .iter()
323            .map(|b| b.clone().expect_downcast())
324            .collect();
325        let samplers: Vec<_> = desc
326            .samplers
327            .iter()
328            .map(|s| s.expect_downcast_ref())
329            .collect();
330        let textures: Vec<_> = desc
331            .textures
332            .iter()
333            .map(|t| t.clone().expect_downcast())
334            .collect();
335        let acceleration_structures: Vec<_> = desc
336            .acceleration_structures
337            .iter()
338            .map(|a| a.expect_downcast_ref())
339            .collect();
340        let external_textures: Vec<_> = desc
341            .external_textures
342            .iter()
343            .map(|et| et.clone().expect_downcast())
344            .collect();
345
346        let desc = BindGroupDescriptor {
347            label: desc.label.to_owned(),
348            layout: desc.layout.expect_downcast_ref(),
349            buffers: &buffers,
350            samplers: &samplers,
351            textures: &textures,
352            entries: desc.entries,
353            acceleration_structures: &acceleration_structures,
354            external_textures: &external_textures,
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_processor: match &desc.vertex_processor {
390                crate::VertexProcessor::Standard {
391                    vertex_buffers,
392                    vertex_stage,
393                } => crate::VertexProcessor::Standard {
394                    vertex_buffers,
395                    vertex_stage: vertex_stage.clone().expect_downcast(),
396                },
397                crate::VertexProcessor::Mesh {
398                    task_stage: task,
399                    mesh_stage: mesh,
400                } => crate::VertexProcessor::Mesh {
401                    task_stage: task.as_ref().map(|a| a.clone().expect_downcast()),
402                    mesh_stage: mesh.clone().expect_downcast(),
403                },
404            },
405            primitive: desc.primitive,
406            depth_stencil: desc.depth_stencil.clone(),
407            multisample: desc.multisample,
408            fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
409            color_targets: desc.color_targets,
410            multiview: desc.multiview,
411            cache: desc.cache.map(|c| c.expect_downcast_ref()),
412        };
413
414        unsafe { D::create_render_pipeline(self, &desc) }
415            .map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
416    }
417
418    unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
419        unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
420    }
421
422    unsafe fn create_compute_pipeline(
423        &self,
424        desc: &ComputePipelineDescriptor<
425            dyn DynPipelineLayout,
426            dyn DynShaderModule,
427            dyn DynPipelineCache,
428        >,
429    ) -> Result<Box<dyn DynComputePipeline>, PipelineError> {
430        let desc = ComputePipelineDescriptor {
431            label: desc.label,
432            layout: desc.layout.expect_downcast_ref(),
433            stage: desc.stage.clone().expect_downcast(),
434            cache: desc.cache.as_ref().map(|c| c.expect_downcast_ref()),
435        };
436
437        unsafe { D::create_compute_pipeline(self, &desc) }
438            .map(|b| -> Box<dyn DynComputePipeline> { Box::new(b) })
439    }
440
441    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>) {
442        unsafe { D::destroy_compute_pipeline(self, pipeline.unbox()) };
443    }
444
445    unsafe fn create_pipeline_cache(
446        &self,
447        desc: &PipelineCacheDescriptor<'_>,
448    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError> {
449        unsafe { D::create_pipeline_cache(self, desc) }
450            .map(|b| -> Box<dyn DynPipelineCache> { Box::new(b) })
451    }
452
453    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
454        D::pipeline_cache_validation_key(self)
455    }
456
457    unsafe fn destroy_pipeline_cache(&self, pipeline_cache: Box<dyn DynPipelineCache>) {
458        unsafe { D::destroy_pipeline_cache(self, pipeline_cache.unbox()) };
459    }
460
461    unsafe fn create_query_set(
462        &self,
463        desc: &wgt::QuerySetDescriptor<Label>,
464    ) -> Result<Box<dyn DynQuerySet>, DeviceError> {
465        unsafe { D::create_query_set(self, desc) }.map(|b| -> Box<dyn DynQuerySet> { Box::new(b) })
466    }
467
468    unsafe fn destroy_query_set(&self, query_set: Box<dyn DynQuerySet>) {
469        unsafe { D::destroy_query_set(self, query_set.unbox()) };
470    }
471
472    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError> {
473        unsafe { D::create_fence(self) }.map(|b| -> Box<dyn DynFence> { Box::new(b) })
474    }
475
476    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>) {
477        unsafe { D::destroy_fence(self, fence.unbox()) };
478    }
479
480    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError> {
481        let fence = fence.expect_downcast_ref();
482        unsafe { D::get_fence_value(self, fence) }
483    }
484
485    unsafe fn wait(
486        &self,
487        fence: &dyn DynFence,
488        value: FenceValue,
489        timeout_ms: u32,
490    ) -> Result<bool, DeviceError> {
491        let fence = fence.expect_downcast_ref();
492        unsafe { D::wait(self, fence, value, timeout_ms) }
493    }
494
495    unsafe fn start_graphics_debugger_capture(&self) -> bool {
496        unsafe { D::start_graphics_debugger_capture(self) }
497    }
498
499    unsafe fn stop_graphics_debugger_capture(&self) {
500        unsafe { D::stop_graphics_debugger_capture(self) }
501    }
502
503    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>> {
504        let cache = cache.expect_downcast_ref();
505        unsafe { D::pipeline_cache_get_data(self, cache) }
506    }
507
508    unsafe fn create_acceleration_structure(
509        &self,
510        desc: &AccelerationStructureDescriptor,
511    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError> {
512        unsafe { D::create_acceleration_structure(self, desc) }
513            .map(|b| -> Box<dyn DynAccelerationStructure> { Box::new(b) })
514    }
515
516    unsafe fn get_acceleration_structure_build_sizes(
517        &self,
518        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
519    ) -> AccelerationStructureBuildSizes {
520        let entries = desc.entries.expect_downcast();
521        let desc = GetAccelerationStructureBuildSizesDescriptor {
522            entries: &entries,
523            flags: desc.flags,
524        };
525        unsafe { D::get_acceleration_structure_build_sizes(self, &desc) }
526    }
527
528    unsafe fn get_acceleration_structure_device_address(
529        &self,
530        acceleration_structure: &dyn DynAccelerationStructure,
531    ) -> wgt::BufferAddress {
532        let acceleration_structure = acceleration_structure.expect_downcast_ref();
533        unsafe { D::get_acceleration_structure_device_address(self, acceleration_structure) }
534    }
535
536    unsafe fn destroy_acceleration_structure(
537        &self,
538        acceleration_structure: Box<dyn DynAccelerationStructure>,
539    ) {
540        unsafe { D::destroy_acceleration_structure(self, acceleration_structure.unbox()) }
541    }
542
543    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
544        D::tlas_instance_to_bytes(self, instance)
545    }
546
547    fn get_internal_counters(&self) -> wgt::HalCounters {
548        D::get_internal_counters(self)
549    }
550
551    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
552        D::generate_allocator_report(self)
553    }
554
555    fn check_if_oom(&self) -> Result<(), DeviceError> {
556        D::check_if_oom(self)
557    }
558}