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