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,
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 exit(self: Box<Self>, queue: Box<dyn DynQueue>);
20
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    unsafe fn destroy_command_encoder(&self, pool: Box<dyn DynCommandEncoder>);
64
65    unsafe fn create_bind_group_layout(
66        &self,
67        desc: &BindGroupLayoutDescriptor,
68    ) -> Result<Box<dyn DynBindGroupLayout>, DeviceError>;
69    unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>);
70
71    unsafe fn create_pipeline_layout(
72        &self,
73        desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
74    ) -> Result<Box<dyn DynPipelineLayout>, DeviceError>;
75    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>);
76
77    unsafe fn create_bind_group(
78        &self,
79        desc: &BindGroupDescriptor<
80            dyn DynBindGroupLayout,
81            dyn DynBuffer,
82            dyn DynSampler,
83            dyn DynTextureView,
84            dyn DynAccelerationStructure,
85        >,
86    ) -> Result<Box<dyn DynBindGroup>, DeviceError>;
87    unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>);
88
89    unsafe fn create_shader_module(
90        &self,
91        desc: &ShaderModuleDescriptor,
92        shader: ShaderInput,
93    ) -> Result<Box<dyn DynShaderModule>, ShaderError>;
94    unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>);
95
96    unsafe fn create_render_pipeline(
97        &self,
98        desc: &RenderPipelineDescriptor<
99            dyn DynPipelineLayout,
100            dyn DynShaderModule,
101            dyn DynPipelineCache,
102        >,
103    ) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
104    unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>);
105
106    unsafe fn create_compute_pipeline(
107        &self,
108        desc: &ComputePipelineDescriptor<
109            dyn DynPipelineLayout,
110            dyn DynShaderModule,
111            dyn DynPipelineCache,
112        >,
113    ) -> Result<Box<dyn DynComputePipeline>, PipelineError>;
114    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>);
115
116    unsafe fn create_pipeline_cache(
117        &self,
118        desc: &PipelineCacheDescriptor<'_>,
119    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError>;
120    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
121        None
122    }
123    unsafe fn destroy_pipeline_cache(&self, cache: Box<dyn DynPipelineCache>);
124
125    unsafe fn create_query_set(
126        &self,
127        desc: &wgt::QuerySetDescriptor<Label>,
128    ) -> Result<Box<dyn DynQuerySet>, DeviceError>;
129    unsafe fn destroy_query_set(&self, set: Box<dyn DynQuerySet>);
130
131    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError>;
132    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>);
133    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError>;
134
135    unsafe fn wait(
136        &self,
137        fence: &dyn DynFence,
138        value: FenceValue,
139        timeout_ms: u32,
140    ) -> Result<bool, DeviceError>;
141
142    unsafe fn start_capture(&self) -> bool;
143    unsafe fn stop_capture(&self);
144
145    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>>;
146
147    unsafe fn create_acceleration_structure(
148        &self,
149        desc: &AccelerationStructureDescriptor,
150    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError>;
151    unsafe fn get_acceleration_structure_build_sizes(
152        &self,
153        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
154    ) -> AccelerationStructureBuildSizes;
155    unsafe fn get_acceleration_structure_device_address(
156        &self,
157        acceleration_structure: &dyn DynAccelerationStructure,
158    ) -> wgt::BufferAddress;
159    unsafe fn destroy_acceleration_structure(
160        &self,
161        acceleration_structure: Box<dyn DynAccelerationStructure>,
162    );
163
164    fn get_internal_counters(&self) -> wgt::HalCounters;
165    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport>;
166}
167
168impl<D: Device + DynResource> DynDevice for D {
169    unsafe fn exit(self: Box<Self>, queue: Box<dyn DynQueue>) {
170        unsafe { D::exit(*self, queue.unbox()) }
171    }
172
173    unsafe fn create_buffer(
174        &self,
175        desc: &BufferDescriptor,
176    ) -> Result<Box<dyn DynBuffer>, DeviceError> {
177        unsafe { D::create_buffer(self, desc) }.map(|b| -> Box<dyn DynBuffer> { Box::new(b) })
178    }
179
180    unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>) {
181        unsafe { D::destroy_buffer(self, buffer.unbox()) };
182    }
183    unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer) {
184        let buffer = buffer.expect_downcast_ref();
185        unsafe { D::add_raw_buffer(self, buffer) };
186    }
187
188    unsafe fn map_buffer(
189        &self,
190        buffer: &dyn DynBuffer,
191        range: MemoryRange,
192    ) -> Result<BufferMapping, DeviceError> {
193        let buffer = buffer.expect_downcast_ref();
194        unsafe { D::map_buffer(self, buffer, range) }
195    }
196
197    unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer) {
198        let buffer = buffer.expect_downcast_ref();
199        unsafe { D::unmap_buffer(self, buffer) }
200    }
201
202    unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
203        let buffer = buffer.expect_downcast_ref();
204        unsafe { D::flush_mapped_ranges(self, buffer, ranges.iter().cloned()) }
205    }
206
207    unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
208        let buffer = buffer.expect_downcast_ref();
209        unsafe { D::invalidate_mapped_ranges(self, buffer, ranges.iter().cloned()) }
210    }
211
212    unsafe fn create_texture(
213        &self,
214        desc: &TextureDescriptor,
215    ) -> Result<Box<dyn DynTexture>, DeviceError> {
216        unsafe { D::create_texture(self, desc) }.map(|b| {
217            let boxed_texture: Box<<D::A as Api>::Texture> = Box::new(b);
218            let boxed_texture: Box<dyn DynTexture> = boxed_texture;
219            boxed_texture
220        })
221    }
222
223    unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>) {
224        unsafe { D::destroy_texture(self, texture.unbox()) };
225    }
226
227    unsafe fn add_raw_texture(&self, texture: &dyn DynTexture) {
228        let texture = texture.expect_downcast_ref();
229        unsafe { D::add_raw_texture(self, texture) };
230    }
231
232    unsafe fn create_texture_view(
233        &self,
234        texture: &dyn DynTexture,
235        desc: &TextureViewDescriptor,
236    ) -> Result<Box<dyn DynTextureView>, DeviceError> {
237        let texture = texture.expect_downcast_ref();
238        unsafe { D::create_texture_view(self, texture, desc) }.map(|b| {
239            let boxed_texture_view: Box<<D::A as Api>::TextureView> = Box::new(b);
240            let boxed_texture_view: Box<dyn DynTextureView> = boxed_texture_view;
241            boxed_texture_view
242        })
243    }
244
245    unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>) {
246        unsafe { D::destroy_texture_view(self, view.unbox()) };
247    }
248
249    unsafe fn create_sampler(
250        &self,
251        desc: &SamplerDescriptor,
252    ) -> Result<Box<dyn DynSampler>, DeviceError> {
253        unsafe { D::create_sampler(self, desc) }.map(|b| {
254            let boxed_sampler: Box<<D::A as Api>::Sampler> = Box::new(b);
255            let boxed_sampler: Box<dyn DynSampler> = boxed_sampler;
256            boxed_sampler
257        })
258    }
259
260    unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>) {
261        unsafe { D::destroy_sampler(self, sampler.unbox()) };
262    }
263
264    unsafe fn create_command_encoder(
265        &self,
266        desc: &CommandEncoderDescriptor<'_, dyn DynQueue>,
267    ) -> Result<Box<dyn DynCommandEncoder>, DeviceError> {
268        let desc = CommandEncoderDescriptor {
269            label: desc.label,
270            queue: desc.queue.expect_downcast_ref(),
271        };
272        unsafe { D::create_command_encoder(self, &desc) }
273            .map(|b| -> Box<dyn DynCommandEncoder> { Box::new(b) })
274    }
275
276    unsafe fn destroy_command_encoder(&self, encoder: Box<dyn DynCommandEncoder>) {
277        unsafe { D::destroy_command_encoder(self, encoder.unbox()) };
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 destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
405        unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
406    }
407
408    unsafe fn create_compute_pipeline(
409        &self,
410        desc: &ComputePipelineDescriptor<
411            dyn DynPipelineLayout,
412            dyn DynShaderModule,
413            dyn DynPipelineCache,
414        >,
415    ) -> Result<Box<dyn DynComputePipeline>, PipelineError> {
416        let desc = ComputePipelineDescriptor {
417            label: desc.label,
418            layout: desc.layout.expect_downcast_ref(),
419            stage: desc.stage.clone().expect_downcast(),
420            cache: desc.cache.as_ref().map(|c| c.expect_downcast_ref()),
421        };
422
423        unsafe { D::create_compute_pipeline(self, &desc) }
424            .map(|b| -> Box<dyn DynComputePipeline> { Box::new(b) })
425    }
426
427    unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>) {
428        unsafe { D::destroy_compute_pipeline(self, pipeline.unbox()) };
429    }
430
431    unsafe fn create_pipeline_cache(
432        &self,
433        desc: &PipelineCacheDescriptor<'_>,
434    ) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError> {
435        unsafe { D::create_pipeline_cache(self, desc) }
436            .map(|b| -> Box<dyn DynPipelineCache> { Box::new(b) })
437    }
438
439    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
440        D::pipeline_cache_validation_key(self)
441    }
442
443    unsafe fn destroy_pipeline_cache(&self, pipeline_cache: Box<dyn DynPipelineCache>) {
444        unsafe { D::destroy_pipeline_cache(self, pipeline_cache.unbox()) };
445    }
446
447    unsafe fn create_query_set(
448        &self,
449        desc: &wgt::QuerySetDescriptor<Label>,
450    ) -> Result<Box<dyn DynQuerySet>, DeviceError> {
451        unsafe { D::create_query_set(self, desc) }.map(|b| -> Box<dyn DynQuerySet> { Box::new(b) })
452    }
453
454    unsafe fn destroy_query_set(&self, query_set: Box<dyn DynQuerySet>) {
455        unsafe { D::destroy_query_set(self, query_set.unbox()) };
456    }
457
458    unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError> {
459        unsafe { D::create_fence(self) }.map(|b| -> Box<dyn DynFence> { Box::new(b) })
460    }
461
462    unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>) {
463        unsafe { D::destroy_fence(self, fence.unbox()) };
464    }
465
466    unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError> {
467        let fence = fence.expect_downcast_ref();
468        unsafe { D::get_fence_value(self, fence) }
469    }
470
471    unsafe fn wait(
472        &self,
473        fence: &dyn DynFence,
474        value: FenceValue,
475        timeout_ms: u32,
476    ) -> Result<bool, DeviceError> {
477        let fence = fence.expect_downcast_ref();
478        unsafe { D::wait(self, fence, value, timeout_ms) }
479    }
480
481    unsafe fn start_capture(&self) -> bool {
482        unsafe { D::start_capture(self) }
483    }
484
485    unsafe fn stop_capture(&self) {
486        unsafe { D::stop_capture(self) }
487    }
488
489    unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>> {
490        let cache = cache.expect_downcast_ref();
491        unsafe { D::pipeline_cache_get_data(self, cache) }
492    }
493
494    unsafe fn create_acceleration_structure(
495        &self,
496        desc: &AccelerationStructureDescriptor,
497    ) -> Result<Box<dyn DynAccelerationStructure>, DeviceError> {
498        unsafe { D::create_acceleration_structure(self, desc) }
499            .map(|b| -> Box<dyn DynAccelerationStructure> { Box::new(b) })
500    }
501
502    unsafe fn get_acceleration_structure_build_sizes(
503        &self,
504        desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
505    ) -> AccelerationStructureBuildSizes {
506        let entries = desc.entries.expect_downcast();
507        let desc = GetAccelerationStructureBuildSizesDescriptor {
508            entries: &entries,
509            flags: desc.flags,
510        };
511        unsafe { D::get_acceleration_structure_build_sizes(self, &desc) }
512    }
513
514    unsafe fn get_acceleration_structure_device_address(
515        &self,
516        acceleration_structure: &dyn DynAccelerationStructure,
517    ) -> wgt::BufferAddress {
518        let acceleration_structure = acceleration_structure.expect_downcast_ref();
519        unsafe { D::get_acceleration_structure_device_address(self, acceleration_structure) }
520    }
521
522    unsafe fn destroy_acceleration_structure(
523        &self,
524        acceleration_structure: Box<dyn DynAccelerationStructure>,
525    ) {
526        unsafe { D::destroy_acceleration_structure(self, acceleration_structure.unbox()) }
527    }
528
529    fn get_internal_counters(&self) -> wgt::HalCounters {
530        D::get_internal_counters(self)
531    }
532
533    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
534        D::generate_allocator_report(self)
535    }
536}