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