wgpu_hal/dynamic/
command.rs

1use alloc::{boxed::Box, vec::Vec};
2use core::ops::Range;
3
4use crate::{
5    AccelerationStructureBarrier, Api, Attachment, BufferBarrier, BufferBinding, BufferCopy,
6    BufferTextureCopy, BuildAccelerationStructureDescriptor, ColorAttachment, CommandEncoder,
7    ComputePassDescriptor, DepthStencilAttachment, DeviceError, Label, MemoryRange,
8    PassTimestampWrites, Rect, RenderPassDescriptor, TextureBarrier, TextureCopy,
9};
10
11use super::{
12    DynAccelerationStructure, DynBindGroup, DynBuffer, DynCommandBuffer, DynComputePipeline,
13    DynPipelineLayout, DynQuerySet, DynRenderPipeline, DynResource, DynResourceExt as _,
14    DynTexture, DynTextureView,
15};
16
17pub trait DynCommandEncoder: DynResource + core::fmt::Debug {
18    unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
19
20    unsafe fn discard_encoding(&mut self);
21
22    unsafe fn end_encoding(&mut self) -> Result<Box<dyn DynCommandBuffer>, DeviceError>;
23
24    unsafe fn reset_all(&mut self, command_buffers: Vec<Box<dyn DynCommandBuffer>>);
25
26    unsafe fn transition_buffers(&mut self, barriers: &[BufferBarrier<'_, dyn DynBuffer>]);
27    unsafe fn transition_textures(&mut self, barriers: &[TextureBarrier<'_, dyn DynTexture>]);
28
29    unsafe fn clear_buffer(&mut self, buffer: &dyn DynBuffer, range: MemoryRange);
30
31    unsafe fn copy_buffer_to_buffer(
32        &mut self,
33        src: &dyn DynBuffer,
34        dst: &dyn DynBuffer,
35        regions: &[BufferCopy],
36    );
37
38    unsafe fn copy_texture_to_texture(
39        &mut self,
40        src: &dyn DynTexture,
41        src_usage: wgt::TextureUses,
42        dst: &dyn DynTexture,
43        regions: &[TextureCopy],
44    );
45
46    unsafe fn copy_buffer_to_texture(
47        &mut self,
48        src: &dyn DynBuffer,
49        dst: &dyn DynTexture,
50        regions: &[BufferTextureCopy],
51    );
52
53    unsafe fn copy_texture_to_buffer(
54        &mut self,
55        src: &dyn DynTexture,
56        src_usage: wgt::TextureUses,
57        dst: &dyn DynBuffer,
58        regions: &[BufferTextureCopy],
59    );
60
61    unsafe fn set_bind_group(
62        &mut self,
63        layout: &dyn DynPipelineLayout,
64        index: u32,
65        group: Option<&dyn DynBindGroup>,
66        dynamic_offsets: &[wgt::DynamicOffset],
67    );
68
69    unsafe fn set_immediates(
70        &mut self,
71        layout: &dyn DynPipelineLayout,
72        offset_bytes: u32,
73        data: &[u32],
74    );
75
76    unsafe fn insert_debug_marker(&mut self, label: &str);
77    unsafe fn begin_debug_marker(&mut self, group_label: &str);
78    unsafe fn end_debug_marker(&mut self);
79
80    unsafe fn begin_query(&mut self, set: &dyn DynQuerySet, index: u32);
81    unsafe fn end_query(&mut self, set: &dyn DynQuerySet, index: u32);
82    unsafe fn write_timestamp(&mut self, set: &dyn DynQuerySet, index: u32);
83    unsafe fn reset_queries(&mut self, set: &dyn DynQuerySet, range: Range<u32>);
84    unsafe fn copy_query_results(
85        &mut self,
86        set: &dyn DynQuerySet,
87        range: Range<u32>,
88        buffer: &dyn DynBuffer,
89        offset: wgt::BufferAddress,
90        stride: wgt::BufferSize,
91    );
92
93    unsafe fn begin_render_pass(
94        &mut self,
95        desc: &RenderPassDescriptor<dyn DynQuerySet, dyn DynTextureView>,
96    ) -> Result<(), DeviceError>;
97    unsafe fn end_render_pass(&mut self);
98
99    unsafe fn set_render_pipeline(&mut self, pipeline: &dyn DynRenderPipeline);
100
101    unsafe fn set_index_buffer<'a>(
102        &mut self,
103        binding: BufferBinding<'a, dyn DynBuffer>,
104        format: wgt::IndexFormat,
105    );
106
107    unsafe fn set_vertex_buffer<'a>(
108        &mut self,
109        index: u32,
110        binding: BufferBinding<'a, dyn DynBuffer>,
111    );
112    unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
113    unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
114    unsafe fn set_stencil_reference(&mut self, value: u32);
115    unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
116
117    unsafe fn draw(
118        &mut self,
119        first_vertex: u32,
120        vertex_count: u32,
121        first_instance: u32,
122        instance_count: u32,
123    );
124    unsafe fn draw_indexed(
125        &mut self,
126        first_index: u32,
127        index_count: u32,
128        base_vertex: i32,
129        first_instance: u32,
130        instance_count: u32,
131    );
132    unsafe fn draw_mesh_tasks(
133        &mut self,
134        group_count_x: u32,
135        group_count_y: u32,
136        group_count_z: u32,
137    );
138    unsafe fn draw_indirect(
139        &mut self,
140        buffer: &dyn DynBuffer,
141        offset: wgt::BufferAddress,
142        draw_count: u32,
143    );
144    unsafe fn draw_indexed_indirect(
145        &mut self,
146        buffer: &dyn DynBuffer,
147        offset: wgt::BufferAddress,
148        draw_count: u32,
149    );
150    unsafe fn draw_mesh_tasks_indirect(
151        &mut self,
152        buffer: &dyn DynBuffer,
153        offset: wgt::BufferAddress,
154        draw_count: u32,
155    );
156    unsafe fn draw_indirect_count(
157        &mut self,
158        buffer: &dyn DynBuffer,
159        offset: wgt::BufferAddress,
160        count_buffer: &dyn DynBuffer,
161        count_offset: wgt::BufferAddress,
162        max_count: u32,
163    );
164    unsafe fn draw_indexed_indirect_count(
165        &mut self,
166        buffer: &dyn DynBuffer,
167        offset: wgt::BufferAddress,
168        count_buffer: &dyn DynBuffer,
169        count_offset: wgt::BufferAddress,
170        max_count: u32,
171    );
172    unsafe fn draw_mesh_tasks_indirect_count(
173        &mut self,
174        buffer: &dyn DynBuffer,
175        offset: wgt::BufferAddress,
176        count_buffer: &dyn DynBuffer,
177        count_offset: wgt::BufferAddress,
178        max_count: u32,
179    );
180
181    unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>);
182    unsafe fn end_compute_pass(&mut self);
183
184    unsafe fn set_compute_pipeline(&mut self, pipeline: &dyn DynComputePipeline);
185
186    unsafe fn dispatch(&mut self, count: [u32; 3]);
187    unsafe fn dispatch_indirect(&mut self, buffer: &dyn DynBuffer, offset: wgt::BufferAddress);
188
189    unsafe fn build_acceleration_structures<'a>(
190        &mut self,
191        descriptors: &'a [BuildAccelerationStructureDescriptor<
192            'a,
193            dyn DynBuffer,
194            dyn DynAccelerationStructure,
195        >],
196    );
197
198    unsafe fn place_acceleration_structure_barrier(
199        &mut self,
200        barrier: AccelerationStructureBarrier,
201    );
202
203    unsafe fn copy_acceleration_structure_to_acceleration_structure(
204        &mut self,
205        src: &dyn DynAccelerationStructure,
206        dst: &dyn DynAccelerationStructure,
207        copy: wgt::AccelerationStructureCopy,
208    );
209    unsafe fn read_acceleration_structure_compact_size(
210        &mut self,
211        acceleration_structure: &dyn DynAccelerationStructure,
212        buf: &dyn DynBuffer,
213    );
214}
215
216impl<C: CommandEncoder + DynResource> DynCommandEncoder for C {
217    unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError> {
218        unsafe { C::begin_encoding(self, label) }
219    }
220
221    unsafe fn discard_encoding(&mut self) {
222        unsafe { C::discard_encoding(self) }
223    }
224
225    unsafe fn end_encoding(&mut self) -> Result<Box<dyn DynCommandBuffer>, DeviceError> {
226        unsafe { C::end_encoding(self) }.map(|cb| {
227            let boxed_command_buffer: Box<<C::A as Api>::CommandBuffer> = Box::new(cb);
228            let boxed_command_buffer: Box<dyn DynCommandBuffer> = boxed_command_buffer;
229            boxed_command_buffer
230        })
231    }
232
233    unsafe fn reset_all(&mut self, command_buffers: Vec<Box<dyn DynCommandBuffer>>) {
234        unsafe { C::reset_all(self, command_buffers.into_iter().map(|cb| cb.unbox())) }
235    }
236
237    unsafe fn transition_buffers(&mut self, barriers: &[BufferBarrier<'_, dyn DynBuffer>]) {
238        let barriers = barriers.iter().map(|barrier| BufferBarrier {
239            buffer: barrier.buffer.expect_downcast_ref(),
240            usage: barrier.usage.clone(),
241        });
242        unsafe { self.transition_buffers(barriers) };
243    }
244
245    unsafe fn transition_textures(&mut self, barriers: &[TextureBarrier<'_, dyn DynTexture>]) {
246        let barriers = barriers.iter().map(|barrier| TextureBarrier {
247            texture: barrier.texture.expect_downcast_ref(),
248            usage: barrier.usage.clone(),
249            range: barrier.range,
250        });
251        unsafe { self.transition_textures(barriers) };
252    }
253
254    unsafe fn clear_buffer(&mut self, buffer: &dyn DynBuffer, range: MemoryRange) {
255        let buffer = buffer.expect_downcast_ref();
256        unsafe { C::clear_buffer(self, buffer, range) };
257    }
258
259    unsafe fn copy_buffer_to_buffer(
260        &mut self,
261        src: &dyn DynBuffer,
262        dst: &dyn DynBuffer,
263        regions: &[BufferCopy],
264    ) {
265        let src = src.expect_downcast_ref();
266        let dst = dst.expect_downcast_ref();
267        unsafe {
268            C::copy_buffer_to_buffer(self, src, dst, regions.iter().copied());
269        }
270    }
271
272    unsafe fn copy_texture_to_texture(
273        &mut self,
274        src: &dyn DynTexture,
275        src_usage: wgt::TextureUses,
276        dst: &dyn DynTexture,
277        regions: &[TextureCopy],
278    ) {
279        let src = src.expect_downcast_ref();
280        let dst = dst.expect_downcast_ref();
281        unsafe {
282            C::copy_texture_to_texture(self, src, src_usage, dst, regions.iter().cloned());
283        }
284    }
285
286    unsafe fn copy_buffer_to_texture(
287        &mut self,
288        src: &dyn DynBuffer,
289        dst: &dyn DynTexture,
290        regions: &[BufferTextureCopy],
291    ) {
292        let src = src.expect_downcast_ref();
293        let dst = dst.expect_downcast_ref();
294        unsafe {
295            C::copy_buffer_to_texture(self, src, dst, regions.iter().cloned());
296        }
297    }
298
299    unsafe fn copy_texture_to_buffer(
300        &mut self,
301        src: &dyn DynTexture,
302        src_usage: wgt::TextureUses,
303        dst: &dyn DynBuffer,
304        regions: &[BufferTextureCopy],
305    ) {
306        let src = src.expect_downcast_ref();
307        let dst = dst.expect_downcast_ref();
308        unsafe {
309            C::copy_texture_to_buffer(self, src, src_usage, dst, regions.iter().cloned());
310        }
311    }
312
313    unsafe fn set_bind_group(
314        &mut self,
315        layout: &dyn DynPipelineLayout,
316        index: u32,
317        group: Option<&dyn DynBindGroup>,
318        dynamic_offsets: &[wgt::DynamicOffset],
319    ) {
320        if group.is_none() {
321            // TODO: Handle group None correctly.
322            return;
323        }
324        let group = group.unwrap();
325
326        let layout = layout.expect_downcast_ref();
327        let group = group.expect_downcast_ref();
328        unsafe { C::set_bind_group(self, layout, index, group, dynamic_offsets) };
329    }
330
331    unsafe fn set_immediates(
332        &mut self,
333        layout: &dyn DynPipelineLayout,
334        offset_bytes: u32,
335        data: &[u32],
336    ) {
337        let layout = layout.expect_downcast_ref();
338        unsafe { C::set_immediates(self, layout, offset_bytes, data) };
339    }
340
341    unsafe fn insert_debug_marker(&mut self, label: &str) {
342        unsafe {
343            C::insert_debug_marker(self, label);
344        }
345    }
346
347    unsafe fn begin_debug_marker(&mut self, group_label: &str) {
348        unsafe {
349            C::begin_debug_marker(self, group_label);
350        }
351    }
352
353    unsafe fn end_debug_marker(&mut self) {
354        unsafe {
355            C::end_debug_marker(self);
356        }
357    }
358
359    unsafe fn begin_query(&mut self, set: &dyn DynQuerySet, index: u32) {
360        let set = set.expect_downcast_ref();
361        unsafe { C::begin_query(self, set, index) };
362    }
363
364    unsafe fn end_query(&mut self, set: &dyn DynQuerySet, index: u32) {
365        let set = set.expect_downcast_ref();
366        unsafe { C::end_query(self, set, index) };
367    }
368
369    unsafe fn write_timestamp(&mut self, set: &dyn DynQuerySet, index: u32) {
370        let set = set.expect_downcast_ref();
371        unsafe { C::write_timestamp(self, set, index) };
372    }
373
374    unsafe fn reset_queries(&mut self, set: &dyn DynQuerySet, range: Range<u32>) {
375        let set = set.expect_downcast_ref();
376        unsafe { C::reset_queries(self, set, range) };
377    }
378
379    unsafe fn copy_query_results(
380        &mut self,
381        set: &dyn DynQuerySet,
382        range: Range<u32>,
383        buffer: &dyn DynBuffer,
384        offset: wgt::BufferAddress,
385        stride: wgt::BufferSize,
386    ) {
387        let set = set.expect_downcast_ref();
388        let buffer = buffer.expect_downcast_ref();
389        unsafe { C::copy_query_results(self, set, range, buffer, offset, stride) };
390    }
391
392    unsafe fn begin_render_pass(
393        &mut self,
394        desc: &RenderPassDescriptor<dyn DynQuerySet, dyn DynTextureView>,
395    ) -> Result<(), DeviceError> {
396        let color_attachments = desc
397            .color_attachments
398            .iter()
399            .map(|attachment| {
400                attachment
401                    .as_ref()
402                    .map(|attachment| attachment.expect_downcast())
403            })
404            .collect::<Vec<_>>();
405
406        let desc: RenderPassDescriptor<<C::A as Api>::QuerySet, <C::A as Api>::TextureView> =
407            RenderPassDescriptor {
408                label: desc.label,
409                extent: desc.extent,
410                sample_count: desc.sample_count,
411                color_attachments: &color_attachments,
412                depth_stencil_attachment: desc
413                    .depth_stencil_attachment
414                    .as_ref()
415                    .map(|ds| ds.expect_downcast()),
416                multiview_mask: desc.multiview_mask,
417                timestamp_writes: desc
418                    .timestamp_writes
419                    .as_ref()
420                    .map(|writes| writes.expect_downcast()),
421                occlusion_query_set: desc
422                    .occlusion_query_set
423                    .map(|set| set.expect_downcast_ref()),
424            };
425        unsafe { C::begin_render_pass(self, &desc) }
426    }
427
428    unsafe fn end_render_pass(&mut self) {
429        unsafe {
430            C::end_render_pass(self);
431        }
432    }
433
434    unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>) {
435        unsafe {
436            C::set_viewport(self, rect, depth_range);
437        }
438    }
439
440    unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>) {
441        unsafe {
442            C::set_scissor_rect(self, rect);
443        }
444    }
445
446    unsafe fn set_stencil_reference(&mut self, value: u32) {
447        unsafe {
448            C::set_stencil_reference(self, value);
449        }
450    }
451
452    unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {
453        unsafe { C::set_blend_constants(self, color) };
454    }
455
456    unsafe fn draw(
457        &mut self,
458        first_vertex: u32,
459        vertex_count: u32,
460        first_instance: u32,
461        instance_count: u32,
462    ) {
463        unsafe {
464            C::draw(
465                self,
466                first_vertex,
467                vertex_count,
468                first_instance,
469                instance_count,
470            )
471        };
472    }
473
474    unsafe fn draw_indexed(
475        &mut self,
476        first_index: u32,
477        index_count: u32,
478        base_vertex: i32,
479        first_instance: u32,
480        instance_count: u32,
481    ) {
482        unsafe {
483            C::draw_indexed(
484                self,
485                first_index,
486                index_count,
487                base_vertex,
488                first_instance,
489                instance_count,
490            )
491        };
492    }
493
494    unsafe fn draw_mesh_tasks(
495        &mut self,
496        group_count_x: u32,
497        group_count_y: u32,
498        group_count_z: u32,
499    ) {
500        unsafe { C::draw_mesh_tasks(self, group_count_x, group_count_y, group_count_z) };
501    }
502
503    unsafe fn draw_indirect(
504        &mut self,
505        buffer: &dyn DynBuffer,
506        offset: wgt::BufferAddress,
507        draw_count: u32,
508    ) {
509        let buffer = buffer.expect_downcast_ref();
510        unsafe { C::draw_indirect(self, buffer, offset, draw_count) };
511    }
512
513    unsafe fn draw_indexed_indirect(
514        &mut self,
515        buffer: &dyn DynBuffer,
516        offset: wgt::BufferAddress,
517        draw_count: u32,
518    ) {
519        let buffer = buffer.expect_downcast_ref();
520        unsafe { C::draw_indexed_indirect(self, buffer, offset, draw_count) };
521    }
522
523    unsafe fn draw_mesh_tasks_indirect(
524        &mut self,
525        buffer: &dyn DynBuffer,
526        offset: wgt::BufferAddress,
527        draw_count: u32,
528    ) {
529        let buffer = buffer.expect_downcast_ref();
530        unsafe { C::draw_mesh_tasks_indirect(self, buffer, offset, draw_count) };
531    }
532
533    unsafe fn draw_indirect_count(
534        &mut self,
535        buffer: &dyn DynBuffer,
536        offset: wgt::BufferAddress,
537        count_buffer: &dyn DynBuffer,
538        count_offset: wgt::BufferAddress,
539        max_count: u32,
540    ) {
541        let buffer = buffer.expect_downcast_ref();
542        let count_buffer = count_buffer.expect_downcast_ref();
543        unsafe {
544            C::draw_indirect_count(self, buffer, offset, count_buffer, count_offset, max_count)
545        };
546    }
547
548    unsafe fn draw_indexed_indirect_count(
549        &mut self,
550        buffer: &dyn DynBuffer,
551        offset: wgt::BufferAddress,
552        count_buffer: &dyn DynBuffer,
553        count_offset: wgt::BufferAddress,
554        max_count: u32,
555    ) {
556        let buffer = buffer.expect_downcast_ref();
557        let count_buffer = count_buffer.expect_downcast_ref();
558        unsafe {
559            C::draw_indexed_indirect_count(
560                self,
561                buffer,
562                offset,
563                count_buffer,
564                count_offset,
565                max_count,
566            )
567        };
568    }
569
570    unsafe fn draw_mesh_tasks_indirect_count(
571        &mut self,
572        buffer: &dyn DynBuffer,
573        offset: wgt::BufferAddress,
574        count_buffer: &dyn DynBuffer,
575        count_offset: wgt::BufferAddress,
576        max_count: u32,
577    ) {
578        let buffer = buffer.expect_downcast_ref();
579        let count_buffer = count_buffer.expect_downcast_ref();
580        unsafe {
581            C::draw_mesh_tasks_indirect_count(
582                self,
583                buffer,
584                offset,
585                count_buffer,
586                count_offset,
587                max_count,
588            )
589        };
590    }
591
592    unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>) {
593        let desc = ComputePassDescriptor {
594            label: desc.label,
595            timestamp_writes: desc
596                .timestamp_writes
597                .as_ref()
598                .map(|writes| writes.expect_downcast()),
599        };
600        unsafe { C::begin_compute_pass(self, &desc) };
601    }
602
603    unsafe fn end_compute_pass(&mut self) {
604        unsafe { C::end_compute_pass(self) };
605    }
606
607    unsafe fn set_compute_pipeline(&mut self, pipeline: &dyn DynComputePipeline) {
608        let pipeline = pipeline.expect_downcast_ref();
609        unsafe { C::set_compute_pipeline(self, pipeline) };
610    }
611
612    unsafe fn dispatch(&mut self, count: [u32; 3]) {
613        unsafe { C::dispatch(self, count) };
614    }
615
616    unsafe fn dispatch_indirect(&mut self, buffer: &dyn DynBuffer, offset: wgt::BufferAddress) {
617        let buffer = buffer.expect_downcast_ref();
618        unsafe { C::dispatch_indirect(self, buffer, offset) };
619    }
620
621    unsafe fn set_render_pipeline(&mut self, pipeline: &dyn DynRenderPipeline) {
622        let pipeline = pipeline.expect_downcast_ref();
623        unsafe { C::set_render_pipeline(self, pipeline) };
624    }
625
626    unsafe fn set_index_buffer<'a>(
627        &mut self,
628        binding: BufferBinding<'a, dyn DynBuffer>,
629        format: wgt::IndexFormat,
630    ) {
631        let binding = binding.expect_downcast();
632        unsafe { self.set_index_buffer(binding, format) };
633    }
634
635    unsafe fn set_vertex_buffer<'a>(
636        &mut self,
637        index: u32,
638        binding: BufferBinding<'a, dyn DynBuffer>,
639    ) {
640        let binding = binding.expect_downcast();
641        unsafe { self.set_vertex_buffer(index, binding) };
642    }
643
644    unsafe fn build_acceleration_structures<'a>(
645        &mut self,
646        descriptors: &'a [BuildAccelerationStructureDescriptor<
647            'a,
648            dyn DynBuffer,
649            dyn DynAccelerationStructure,
650        >],
651    ) {
652        // Need to collect entries here so we can reference them in the descriptor.
653        // TODO: API should be redesigned to avoid this and other descriptor copies that happen due to the dyn api.
654        let descriptor_entries = descriptors
655            .iter()
656            .map(|d| d.entries.expect_downcast())
657            .collect::<Vec<_>>();
658        let descriptors = descriptors
659            .iter()
660            .zip(descriptor_entries.iter())
661            .map(|(d, entries)| BuildAccelerationStructureDescriptor::<
662                <C::A as Api>::Buffer,
663                <C::A as Api>::AccelerationStructure,
664            > {
665                entries,
666                mode: d.mode,
667                flags: d.flags,
668                source_acceleration_structure: d
669                    .source_acceleration_structure
670                    .map(|a| a.expect_downcast_ref()),
671                destination_acceleration_structure: d
672                    .destination_acceleration_structure
673                    .expect_downcast_ref(),
674                scratch_buffer: d.scratch_buffer.expect_downcast_ref(),
675                scratch_buffer_offset: d.scratch_buffer_offset,
676            });
677        unsafe { C::build_acceleration_structures(self, descriptors.len() as _, descriptors) };
678    }
679
680    unsafe fn place_acceleration_structure_barrier(
681        &mut self,
682        barrier: AccelerationStructureBarrier,
683    ) {
684        unsafe { C::place_acceleration_structure_barrier(self, barrier) };
685    }
686
687    unsafe fn copy_acceleration_structure_to_acceleration_structure(
688        &mut self,
689        src: &dyn DynAccelerationStructure,
690        dst: &dyn DynAccelerationStructure,
691        copy: wgt::AccelerationStructureCopy,
692    ) {
693        let src = src.expect_downcast_ref();
694        let dst = dst.expect_downcast_ref();
695        unsafe { C::copy_acceleration_structure_to_acceleration_structure(self, src, dst, copy) };
696    }
697    unsafe fn read_acceleration_structure_compact_size(
698        &mut self,
699        acceleration_structure: &dyn DynAccelerationStructure,
700        buf: &dyn DynBuffer,
701    ) {
702        let acceleration_structure = acceleration_structure.expect_downcast_ref();
703        let buf = buf.expect_downcast_ref();
704        unsafe { C::read_acceleration_structure_compact_size(self, acceleration_structure, buf) }
705    }
706}
707
708impl<'a> PassTimestampWrites<'a, dyn DynQuerySet> {
709    pub fn expect_downcast<B: DynQuerySet>(&self) -> PassTimestampWrites<'a, B> {
710        PassTimestampWrites {
711            query_set: self.query_set.expect_downcast_ref(),
712            beginning_of_pass_write_index: self.beginning_of_pass_write_index,
713            end_of_pass_write_index: self.end_of_pass_write_index,
714        }
715    }
716}
717
718impl<'a> Attachment<'a, dyn DynTextureView> {
719    pub fn expect_downcast<B: DynTextureView>(&self) -> Attachment<'a, B> {
720        Attachment {
721            view: self.view.expect_downcast_ref(),
722            usage: self.usage,
723        }
724    }
725}
726
727impl<'a> ColorAttachment<'a, dyn DynTextureView> {
728    pub fn expect_downcast<B: DynTextureView>(&self) -> ColorAttachment<'a, B> {
729        ColorAttachment {
730            target: self.target.expect_downcast(),
731            depth_slice: self.depth_slice,
732            resolve_target: self.resolve_target.as_ref().map(|rt| rt.expect_downcast()),
733            ops: self.ops,
734            clear_value: self.clear_value,
735        }
736    }
737}
738
739impl<'a> DepthStencilAttachment<'a, dyn DynTextureView> {
740    pub fn expect_downcast<B: DynTextureView>(&self) -> DepthStencilAttachment<'a, B> {
741        DepthStencilAttachment {
742            target: self.target.expect_downcast(),
743            depth_ops: self.depth_ops,
744            stencil_ops: self.stencil_ops,
745            clear_value: self.clear_value,
746        }
747    }
748}