wgpu_hal/dynamic/
device.rs

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