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}