Skip to main content

wgpu_hal/vulkan/
command.rs

1use super::conv;
2use arrayvec::ArrayVec;
3use ash::vk;
4use core::{mem, ops::Range};
5use hashbrown::hash_map::Entry;
6
7const ALLOCATION_GRANULARITY: u32 = 16;
8const DST_IMAGE_LAYOUT: vk::ImageLayout = vk::ImageLayout::TRANSFER_DST_OPTIMAL;
9
10impl super::Texture {
11    fn map_buffer_copies<T>(&self, regions: T) -> impl Iterator<Item = vk::BufferImageCopy>
12    where
13        T: Iterator<Item = crate::BufferTextureCopy>,
14    {
15        let (block_width, block_height) = self.format.block_dimensions();
16        let format = self.format;
17        let copy_size = self.copy_size;
18        regions.map(move |r| {
19            let extent = r.texture_base.max_copy_size(&copy_size).min(&r.size);
20            let (image_subresource, image_offset) = conv::map_subresource_layers(&r.texture_base);
21            vk::BufferImageCopy {
22                buffer_offset: r.buffer_layout.offset,
23                buffer_row_length: r.buffer_layout.bytes_per_row.map_or(0, |bpr| {
24                    let block_size = format
25                        .block_copy_size(Some(r.texture_base.aspect.map()))
26                        .unwrap();
27                    block_width * (bpr / block_size)
28                }),
29                buffer_image_height: r
30                    .buffer_layout
31                    .rows_per_image
32                    .map_or(0, |rpi| rpi * block_height),
33                image_subresource,
34                image_offset,
35                image_extent: conv::map_copy_extent(&extent),
36            }
37        })
38    }
39}
40
41impl super::CommandEncoder {
42    fn write_pass_end_timestamp_if_requested(&mut self) {
43        if let Some((query_set, index)) = self.end_of_pass_timer_query.take() {
44            unsafe {
45                self.device.raw.cmd_write_timestamp(
46                    self.active,
47                    vk::PipelineStageFlags::BOTTOM_OF_PIPE,
48                    query_set,
49                    index,
50                );
51            }
52        }
53    }
54
55    fn make_framebuffer(
56        &mut self,
57        key: super::FramebufferKey,
58    ) -> Result<vk::Framebuffer, crate::DeviceError> {
59        Ok(match self.framebuffers.entry(key) {
60            Entry::Occupied(e) => *e.get(),
61            Entry::Vacant(e) => {
62                let super::FramebufferKey {
63                    raw_pass,
64                    ref attachment_views,
65                    attachment_identities: _,
66                    extent,
67                } = *e.key();
68
69                let vk_info = vk::FramebufferCreateInfo::default()
70                    .render_pass(raw_pass)
71                    .width(extent.width)
72                    .height(extent.height)
73                    .layers(extent.depth_or_array_layers)
74                    .attachments(attachment_views);
75
76                let raw = unsafe { self.device.raw.create_framebuffer(&vk_info, None).unwrap() };
77                *e.insert(raw)
78            }
79        })
80    }
81
82    fn make_temp_texture_view(
83        &mut self,
84        key: super::TempTextureViewKey,
85    ) -> Result<super::IdentifiedTextureView, crate::DeviceError> {
86        Ok(match self.temp_texture_views.entry(key) {
87            Entry::Occupied(e) => *e.get(),
88            Entry::Vacant(e) => {
89                let super::TempTextureViewKey {
90                    texture,
91                    texture_identity: _,
92                    format,
93                    mip_level,
94                    depth_slice,
95                } = *e.key();
96
97                let vk_info = vk::ImageViewCreateInfo::default()
98                    .image(texture)
99                    .view_type(vk::ImageViewType::TYPE_2D)
100                    .format(format)
101                    .subresource_range(vk::ImageSubresourceRange {
102                        aspect_mask: vk::ImageAspectFlags::COLOR,
103                        base_mip_level: mip_level,
104                        level_count: 1,
105                        base_array_layer: depth_slice,
106                        layer_count: 1,
107                    });
108                let raw = unsafe { self.device.raw.create_image_view(&vk_info, None) }
109                    .map_err(super::map_host_device_oom_and_ioca_err)?;
110
111                let identity = self.device.texture_view_identity_factory.next();
112
113                *e.insert(super::IdentifiedTextureView { raw, identity })
114            }
115        })
116    }
117}
118
119impl crate::CommandEncoder for super::CommandEncoder {
120    type A = super::Api;
121
122    unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
123        if self.free.is_empty() {
124            let vk_info = vk::CommandBufferAllocateInfo::default()
125                .command_pool(self.raw)
126                .command_buffer_count(ALLOCATION_GRANULARITY);
127            let cmd_buf_vec = unsafe {
128                self.device
129                    .raw
130                    .allocate_command_buffers(&vk_info)
131                    .map_err(super::map_host_device_oom_err)?
132            };
133            self.free.extend(cmd_buf_vec);
134        }
135        let raw = self.free.pop().unwrap();
136
137        // Set the name unconditionally, since there might be a
138        // previous name assigned to this.
139        unsafe { self.device.set_object_name(raw, label.unwrap_or_default()) };
140
141        // Reset some state in case the last renderpass was never ended.
142        self.rpass_debug_marker_active = false;
143        self.end_of_pass_timer_query = None;
144
145        let vk_info = vk::CommandBufferBeginInfo::default()
146            .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
147        unsafe { self.device.raw.begin_command_buffer(raw, &vk_info) }
148            .map_err(super::map_host_device_oom_err)?;
149        self.active = raw;
150        self.texture_stages_widened = self.device.texture_stages_widened();
151
152        Ok(())
153    }
154
155    unsafe fn end_encoding(&mut self) -> Result<super::CommandBuffer, crate::DeviceError> {
156        let raw = self.active;
157        self.active = vk::CommandBuffer::null();
158        unsafe { self.device.raw.end_command_buffer(raw) }.map_err(map_err)?;
159        fn map_err(err: vk::Result) -> crate::DeviceError {
160            // We don't use VK_KHR_video_encode_queue
161            // VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR
162            super::map_host_device_oom_err(err)
163        }
164        Ok(super::CommandBuffer {
165            raw,
166            texture_stages_widened: self.texture_stages_widened,
167        })
168    }
169
170    unsafe fn discard_encoding(&mut self) {
171        // Safe use requires this is not called in the "closed" state, so the buffer
172        // shouldn't be null. Assert this to make sure we're not pushing null
173        // buffers to the discard pile.
174        assert_ne!(self.active, vk::CommandBuffer::null());
175
176        self.discarded.push(self.active);
177        self.active = vk::CommandBuffer::null();
178    }
179
180    unsafe fn reset_all<I>(&mut self, cmd_bufs: I)
181    where
182        I: Iterator<Item = super::CommandBuffer>,
183    {
184        self.temp.clear();
185        self.free
186            .extend(cmd_bufs.into_iter().map(|cmd_buf| cmd_buf.raw));
187        self.free.append(&mut self.discarded);
188        // Delete framebuffers from the framebuffer cache
189        for (_, framebuffer) in self.framebuffers.drain() {
190            unsafe { self.device.raw.destroy_framebuffer(framebuffer, None) };
191        }
192        // After a burst of heavy frames the pool gives the driver back the
193        // command memory they took; see `pool_trim`.
194        let flags = if self.pool_trim.reset() {
195            vk::CommandPoolResetFlags::RELEASE_RESOURCES
196        } else {
197            vk::CommandPoolResetFlags::empty()
198        };
199        let _ = unsafe { self.device.raw.reset_command_pool(self.raw, flags) };
200    }
201
202    unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
203    where
204        T: Iterator<Item = crate::BufferBarrier<'a, super::Buffer>>,
205    {
206        //Note: this is done so that we never end up with empty stage flags
207        let mut src_stages = vk::PipelineStageFlags::TOP_OF_PIPE;
208        let mut dst_stages = vk::PipelineStageFlags::BOTTOM_OF_PIPE;
209        let vk_barriers = &mut self.temp.buffer_barriers;
210        vk_barriers.clear();
211
212        for bar in barriers {
213            let (src_stage, src_access) = conv::map_buffer_usage_to_barrier(bar.usage.from);
214            src_stages |= src_stage;
215            let (dst_stage, dst_access) = conv::map_buffer_usage_to_barrier(bar.usage.to);
216            dst_stages |= dst_stage;
217
218            vk_barriers.push(
219                vk::BufferMemoryBarrier::default()
220                    .buffer(bar.buffer.raw)
221                    .size(vk::WHOLE_SIZE)
222                    .src_access_mask(src_access)
223                    .dst_access_mask(dst_access),
224            )
225        }
226
227        if !vk_barriers.is_empty() {
228            unsafe {
229                self.device.raw.cmd_pipeline_barrier(
230                    self.active,
231                    src_stages,
232                    dst_stages,
233                    vk::DependencyFlags::empty(),
234                    &[],
235                    vk_barriers,
236                    &[],
237                )
238            };
239        }
240    }
241
242    unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
243    where
244        T: Iterator<Item = crate::TextureBarrier<'a, super::Texture>>,
245    {
246        let mut src_stages = vk::PipelineStageFlags::empty();
247        let mut dst_stages = vk::PipelineStageFlags::empty();
248        let vk_barriers = &mut self.temp.image_barriers;
249        vk_barriers.clear();
250        let shader_stages = conv::texture_shader_stages(self.texture_stages_widened);
251
252        for bar in barriers {
253            let range = conv::map_subresource_range_combined_aspect(
254                &bar.range,
255                bar.texture.format,
256                &self.device.private_caps,
257            );
258            let (src_stage, src_access) = conv::map_texture_usage_to_barrier(bar.usage.from, shader_stages);
259            let src_layout = conv::derive_image_layout(bar.usage.from, bar.texture.format);
260            src_stages |= src_stage;
261            let (dst_stage, dst_access) = conv::map_texture_usage_to_barrier(bar.usage.to, shader_stages);
262            let dst_layout = conv::derive_image_layout(bar.usage.to, bar.texture.format);
263            dst_stages |= dst_stage;
264
265            vk_barriers.push(
266                vk::ImageMemoryBarrier::default()
267                    .image(bar.texture.raw)
268                    .subresource_range(range)
269                    .src_access_mask(src_access)
270                    .dst_access_mask(dst_access)
271                    .old_layout(src_layout)
272                    .new_layout(dst_layout),
273            );
274        }
275
276        if !vk_barriers.is_empty() {
277            unsafe {
278                self.device.raw.cmd_pipeline_barrier(
279                    self.active,
280                    src_stages,
281                    dst_stages,
282                    vk::DependencyFlags::empty(),
283                    &[],
284                    &[],
285                    vk_barriers,
286                )
287            };
288        }
289    }
290
291    unsafe fn clear_buffer(&mut self, buffer: &super::Buffer, range: crate::MemoryRange) {
292        let range_size = range.end - range.start;
293        if self.device.workarounds.contains(
294            super::Workarounds::FORCE_FILL_BUFFER_WITH_SIZE_GREATER_4096_ALIGNED_OFFSET_16,
295        ) && range_size >= 4096
296            && !range.start.is_multiple_of(16)
297        {
298            let rounded_start = wgt::math::align_to(range.start, 16);
299            let prefix_size = rounded_start - range.start;
300
301            unsafe {
302                self.device.raw.cmd_fill_buffer(
303                    self.active,
304                    buffer.raw,
305                    range.start,
306                    prefix_size,
307                    0,
308                )
309            };
310
311            // This will never be zero, as rounding can only add up to 12 bytes, and the total size is 4096.
312            let suffix_size = range.end - rounded_start;
313
314            unsafe {
315                self.device.raw.cmd_fill_buffer(
316                    self.active,
317                    buffer.raw,
318                    rounded_start,
319                    suffix_size,
320                    0,
321                )
322            };
323        } else {
324            unsafe {
325                self.device
326                    .raw
327                    .cmd_fill_buffer(self.active, buffer.raw, range.start, range_size, 0)
328            };
329        }
330    }
331
332    unsafe fn copy_buffer_to_buffer<T>(
333        &mut self,
334        src: &super::Buffer,
335        dst: &super::Buffer,
336        regions: T,
337    ) where
338        T: Iterator<Item = crate::BufferCopy>,
339    {
340        let vk_regions_iter = regions.map(|r| vk::BufferCopy {
341            src_offset: r.src_offset,
342            dst_offset: r.dst_offset,
343            size: r.size.get(),
344        });
345
346        unsafe {
347            self.device.raw.cmd_copy_buffer(
348                self.active,
349                src.raw,
350                dst.raw,
351                &smallvec::SmallVec::<[vk::BufferCopy; 32]>::from_iter(vk_regions_iter),
352            )
353        };
354    }
355
356    unsafe fn copy_texture_to_texture<T>(
357        &mut self,
358        src: &super::Texture,
359        src_usage: wgt::TextureUses,
360        dst: &super::Texture,
361        regions: T,
362    ) where
363        T: Iterator<Item = crate::TextureCopy>,
364    {
365        let src_layout = conv::derive_image_layout(src_usage, src.format);
366
367        let vk_regions_iter = regions.map(|r| {
368            let (src_subresource, src_offset) = conv::map_subresource_layers(&r.src_base);
369            let (dst_subresource, dst_offset) = conv::map_subresource_layers(&r.dst_base);
370            let extent = r
371                .size
372                .min(&r.src_base.max_copy_size(&src.copy_size))
373                .min(&r.dst_base.max_copy_size(&dst.copy_size));
374            vk::ImageCopy {
375                src_subresource,
376                src_offset,
377                dst_subresource,
378                dst_offset,
379                extent: conv::map_copy_extent(&extent),
380            }
381        });
382
383        unsafe {
384            self.device.raw.cmd_copy_image(
385                self.active,
386                src.raw,
387                src_layout,
388                dst.raw,
389                DST_IMAGE_LAYOUT,
390                &smallvec::SmallVec::<[vk::ImageCopy; 32]>::from_iter(vk_regions_iter),
391            )
392        };
393    }
394
395    unsafe fn copy_buffer_to_texture<T>(
396        &mut self,
397        src: &super::Buffer,
398        dst: &super::Texture,
399        regions: T,
400    ) where
401        T: Iterator<Item = crate::BufferTextureCopy>,
402    {
403        let vk_regions_iter = dst.map_buffer_copies(regions);
404
405        unsafe {
406            self.device.raw.cmd_copy_buffer_to_image(
407                self.active,
408                src.raw,
409                dst.raw,
410                DST_IMAGE_LAYOUT,
411                &smallvec::SmallVec::<[vk::BufferImageCopy; 32]>::from_iter(vk_regions_iter),
412            )
413        };
414    }
415
416    unsafe fn copy_texture_to_buffer<T>(
417        &mut self,
418        src: &super::Texture,
419        src_usage: wgt::TextureUses,
420        dst: &super::Buffer,
421        regions: T,
422    ) where
423        T: Iterator<Item = crate::BufferTextureCopy>,
424    {
425        let src_layout = conv::derive_image_layout(src_usage, src.format);
426        let vk_regions_iter = src.map_buffer_copies(regions);
427
428        unsafe {
429            self.device.raw.cmd_copy_image_to_buffer(
430                self.active,
431                src.raw,
432                src_layout,
433                dst.raw,
434                &smallvec::SmallVec::<[vk::BufferImageCopy; 32]>::from_iter(vk_regions_iter),
435            )
436        };
437    }
438
439    unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {
440        unsafe {
441            self.device.raw.cmd_begin_query(
442                self.active,
443                set.raw,
444                index,
445                vk::QueryControlFlags::empty(),
446            )
447        };
448    }
449    unsafe fn end_query(&mut self, set: &super::QuerySet, index: u32) {
450        unsafe { self.device.raw.cmd_end_query(self.active, set.raw, index) };
451    }
452    unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {
453        unsafe {
454            self.device.raw.cmd_write_timestamp(
455                self.active,
456                vk::PipelineStageFlags::BOTTOM_OF_PIPE,
457                set.raw,
458                index,
459            )
460        };
461    }
462    unsafe fn read_acceleration_structure_compact_size(
463        &mut self,
464        acceleration_structure: &super::AccelerationStructure,
465        buffer: &super::Buffer,
466    ) {
467        let ray_tracing_functions = self
468            .device
469            .extension_fns
470            .ray_tracing
471            .as_ref()
472            .expect("Feature `RAY_TRACING` not enabled");
473        let query_pool = acceleration_structure
474            .compacted_size_query
475            .as_ref()
476            .unwrap();
477        unsafe {
478            self.device
479                .raw
480                .cmd_reset_query_pool(self.active, *query_pool, 0, 1);
481            ray_tracing_functions
482                .acceleration_structure
483                .cmd_write_acceleration_structures_properties(
484                    self.active,
485                    &[acceleration_structure.raw],
486                    vk::QueryType::ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
487                    *query_pool,
488                    0,
489                );
490            self.device.raw.cmd_copy_query_pool_results(
491                self.active,
492                *query_pool,
493                0,
494                1,
495                buffer.raw,
496                0,
497                wgt::QUERY_SIZE as vk::DeviceSize,
498                vk::QueryResultFlags::TYPE_64 | vk::QueryResultFlags::WAIT,
499            )
500        };
501    }
502    unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: Range<u32>) {
503        unsafe {
504            self.device.raw.cmd_reset_query_pool(
505                self.active,
506                set.raw,
507                range.start,
508                range.end - range.start,
509            )
510        };
511    }
512    unsafe fn copy_query_results(
513        &mut self,
514        set: &super::QuerySet,
515        range: Range<u32>,
516        buffer: &super::Buffer,
517        offset: wgt::BufferAddress,
518        stride: wgt::BufferSize,
519    ) {
520        unsafe {
521            self.device.raw.cmd_copy_query_pool_results(
522                self.active,
523                set.raw,
524                range.start,
525                range.end - range.start,
526                buffer.raw,
527                offset,
528                stride.get(),
529                vk::QueryResultFlags::TYPE_64 | vk::QueryResultFlags::WAIT,
530            )
531        };
532    }
533
534    unsafe fn build_acceleration_structures<'a, T>(&mut self, descriptor_count: u32, descriptors: T)
535    where
536        super::Api: 'a,
537        T: IntoIterator<
538            Item = crate::BuildAccelerationStructureDescriptor<
539                'a,
540                super::Buffer,
541                super::AccelerationStructure,
542            >,
543        >,
544    {
545        const CAPACITY_OUTER: usize = 8;
546        const CAPACITY_INNER: usize = 1;
547        let descriptor_count = descriptor_count as usize;
548
549        let ray_tracing_functions = self
550            .device
551            .extension_fns
552            .ray_tracing
553            .as_ref()
554            .expect("Feature `RAY_TRACING` not enabled");
555
556        let get_device_address = |buffer: Option<&super::Buffer>| unsafe {
557            match buffer {
558                Some(buffer) => ray_tracing_functions
559                    .buffer_device_address
560                    .get_buffer_device_address(
561                        &vk::BufferDeviceAddressInfo::default().buffer(buffer.raw),
562                    ),
563                None => panic!("Buffers are required to build acceleration structures"),
564            }
565        };
566
567        // storage to all the data required for cmd_build_acceleration_structures
568        let mut ranges_storage = smallvec::SmallVec::<
569            [smallvec::SmallVec<[vk::AccelerationStructureBuildRangeInfoKHR; CAPACITY_INNER]>;
570                CAPACITY_OUTER],
571        >::with_capacity(descriptor_count);
572        let mut geometries_storage = smallvec::SmallVec::<
573            [smallvec::SmallVec<[vk::AccelerationStructureGeometryKHR; CAPACITY_INNER]>;
574                CAPACITY_OUTER],
575        >::with_capacity(descriptor_count);
576
577        // pointers to all the data required for cmd_build_acceleration_structures
578        let mut geometry_infos = smallvec::SmallVec::<
579            [vk::AccelerationStructureBuildGeometryInfoKHR; CAPACITY_OUTER],
580        >::with_capacity(descriptor_count);
581        let mut ranges_ptrs = smallvec::SmallVec::<
582            [&[vk::AccelerationStructureBuildRangeInfoKHR]; CAPACITY_OUTER],
583        >::with_capacity(descriptor_count);
584
585        for desc in descriptors {
586            let (geometries, ranges) = match *desc.entries {
587                crate::AccelerationStructureEntries::Instances(ref instances) => {
588                    let instance_data = vk::AccelerationStructureGeometryInstancesDataKHR::default(
589                    // TODO: Code is so large that rustfmt refuses to treat this... :(
590                    )
591                    .data(vk::DeviceOrHostAddressConstKHR {
592                        device_address: get_device_address(instances.buffer),
593                    });
594
595                    let geometry = vk::AccelerationStructureGeometryKHR::default()
596                        .geometry_type(vk::GeometryTypeKHR::INSTANCES)
597                        .geometry(vk::AccelerationStructureGeometryDataKHR {
598                            instances: instance_data,
599                        });
600
601                    let range = vk::AccelerationStructureBuildRangeInfoKHR::default()
602                        .primitive_count(instances.count)
603                        .primitive_offset(instances.offset);
604
605                    (smallvec::smallvec![geometry], smallvec::smallvec![range])
606                }
607                crate::AccelerationStructureEntries::Triangles(ref in_geometries) => {
608                    let mut ranges = smallvec::SmallVec::<
609                        [vk::AccelerationStructureBuildRangeInfoKHR; CAPACITY_INNER],
610                    >::with_capacity(in_geometries.len());
611                    let mut geometries = smallvec::SmallVec::<
612                        [vk::AccelerationStructureGeometryKHR; CAPACITY_INNER],
613                    >::with_capacity(in_geometries.len());
614                    for triangles in in_geometries {
615                        let mut triangle_data =
616                            vk::AccelerationStructureGeometryTrianglesDataKHR::default()
617                                // IndexType::NONE_KHR is not set by default (due to being provided by VK_KHR_acceleration_structure) but unless there is an
618                                // index buffer we need to have IndexType::NONE_KHR as our index type.
619                                .index_type(vk::IndexType::NONE_KHR)
620                                .vertex_data(vk::DeviceOrHostAddressConstKHR {
621                                    device_address: get_device_address(triangles.vertex_buffer)
622                                        + (triangles.first_vertex as u64 * triangles.vertex_stride),
623                                })
624                                .vertex_format(conv::map_vertex_format(triangles.vertex_format))
625                                .max_vertex(triangles.vertex_count)
626                                .vertex_stride(triangles.vertex_stride);
627
628                        let mut range = vk::AccelerationStructureBuildRangeInfoKHR::default();
629
630                        if let Some(ref indices) = triangles.indices {
631                            triangle_data = triangle_data
632                                .index_data(vk::DeviceOrHostAddressConstKHR {
633                                    device_address: get_device_address(indices.buffer),
634                                })
635                                .index_type(conv::map_index_format(indices.format));
636
637                            range = range
638                                .primitive_count(indices.count / 3)
639                                .primitive_offset(indices.offset);
640                        } else {
641                            range = range.primitive_count(triangles.vertex_count / 3);
642                        }
643
644                        if let Some(ref transform) = triangles.transform {
645                            let transform_device_address = unsafe {
646                                ray_tracing_functions
647                                    .buffer_device_address
648                                    .get_buffer_device_address(
649                                        &vk::BufferDeviceAddressInfo::default()
650                                            .buffer(transform.buffer.raw),
651                                    )
652                            };
653                            triangle_data =
654                                triangle_data.transform_data(vk::DeviceOrHostAddressConstKHR {
655                                    device_address: transform_device_address,
656                                });
657
658                            range = range.transform_offset(transform.offset);
659                        }
660
661                        let geometry = vk::AccelerationStructureGeometryKHR::default()
662                            .geometry_type(vk::GeometryTypeKHR::TRIANGLES)
663                            .geometry(vk::AccelerationStructureGeometryDataKHR {
664                                triangles: triangle_data,
665                            })
666                            .flags(conv::map_acceleration_structure_geometry_flags(
667                                triangles.flags,
668                            ));
669
670                        geometries.push(geometry);
671                        ranges.push(range);
672                    }
673                    (geometries, ranges)
674                }
675                crate::AccelerationStructureEntries::AABBs(ref in_geometries) => {
676                    let mut ranges = smallvec::SmallVec::<
677                        [vk::AccelerationStructureBuildRangeInfoKHR; CAPACITY_INNER],
678                    >::with_capacity(in_geometries.len());
679                    let mut geometries = smallvec::SmallVec::<
680                        [vk::AccelerationStructureGeometryKHR; CAPACITY_INNER],
681                    >::with_capacity(in_geometries.len());
682                    for aabb in in_geometries {
683                        let aabbs_data = vk::AccelerationStructureGeometryAabbsDataKHR::default()
684                            .data(vk::DeviceOrHostAddressConstKHR {
685                                device_address: get_device_address(aabb.buffer),
686                            })
687                            .stride(aabb.stride);
688
689                        let range = vk::AccelerationStructureBuildRangeInfoKHR::default()
690                            .primitive_count(aabb.count)
691                            .primitive_offset(aabb.offset);
692
693                        let geometry = vk::AccelerationStructureGeometryKHR::default()
694                            .geometry_type(vk::GeometryTypeKHR::AABBS)
695                            .geometry(vk::AccelerationStructureGeometryDataKHR {
696                                aabbs: aabbs_data,
697                            })
698                            .flags(conv::map_acceleration_structure_geometry_flags(aabb.flags));
699
700                        geometries.push(geometry);
701                        ranges.push(range);
702                    }
703                    (geometries, ranges)
704                }
705            };
706
707            ranges_storage.push(ranges);
708            geometries_storage.push(geometries);
709
710            let scratch_device_address = unsafe {
711                ray_tracing_functions
712                    .buffer_device_address
713                    .get_buffer_device_address(
714                        &vk::BufferDeviceAddressInfo::default().buffer(desc.scratch_buffer.raw),
715                    )
716            };
717            let ty = match *desc.entries {
718                crate::AccelerationStructureEntries::Instances(_) => {
719                    vk::AccelerationStructureTypeKHR::TOP_LEVEL
720                }
721                _ => vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL,
722            };
723            let mut geometry_info = vk::AccelerationStructureBuildGeometryInfoKHR::default()
724                .ty(ty)
725                .mode(conv::map_acceleration_structure_build_mode(desc.mode))
726                .flags(conv::map_acceleration_structure_flags(desc.flags))
727                .dst_acceleration_structure(desc.destination_acceleration_structure.raw)
728                .scratch_data(vk::DeviceOrHostAddressKHR {
729                    device_address: scratch_device_address + desc.scratch_buffer_offset,
730                });
731
732            if desc.mode == crate::AccelerationStructureBuildMode::Update {
733                geometry_info.src_acceleration_structure = desc
734                    .source_acceleration_structure
735                    .unwrap_or(desc.destination_acceleration_structure)
736                    .raw;
737            }
738
739            geometry_infos.push(geometry_info);
740        }
741
742        for (i, geometry_info) in geometry_infos.iter_mut().enumerate() {
743            geometry_info.geometry_count = geometries_storage[i].len() as u32;
744            geometry_info.p_geometries = geometries_storage[i].as_ptr();
745            ranges_ptrs.push(&ranges_storage[i]);
746        }
747
748        unsafe {
749            ray_tracing_functions
750                .acceleration_structure
751                .cmd_build_acceleration_structures(self.active, &geometry_infos, &ranges_ptrs);
752        }
753    }
754
755    unsafe fn place_acceleration_structure_barrier(
756        &mut self,
757        barrier: crate::AccelerationStructureBarrier,
758    ) {
759        let (src_stage, src_access) = conv::map_acceleration_structure_usage_to_barrier(
760            barrier.usage.from,
761            self.device.features,
762        );
763        let (dst_stage, dst_access) = conv::map_acceleration_structure_usage_to_barrier(
764            barrier.usage.to,
765            self.device.features,
766        );
767
768        unsafe {
769            self.device.raw.cmd_pipeline_barrier(
770                self.active,
771                src_stage | vk::PipelineStageFlags::TOP_OF_PIPE,
772                dst_stage | vk::PipelineStageFlags::BOTTOM_OF_PIPE,
773                vk::DependencyFlags::empty(),
774                &[vk::MemoryBarrier::default()
775                    .src_access_mask(src_access)
776                    .dst_access_mask(dst_access)],
777                &[],
778                &[],
779            )
780        };
781    }
782
783    unsafe fn set_acceleration_structure_dependencies(
784        _command_buffers: &[&super::CommandBuffer],
785        _dependencies: &[&super::AccelerationStructure],
786    ) {
787    }
788    // render
789
790    unsafe fn begin_render_pass(
791        &mut self,
792        desc: &crate::RenderPassDescriptor<super::QuerySet, super::TextureView>,
793    ) -> Result<(), crate::DeviceError> {
794        self.pool_trim.begin_render_pass();
795        let mut vk_clear_values =
796            ArrayVec::<vk::ClearValue, { super::MAX_TOTAL_ATTACHMENTS }>::new();
797        let mut rp_key = super::RenderPassKey {
798            colors: ArrayVec::default(),
799            depth_stencil: None,
800            sample_count: desc.sample_count,
801            multiview_mask: desc.multiview_mask,
802        };
803        let mut fb_key = super::FramebufferKey {
804            raw_pass: vk::RenderPass::null(),
805            attachment_views: ArrayVec::default(),
806            attachment_identities: ArrayVec::default(),
807            extent: desc.extent,
808        };
809
810        for cat in desc.color_attachments {
811            if let Some(cat) = cat.as_ref() {
812                let color_view = if cat.target.view.dimension == wgt::TextureViewDimension::D3 {
813                    let key = super::TempTextureViewKey {
814                        texture: cat.target.view.raw_texture,
815                        texture_identity: cat.target.view.texture_identity,
816                        format: cat.target.view.raw_format,
817                        mip_level: cat.target.view.base_mip_level,
818                        depth_slice: cat.depth_slice.unwrap(),
819                    };
820                    self.make_temp_texture_view(key)?
821                } else {
822                    cat.target.view.identified_raw_view()
823                };
824
825                vk_clear_values.push(vk::ClearValue {
826                    color: unsafe { cat.make_vk_clear_color() },
827                });
828                let color = super::ColorAttachmentKey {
829                    base: cat.target.make_attachment_key(cat.ops),
830                    resolve: cat.resolve_target.as_ref().map(|target| {
831                        target.make_attachment_key(
832                            crate::AttachmentOps::LOAD_CLEAR | crate::AttachmentOps::STORE,
833                        )
834                    }),
835                };
836
837                rp_key.colors.push(Some(color));
838                fb_key.push_view(color_view);
839                if let Some(ref at) = cat.resolve_target {
840                    vk_clear_values.push(unsafe { mem::zeroed() });
841                    fb_key.push_view(at.view.identified_raw_view());
842                }
843            } else {
844                rp_key.colors.push(None);
845            }
846        }
847        if let Some(ref ds) = desc.depth_stencil_attachment {
848            vk_clear_values.push(vk::ClearValue {
849                depth_stencil: vk::ClearDepthStencilValue {
850                    depth: ds.clear_value.0,
851                    stencil: ds.clear_value.1,
852                },
853            });
854            rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
855                base: ds.target.make_attachment_key(ds.depth_ops),
856                stencil_ops: ds.stencil_ops,
857            });
858            fb_key.push_view(ds.target.view.identified_raw_view());
859        }
860
861        let render_area = vk::Rect2D {
862            offset: vk::Offset2D { x: 0, y: 0 },
863            extent: vk::Extent2D {
864                width: desc.extent.width,
865                height: desc.extent.height,
866            },
867        };
868        let vk_viewports = [vk::Viewport {
869            x: 0.0,
870            y: desc.extent.height as f32,
871            width: desc.extent.width as f32,
872            height: -(desc.extent.height as f32),
873            min_depth: 0.0,
874            max_depth: 1.0,
875        }];
876
877        let raw_pass = self.device.make_render_pass(rp_key).unwrap();
878        fb_key.raw_pass = raw_pass;
879        let raw_framebuffer = self.make_framebuffer(fb_key).unwrap();
880
881        let vk_info = vk::RenderPassBeginInfo::default()
882            .render_pass(raw_pass)
883            .render_area(render_area)
884            .clear_values(&vk_clear_values)
885            .framebuffer(raw_framebuffer);
886
887        if let Some(label) = desc.label {
888            unsafe { self.begin_debug_marker(label) };
889            self.rpass_debug_marker_active = true;
890        }
891
892        // Start timestamp if any (before all other commands but after debug marker)
893        if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() {
894            if let Some(index) = timestamp_writes.beginning_of_pass_write_index {
895                unsafe {
896                    self.write_timestamp(timestamp_writes.query_set, index);
897                }
898            }
899            self.end_of_pass_timer_query = timestamp_writes
900                .end_of_pass_write_index
901                .map(|index| (timestamp_writes.query_set.raw, index));
902        }
903
904        unsafe {
905            self.device
906                .raw
907                .cmd_set_viewport(self.active, 0, &vk_viewports);
908            self.device
909                .raw
910                .cmd_set_scissor(self.active, 0, &[render_area]);
911            self.device.raw.cmd_begin_render_pass(
912                self.active,
913                &vk_info,
914                vk::SubpassContents::INLINE,
915            );
916        };
917
918        self.bind_point = vk::PipelineBindPoint::GRAPHICS;
919
920        Ok(())
921    }
922    unsafe fn end_render_pass(&mut self) {
923        unsafe {
924            self.device.raw.cmd_end_render_pass(self.active);
925        }
926
927        // After all other commands but before debug marker, so this is still seen as part of this pass.
928        self.write_pass_end_timestamp_if_requested();
929
930        if self.rpass_debug_marker_active {
931            unsafe {
932                self.end_debug_marker();
933            }
934            self.rpass_debug_marker_active = false;
935        }
936    }
937
938    unsafe fn set_bind_group(
939        &mut self,
940        layout: &super::PipelineLayout,
941        index: u32,
942        group: &super::BindGroup,
943        dynamic_offsets: &[wgt::DynamicOffset],
944    ) {
945        let sets = [group.set.raw()];
946        unsafe {
947            self.device.raw.cmd_bind_descriptor_sets(
948                self.active,
949                self.bind_point,
950                layout.raw,
951                index,
952                &sets,
953                dynamic_offsets,
954            )
955        };
956    }
957    unsafe fn set_immediates(
958        &mut self,
959        layout: &super::PipelineLayout,
960        offset_bytes: u32,
961        data: &[u32],
962    ) {
963        unsafe {
964            self.device.raw.cmd_push_constants(
965                self.active,
966                layout.raw,
967                vk::ShaderStageFlags::ALL,
968                offset_bytes,
969                bytemuck::cast_slice(data),
970            )
971        };
972    }
973
974    unsafe fn insert_debug_marker(&mut self, label: &str) {
975        if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
976            let cstr = self.temp.make_c_str(label);
977            let vk_label = vk::DebugUtilsLabelEXT::default().label_name(cstr);
978            unsafe { ext.cmd_insert_debug_utils_label(self.active, &vk_label) };
979        }
980    }
981    unsafe fn begin_debug_marker(&mut self, group_label: &str) {
982        if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
983            let cstr = self.temp.make_c_str(group_label);
984            let vk_label = vk::DebugUtilsLabelEXT::default().label_name(cstr);
985            unsafe { ext.cmd_begin_debug_utils_label(self.active, &vk_label) };
986        }
987    }
988    unsafe fn end_debug_marker(&mut self) {
989        if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
990            unsafe { ext.cmd_end_debug_utils_label(self.active) };
991        }
992    }
993
994    unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
995        unsafe {
996            self.current_pipeline_is_multiview = pipeline.is_multiview;
997            self.device.raw.cmd_bind_pipeline(
998                self.active,
999                vk::PipelineBindPoint::GRAPHICS,
1000                pipeline.raw,
1001            )
1002        };
1003    }
1004
1005    unsafe fn set_index_buffer<'a>(
1006        &mut self,
1007        binding: crate::BufferBinding<'a, super::Buffer>,
1008        format: wgt::IndexFormat,
1009    ) {
1010        unsafe {
1011            self.device.raw.cmd_bind_index_buffer(
1012                self.active,
1013                binding.buffer.raw,
1014                binding.offset,
1015                conv::map_index_format(format),
1016            )
1017        };
1018    }
1019    unsafe fn set_vertex_buffer<'a>(
1020        &mut self,
1021        index: u32,
1022        binding: crate::BufferBinding<'a, super::Buffer>,
1023    ) {
1024        let vk_buffers = [binding.buffer.raw];
1025        let vk_offsets = [binding.offset];
1026        unsafe {
1027            self.device
1028                .raw
1029                .cmd_bind_vertex_buffers(self.active, index, &vk_buffers, &vk_offsets)
1030        };
1031    }
1032    unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth_range: Range<f32>) {
1033        let vk_viewports = [vk::Viewport {
1034            x: rect.x,
1035            y: rect.y + rect.h,
1036            width: rect.w,
1037            height: -rect.h, // flip Y
1038            min_depth: depth_range.start,
1039            max_depth: depth_range.end,
1040        }];
1041        unsafe {
1042            self.device
1043                .raw
1044                .cmd_set_viewport(self.active, 0, &vk_viewports)
1045        };
1046    }
1047    unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {
1048        let vk_scissors = [vk::Rect2D {
1049            offset: vk::Offset2D {
1050                x: rect.x as i32,
1051                y: rect.y as i32,
1052            },
1053            extent: vk::Extent2D {
1054                width: rect.w,
1055                height: rect.h,
1056            },
1057        }];
1058        unsafe {
1059            self.device
1060                .raw
1061                .cmd_set_scissor(self.active, 0, &vk_scissors)
1062        };
1063    }
1064    unsafe fn set_stencil_reference(&mut self, value: u32) {
1065        unsafe {
1066            self.device.raw.cmd_set_stencil_reference(
1067                self.active,
1068                vk::StencilFaceFlags::FRONT_AND_BACK,
1069                value,
1070            )
1071        };
1072    }
1073    unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {
1074        unsafe { self.device.raw.cmd_set_blend_constants(self.active, color) };
1075    }
1076
1077    unsafe fn draw(
1078        &mut self,
1079        first_vertex: u32,
1080        vertex_count: u32,
1081        first_instance: u32,
1082        instance_count: u32,
1083    ) {
1084        if self.current_pipeline_is_multiview
1085            && (first_instance as u64 + instance_count as u64 - 1)
1086                > self.device.private_caps.multiview_instance_index_limit as u64
1087        {
1088            panic!("This vulkan device is affected by [#8333](https://github.com/gfx-rs/wgpu/issues/8333)");
1089        }
1090        unsafe {
1091            self.device.raw.cmd_draw(
1092                self.active,
1093                vertex_count,
1094                instance_count,
1095                first_vertex,
1096                first_instance,
1097            )
1098        };
1099    }
1100    unsafe fn draw_indexed(
1101        &mut self,
1102        first_index: u32,
1103        index_count: u32,
1104        base_vertex: i32,
1105        first_instance: u32,
1106        instance_count: u32,
1107    ) {
1108        if self.current_pipeline_is_multiview
1109            && (first_instance as u64 + instance_count as u64 - 1)
1110                > self.device.private_caps.multiview_instance_index_limit as u64
1111        {
1112            panic!("This vulkan device is affected by [#8333](https://github.com/gfx-rs/wgpu/issues/8333)");
1113        }
1114        unsafe {
1115            self.device.raw.cmd_draw_indexed(
1116                self.active,
1117                index_count,
1118                instance_count,
1119                first_index,
1120                base_vertex,
1121                first_instance,
1122            )
1123        };
1124    }
1125    unsafe fn draw_mesh_tasks(
1126        &mut self,
1127        group_count_x: u32,
1128        group_count_y: u32,
1129        group_count_z: u32,
1130    ) {
1131        if let Some(ref t) = self.device.extension_fns.mesh_shading {
1132            unsafe {
1133                t.cmd_draw_mesh_tasks(self.active, group_count_x, group_count_y, group_count_z);
1134            };
1135        } else {
1136            panic!("Feature `MESH_SHADING` not enabled");
1137        }
1138    }
1139    unsafe fn draw_indirect(
1140        &mut self,
1141        buffer: &super::Buffer,
1142        offset: wgt::BufferAddress,
1143        draw_count: u32,
1144    ) {
1145        if draw_count >= 1
1146            && self.device.private_caps.multi_draw_indirect
1147            && draw_count <= self.device.private_caps.max_draw_indirect_count
1148        {
1149            unsafe {
1150                self.device.raw.cmd_draw_indirect(
1151                    self.active,
1152                    buffer.raw,
1153                    offset,
1154                    draw_count,
1155                    size_of::<wgt::DrawIndirectArgs>() as u32,
1156                )
1157            };
1158        } else {
1159            for i in 0..draw_count {
1160                let indirect_offset = offset
1161                    + i as wgt::BufferAddress
1162                        * size_of::<wgt::DrawIndirectArgs>() as wgt::BufferAddress;
1163                unsafe {
1164                    self.device.raw.cmd_draw_indirect(
1165                        self.active,
1166                        buffer.raw,
1167                        indirect_offset,
1168                        1,
1169                        size_of::<wgt::DrawIndirectArgs>() as u32,
1170                    )
1171                };
1172            }
1173        }
1174    }
1175    unsafe fn draw_indexed_indirect(
1176        &mut self,
1177        buffer: &super::Buffer,
1178        offset: wgt::BufferAddress,
1179        draw_count: u32,
1180    ) {
1181        if draw_count >= 1
1182            && self.device.private_caps.multi_draw_indirect
1183            && draw_count <= self.device.private_caps.max_draw_indirect_count
1184        {
1185            unsafe {
1186                self.device.raw.cmd_draw_indexed_indirect(
1187                    self.active,
1188                    buffer.raw,
1189                    offset,
1190                    draw_count,
1191                    size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
1192                )
1193            };
1194        } else {
1195            for i in 0..draw_count {
1196                let indirect_offset = offset
1197                    + i as wgt::BufferAddress
1198                        * size_of::<wgt::DrawIndexedIndirectArgs>() as wgt::BufferAddress;
1199                unsafe {
1200                    self.device.raw.cmd_draw_indexed_indirect(
1201                        self.active,
1202                        buffer.raw,
1203                        indirect_offset,
1204                        1,
1205                        size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
1206                    )
1207                };
1208            }
1209        }
1210    }
1211    unsafe fn draw_mesh_tasks_indirect(
1212        &mut self,
1213        buffer: &<Self::A as crate::Api>::Buffer,
1214        offset: wgt::BufferAddress,
1215        draw_count: u32,
1216    ) {
1217        if let Some(ref t) = self.device.extension_fns.mesh_shading {
1218            unsafe {
1219                t.cmd_draw_mesh_tasks_indirect(
1220                    self.active,
1221                    buffer.raw,
1222                    offset,
1223                    draw_count,
1224                    size_of::<wgt::DispatchIndirectArgs>() as u32,
1225                );
1226            };
1227        } else {
1228            panic!("Feature `MESH_SHADING` not enabled");
1229        }
1230    }
1231    unsafe fn draw_indirect_count(
1232        &mut self,
1233        buffer: &super::Buffer,
1234        offset: wgt::BufferAddress,
1235        count_buffer: &super::Buffer,
1236        count_offset: wgt::BufferAddress,
1237        max_count: u32,
1238    ) {
1239        let stride = size_of::<wgt::DrawIndirectArgs>() as u32;
1240        match self.device.extension_fns.draw_indirect_count {
1241            Some(ref t) => {
1242                unsafe {
1243                    t.cmd_draw_indirect_count(
1244                        self.active,
1245                        buffer.raw,
1246                        offset,
1247                        count_buffer.raw,
1248                        count_offset,
1249                        max_count,
1250                        stride,
1251                    )
1252                };
1253            }
1254            None => panic!("Feature `DRAW_INDIRECT_COUNT` not enabled"),
1255        }
1256    }
1257    unsafe fn draw_indexed_indirect_count(
1258        &mut self,
1259        buffer: &super::Buffer,
1260        offset: wgt::BufferAddress,
1261        count_buffer: &super::Buffer,
1262        count_offset: wgt::BufferAddress,
1263        max_count: u32,
1264    ) {
1265        let stride = size_of::<wgt::DrawIndexedIndirectArgs>() as u32;
1266        match self.device.extension_fns.draw_indirect_count {
1267            Some(ref t) => {
1268                unsafe {
1269                    t.cmd_draw_indexed_indirect_count(
1270                        self.active,
1271                        buffer.raw,
1272                        offset,
1273                        count_buffer.raw,
1274                        count_offset,
1275                        max_count,
1276                        stride,
1277                    )
1278                };
1279            }
1280            None => panic!("Feature `DRAW_INDIRECT_COUNT` not enabled"),
1281        }
1282    }
1283    unsafe fn draw_mesh_tasks_indirect_count(
1284        &mut self,
1285        buffer: &<Self::A as crate::Api>::Buffer,
1286        offset: wgt::BufferAddress,
1287        count_buffer: &super::Buffer,
1288        count_offset: wgt::BufferAddress,
1289        max_count: u32,
1290    ) {
1291        if self.device.extension_fns.draw_indirect_count.is_none() {
1292            panic!("Feature `DRAW_INDIRECT_COUNT` not enabled");
1293        }
1294        if let Some(ref t) = self.device.extension_fns.mesh_shading {
1295            unsafe {
1296                t.cmd_draw_mesh_tasks_indirect_count(
1297                    self.active,
1298                    buffer.raw,
1299                    offset,
1300                    count_buffer.raw,
1301                    count_offset,
1302                    max_count,
1303                    size_of::<wgt::DispatchIndirectArgs>() as u32,
1304                );
1305            };
1306        } else {
1307            panic!("Feature `MESH_SHADING` not enabled");
1308        }
1309    }
1310
1311    // compute
1312
1313    unsafe fn begin_compute_pass(
1314        &mut self,
1315        desc: &crate::ComputePassDescriptor<'_, super::QuerySet>,
1316    ) {
1317        self.bind_point = vk::PipelineBindPoint::COMPUTE;
1318        if let Some(label) = desc.label {
1319            unsafe { self.begin_debug_marker(label) };
1320            self.rpass_debug_marker_active = true;
1321        }
1322
1323        if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() {
1324            if let Some(index) = timestamp_writes.beginning_of_pass_write_index {
1325                unsafe {
1326                    self.write_timestamp(timestamp_writes.query_set, index);
1327                }
1328            }
1329            self.end_of_pass_timer_query = timestamp_writes
1330                .end_of_pass_write_index
1331                .map(|index| (timestamp_writes.query_set.raw, index));
1332        }
1333    }
1334    unsafe fn end_compute_pass(&mut self) {
1335        self.write_pass_end_timestamp_if_requested();
1336
1337        if self.rpass_debug_marker_active {
1338            unsafe { self.end_debug_marker() };
1339            self.rpass_debug_marker_active = false
1340        }
1341    }
1342
1343    unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
1344        unsafe {
1345            self.device.raw.cmd_bind_pipeline(
1346                self.active,
1347                vk::PipelineBindPoint::COMPUTE,
1348                pipeline.raw,
1349            )
1350        };
1351    }
1352
1353    unsafe fn dispatch_workgroups(&mut self, count: [u32; 3]) {
1354        unsafe {
1355            self.device
1356                .raw
1357                .cmd_dispatch(self.active, count[0], count[1], count[2])
1358        };
1359    }
1360    unsafe fn dispatch_workgroups_indirect(
1361        &mut self,
1362        buffer: &super::Buffer,
1363        offset: wgt::BufferAddress,
1364    ) {
1365        unsafe {
1366            self.device
1367                .raw
1368                .cmd_dispatch_indirect(self.active, buffer.raw, offset)
1369        }
1370    }
1371
1372    // ray tracing
1373
1374    unsafe fn begin_ray_tracing_pass(&mut self, desc: &crate::RayTracingPassDescriptor<'_>) {
1375        self.bind_point = vk::PipelineBindPoint::RAY_TRACING_KHR;
1376        if let Some(label) = desc.label {
1377            unsafe { self.begin_debug_marker(label) };
1378            self.rpass_debug_marker_active = true;
1379        }
1380    }
1381    unsafe fn end_ray_tracing_pass(&mut self) {
1382        if self.rpass_debug_marker_active {
1383            unsafe { self.end_debug_marker() };
1384            self.rpass_debug_marker_active = false
1385        }
1386    }
1387
1388    unsafe fn trace_rays(
1389        &mut self,
1390        count: [u32; 3],
1391        ray_generation_group_data: crate::PipelineGroupData<super::Buffer>,
1392        miss_group_data: crate::PipelineGroupData<super::Buffer>,
1393        intersection_group_data: crate::PipelineGroupData<super::Buffer>,
1394    ) {
1395        let ray_tracing_functions = self
1396            .device
1397            .extension_fns
1398            .ray_tracing
1399            .as_ref()
1400            .expect("Feature `EXPERIMENTAL_RAY_TRACING` not enabled");
1401
1402        let ray_tracing_pipeline_functions = self
1403            .device
1404            .extension_fns
1405            .ray_tracing_pipelines
1406            .as_ref()
1407            .expect("Feature `EXPERIMENTAL_RAY_TRACING_PIPELINES` not enabled");
1408
1409        let get_device_address = |buffer: &super::Buffer| unsafe {
1410            ray_tracing_functions
1411                .buffer_device_address
1412                .get_buffer_device_address(
1413                    &vk::BufferDeviceAddressInfo::default().buffer(buffer.raw),
1414                )
1415        };
1416
1417        unsafe {
1418            ray_tracing_pipeline_functions.cmd_trace_rays(
1419                self.raw_handle(),
1420                &vk::StridedDeviceAddressRegionKHR {
1421                    device_address: get_device_address(ray_generation_group_data.buffer)
1422                        + ray_generation_group_data.offset,
1423                    stride: ray_generation_group_data.stride,
1424                    size: ray_generation_group_data.stride /* no need for multiplying by count, vulkan requires the ray gen sbt to be just one group */,
1425                },
1426                &vk::StridedDeviceAddressRegionKHR {
1427                    device_address: get_device_address(miss_group_data.buffer)
1428                        + miss_group_data.offset,
1429                    stride: miss_group_data.stride,
1430                    size: miss_group_data.stride * miss_group_data.count,
1431                },
1432                &vk::StridedDeviceAddressRegionKHR {
1433                    device_address: get_device_address(intersection_group_data.buffer)
1434                        + intersection_group_data.offset,
1435                    stride: intersection_group_data.stride,
1436                    size: intersection_group_data.stride * intersection_group_data.count,
1437                },
1438                &vk::StridedDeviceAddressRegionKHR {
1439                    device_address: 0,
1440                    stride: 0,
1441                    size: 0,
1442                },
1443                count[0],
1444                count[1],
1445                count[2],
1446            )
1447        };
1448    }
1449
1450    unsafe fn set_ray_tracing_pipeline(&mut self, pipeline: &super::RayTracingPipeline) {
1451        unsafe {
1452            self.device.raw.cmd_bind_pipeline(
1453                self.active,
1454                vk::PipelineBindPoint::RAY_TRACING_KHR,
1455                pipeline.raw,
1456            )
1457        };
1458    }
1459
1460    unsafe fn copy_acceleration_structure_to_acceleration_structure(
1461        &mut self,
1462        src: &super::AccelerationStructure,
1463        dst: &super::AccelerationStructure,
1464        copy: wgt::AccelerationStructureCopy,
1465    ) {
1466        let ray_tracing_functions = self
1467            .device
1468            .extension_fns
1469            .ray_tracing
1470            .as_ref()
1471            .expect("Feature `RAY_TRACING` not enabled");
1472
1473        let mode = match copy {
1474            wgt::AccelerationStructureCopy::Clone => vk::CopyAccelerationStructureModeKHR::CLONE,
1475            wgt::AccelerationStructureCopy::Compact => {
1476                vk::CopyAccelerationStructureModeKHR::COMPACT
1477            }
1478        };
1479
1480        unsafe {
1481            ray_tracing_functions
1482                .acceleration_structure
1483                .cmd_copy_acceleration_structure(
1484                    self.active,
1485                    &vk::CopyAccelerationStructureInfoKHR {
1486                        s_type: vk::StructureType::COPY_ACCELERATION_STRUCTURE_INFO_KHR,
1487                        p_next: core::ptr::null(),
1488                        src: src.raw,
1489                        dst: dst.raw,
1490                        mode,
1491                        _marker: Default::default(),
1492                    },
1493                );
1494        }
1495    }
1496}
1497
1498#[test]
1499fn check_dst_image_layout() {
1500    assert_eq!(
1501        conv::derive_image_layout(wgt::TextureUses::COPY_DST, wgt::TextureFormat::Rgba8Unorm),
1502        DST_IMAGE_LAYOUT
1503    );
1504}