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