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