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 = [vk::Viewport {
906 x: 0.0,
907 y: desc.extent.height as f32,
908 width: desc.extent.width as f32,
909 height: -(desc.extent.height as f32),
910 min_depth: 0.0,
911 max_depth: 1.0,
912 }];
913
914 let raw_pass = self.device.make_render_pass(rp_key).unwrap();
915 fb_key.raw_pass = raw_pass;
916 let raw_framebuffer = self.make_framebuffer(fb_key).unwrap();
917
918 let vk_info = vk::RenderPassBeginInfo::default()
919 .render_pass(raw_pass)
920 .render_area(render_area)
921 .clear_values(&vk_clear_values)
922 .framebuffer(raw_framebuffer);
923
924 if let Some(label) = desc.label {
925 unsafe { self.begin_debug_marker(label) };
926 self.rpass_debug_marker_active = true;
927 }
928
929 if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() {
931 if let Some(index) = timestamp_writes.beginning_of_pass_write_index {
932 unsafe {
933 self.write_timestamp(timestamp_writes.query_set, index);
934 }
935 }
936 self.end_of_pass_timer_query = timestamp_writes
937 .end_of_pass_write_index
938 .map(|index| (timestamp_writes.query_set.raw, index));
939 }
940
941 unsafe {
942 self.device
943 .raw
944 .cmd_set_viewport(self.active, 0, &vk_viewports);
945 self.device
946 .raw
947 .cmd_set_scissor(self.active, 0, &[render_area]);
948 self.device.raw.cmd_begin_render_pass(
949 self.active,
950 &vk_info,
951 vk::SubpassContents::INLINE,
952 );
953 };
954
955 self.bind_point = vk::PipelineBindPoint::GRAPHICS;
956
957 Ok(())
958 }
959 unsafe fn end_render_pass(&mut self) {
960 unsafe {
961 self.device.raw.cmd_end_render_pass(self.active);
962 }
963
964 self.write_pass_end_timestamp_if_requested();
966
967 if self.rpass_debug_marker_active {
968 unsafe {
969 self.end_debug_marker();
970 }
971 self.rpass_debug_marker_active = false;
972 }
973 }
974
975 unsafe fn set_bind_group(
976 &mut self,
977 layout: &super::PipelineLayout,
978 index: u32,
979 group: &super::BindGroup,
980 dynamic_offsets: &[wgt::DynamicOffset],
981 ) {
982 let sets = [group.set.raw()];
983 unsafe {
984 self.device.raw.cmd_bind_descriptor_sets(
985 self.active,
986 self.bind_point,
987 layout.raw,
988 index,
989 &sets,
990 dynamic_offsets,
991 )
992 };
993 }
994 unsafe fn set_immediates(
995 &mut self,
996 layout: &super::PipelineLayout,
997 offset_bytes: u32,
998 data: &[u32],
999 ) {
1000 unsafe {
1001 self.device.raw.cmd_push_constants(
1002 self.active,
1003 layout.raw,
1004 vk::ShaderStageFlags::ALL,
1005 offset_bytes,
1006 bytemuck::cast_slice(data),
1007 )
1008 };
1009 }
1010
1011 unsafe fn insert_debug_marker(&mut self, label: &str) {
1012 if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
1013 let cstr = self.temp.make_c_str(label);
1014 let vk_label = vk::DebugUtilsLabelEXT::default().label_name(cstr);
1015 unsafe { ext.cmd_insert_debug_utils_label(self.active, &vk_label) };
1016 }
1017 }
1018 unsafe fn begin_debug_marker(&mut self, group_label: &str) {
1019 if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
1020 let cstr = self.temp.make_c_str(group_label);
1021 let vk_label = vk::DebugUtilsLabelEXT::default().label_name(cstr);
1022 unsafe { ext.cmd_begin_debug_utils_label(self.active, &vk_label) };
1023 }
1024 }
1025 unsafe fn end_debug_marker(&mut self) {
1026 if let Some(ext) = self.device.extension_fns.debug_utils.as_ref() {
1027 unsafe { ext.cmd_end_debug_utils_label(self.active) };
1028 }
1029 }
1030
1031 unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
1032 unsafe {
1033 self.current_pipeline_is_multiview = pipeline.is_multiview;
1034 self.device.raw.cmd_bind_pipeline(
1035 self.active,
1036 vk::PipelineBindPoint::GRAPHICS,
1037 pipeline.raw,
1038 )
1039 };
1040 }
1041
1042 unsafe fn set_index_buffer<'a>(
1043 &mut self,
1044 binding: crate::BufferBinding<'a, super::Buffer, wgt::BufferAddress>,
1045 format: wgt::IndexFormat,
1046 ) {
1047 unsafe {
1048 self.device.raw.cmd_bind_index_buffer(
1049 self.active,
1050 binding.buffer.raw,
1051 binding.offset,
1052 conv::map_index_format(format),
1053 )
1054 };
1055 }
1056 unsafe fn set_vertex_buffer<'a>(
1057 &mut self,
1058 index: u32,
1059 binding: crate::BufferBinding<'a, super::Buffer, wgt::BufferAddress>,
1060 ) {
1061 let vk_buffers = [binding.buffer.raw];
1062 let vk_offsets = [binding.offset];
1063 unsafe {
1064 self.device
1065 .raw
1066 .cmd_bind_vertex_buffers(self.active, index, &vk_buffers, &vk_offsets)
1067 };
1068 }
1069 unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth_range: Range<f32>) {
1070 let vk_viewports = [vk::Viewport {
1071 x: rect.x,
1072 y: rect.y + rect.h,
1073 width: rect.w,
1074 height: -rect.h, min_depth: depth_range.start,
1076 max_depth: depth_range.end,
1077 }];
1078 unsafe {
1079 self.device
1080 .raw
1081 .cmd_set_viewport(self.active, 0, &vk_viewports)
1082 };
1083 }
1084 unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {
1085 let vk_scissors = [vk::Rect2D {
1086 offset: vk::Offset2D {
1087 x: rect.x as i32,
1088 y: rect.y as i32,
1089 },
1090 extent: vk::Extent2D {
1091 width: rect.w,
1092 height: rect.h,
1093 },
1094 }];
1095 unsafe {
1096 self.device
1097 .raw
1098 .cmd_set_scissor(self.active, 0, &vk_scissors)
1099 };
1100 }
1101 unsafe fn set_stencil_reference(&mut self, value: u32) {
1102 unsafe {
1103 self.device.raw.cmd_set_stencil_reference(
1104 self.active,
1105 vk::StencilFaceFlags::FRONT_AND_BACK,
1106 value,
1107 )
1108 };
1109 }
1110 unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {
1111 unsafe { self.device.raw.cmd_set_blend_constants(self.active, color) };
1112 }
1113
1114 unsafe fn draw(
1115 &mut self,
1116 first_vertex: u32,
1117 vertex_count: u32,
1118 first_instance: u32,
1119 instance_count: u32,
1120 ) {
1121 if self.current_pipeline_is_multiview
1122 && (first_instance as u64 + instance_count as u64 - 1)
1123 > self.device.private_caps.multiview_instance_index_limit as u64
1124 {
1125 panic!("This vulkan device is affected by [#8333](https://github.com/gfx-rs/wgpu/issues/8333)");
1126 }
1127 unsafe {
1128 self.device.raw.cmd_draw(
1129 self.active,
1130 vertex_count,
1131 instance_count,
1132 first_vertex,
1133 first_instance,
1134 )
1135 };
1136 }
1137 unsafe fn draw_indexed(
1138 &mut self,
1139 first_index: u32,
1140 index_count: u32,
1141 base_vertex: i32,
1142 first_instance: u32,
1143 instance_count: u32,
1144 ) {
1145 if self.current_pipeline_is_multiview
1146 && (first_instance as u64 + instance_count as u64 - 1)
1147 > self.device.private_caps.multiview_instance_index_limit as u64
1148 {
1149 panic!("This vulkan device is affected by [#8333](https://github.com/gfx-rs/wgpu/issues/8333)");
1150 }
1151 unsafe {
1152 self.device.raw.cmd_draw_indexed(
1153 self.active,
1154 index_count,
1155 instance_count,
1156 first_index,
1157 base_vertex,
1158 first_instance,
1159 )
1160 };
1161 }
1162 unsafe fn draw_mesh_tasks(
1163 &mut self,
1164 group_count_x: u32,
1165 group_count_y: u32,
1166 group_count_z: u32,
1167 ) {
1168 if let Some(ref t) = self.device.extension_fns.mesh_shading {
1169 unsafe {
1170 t.cmd_draw_mesh_tasks(self.active, group_count_x, group_count_y, group_count_z);
1171 };
1172 } else {
1173 panic!("Feature `MESH_SHADING` not enabled");
1174 }
1175 }
1176 unsafe fn draw_indirect(
1177 &mut self,
1178 buffer: &super::Buffer,
1179 offset: wgt::BufferAddress,
1180 draw_count: u32,
1181 ) {
1182 if draw_count >= 1
1183 && self.device.private_caps.multi_draw_indirect
1184 && draw_count <= self.device.private_caps.max_draw_indirect_count
1185 {
1186 unsafe {
1187 self.device.raw.cmd_draw_indirect(
1188 self.active,
1189 buffer.raw,
1190 offset,
1191 draw_count,
1192 size_of::<wgt::DrawIndirectArgs>() as u32,
1193 )
1194 };
1195 } else {
1196 for i in 0..draw_count {
1197 let indirect_offset = offset
1198 + i as wgt::BufferAddress
1199 * size_of::<wgt::DrawIndirectArgs>() as wgt::BufferAddress;
1200 unsafe {
1201 self.device.raw.cmd_draw_indirect(
1202 self.active,
1203 buffer.raw,
1204 indirect_offset,
1205 1,
1206 size_of::<wgt::DrawIndirectArgs>() as u32,
1207 )
1208 };
1209 }
1210 }
1211 }
1212 unsafe fn draw_indexed_indirect(
1213 &mut self,
1214 buffer: &super::Buffer,
1215 offset: wgt::BufferAddress,
1216 draw_count: u32,
1217 ) {
1218 if draw_count >= 1
1219 && self.device.private_caps.multi_draw_indirect
1220 && draw_count <= self.device.private_caps.max_draw_indirect_count
1221 {
1222 unsafe {
1223 self.device.raw.cmd_draw_indexed_indirect(
1224 self.active,
1225 buffer.raw,
1226 offset,
1227 draw_count,
1228 size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
1229 )
1230 };
1231 } else {
1232 for i in 0..draw_count {
1233 let indirect_offset = offset
1234 + i as wgt::BufferAddress
1235 * size_of::<wgt::DrawIndexedIndirectArgs>() as wgt::BufferAddress;
1236 unsafe {
1237 self.device.raw.cmd_draw_indexed_indirect(
1238 self.active,
1239 buffer.raw,
1240 indirect_offset,
1241 1,
1242 size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
1243 )
1244 };
1245 }
1246 }
1247 }
1248 unsafe fn draw_mesh_tasks_indirect(
1249 &mut self,
1250 buffer: &<Self::A as crate::Api>::Buffer,
1251 offset: wgt::BufferAddress,
1252 draw_count: u32,
1253 ) {
1254 if let Some(ref t) = self.device.extension_fns.mesh_shading {
1255 unsafe {
1256 t.cmd_draw_mesh_tasks_indirect(
1257 self.active,
1258 buffer.raw,
1259 offset,
1260 draw_count,
1261 size_of::<wgt::DispatchIndirectArgs>() as u32,
1262 );
1263 };
1264 } else {
1265 panic!("Feature `MESH_SHADING` not enabled");
1266 }
1267 }
1268 unsafe fn draw_indirect_count(
1269 &mut self,
1270 buffer: &super::Buffer,
1271 offset: wgt::BufferAddress,
1272 count_buffer: &super::Buffer,
1273 count_offset: wgt::BufferAddress,
1274 max_count: u32,
1275 ) {
1276 let stride = size_of::<wgt::DrawIndirectArgs>() as u32;
1277 match self.device.extension_fns.draw_indirect_count {
1278 Some(ref t) => {
1279 unsafe {
1280 t.cmd_draw_indirect_count(
1281 self.active,
1282 buffer.raw,
1283 offset,
1284 count_buffer.raw,
1285 count_offset,
1286 max_count,
1287 stride,
1288 )
1289 };
1290 }
1291 None => panic!("Feature `DRAW_INDIRECT_COUNT` not enabled"),
1292 }
1293 }
1294 unsafe fn draw_indexed_indirect_count(
1295 &mut self,
1296 buffer: &super::Buffer,
1297 offset: wgt::BufferAddress,
1298 count_buffer: &super::Buffer,
1299 count_offset: wgt::BufferAddress,
1300 max_count: u32,
1301 ) {
1302 let stride = size_of::<wgt::DrawIndexedIndirectArgs>() as u32;
1303 match self.device.extension_fns.draw_indirect_count {
1304 Some(ref t) => {
1305 unsafe {
1306 t.cmd_draw_indexed_indirect_count(
1307 self.active,
1308 buffer.raw,
1309 offset,
1310 count_buffer.raw,
1311 count_offset,
1312 max_count,
1313 stride,
1314 )
1315 };
1316 }
1317 None => panic!("Feature `DRAW_INDIRECT_COUNT` not enabled"),
1318 }
1319 }
1320 unsafe fn draw_mesh_tasks_indirect_count(
1321 &mut self,
1322 buffer: &<Self::A as crate::Api>::Buffer,
1323 offset: wgt::BufferAddress,
1324 count_buffer: &super::Buffer,
1325 count_offset: wgt::BufferAddress,
1326 max_count: u32,
1327 ) {
1328 if self.device.extension_fns.draw_indirect_count.is_none() {
1329 panic!("Feature `DRAW_INDIRECT_COUNT` not enabled");
1330 }
1331 if let Some(ref t) = self.device.extension_fns.mesh_shading {
1332 unsafe {
1333 t.cmd_draw_mesh_tasks_indirect_count(
1334 self.active,
1335 buffer.raw,
1336 offset,
1337 count_buffer.raw,
1338 count_offset,
1339 max_count,
1340 size_of::<wgt::DispatchIndirectArgs>() as u32,
1341 );
1342 };
1343 } else {
1344 panic!("Feature `MESH_SHADING` not enabled");
1345 }
1346 }
1347
1348 unsafe fn begin_compute_pass(
1351 &mut self,
1352 desc: &crate::ComputePassDescriptor<'_, super::QuerySet>,
1353 ) {
1354 self.bind_point = vk::PipelineBindPoint::COMPUTE;
1355 if let Some(label) = desc.label {
1356 unsafe { self.begin_debug_marker(label) };
1357 self.rpass_debug_marker_active = true;
1358 }
1359
1360 if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() {
1361 if let Some(index) = timestamp_writes.beginning_of_pass_write_index {
1362 unsafe {
1363 self.write_timestamp(timestamp_writes.query_set, index);
1364 }
1365 }
1366 self.end_of_pass_timer_query = timestamp_writes
1367 .end_of_pass_write_index
1368 .map(|index| (timestamp_writes.query_set.raw, index));
1369 }
1370 }
1371 unsafe fn end_compute_pass(&mut self) {
1372 self.write_pass_end_timestamp_if_requested();
1373
1374 if self.rpass_debug_marker_active {
1375 unsafe { self.end_debug_marker() };
1376 self.rpass_debug_marker_active = false
1377 }
1378 }
1379
1380 unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
1381 unsafe {
1382 self.device.raw.cmd_bind_pipeline(
1383 self.active,
1384 vk::PipelineBindPoint::COMPUTE,
1385 pipeline.raw,
1386 )
1387 };
1388 }
1389
1390 unsafe fn dispatch_workgroups(&mut self, count: [u32; 3]) {
1391 unsafe {
1392 self.device
1393 .raw
1394 .cmd_dispatch(self.active, count[0], count[1], count[2])
1395 };
1396 }
1397 unsafe fn dispatch_workgroups_indirect(
1398 &mut self,
1399 buffer: &super::Buffer,
1400 offset: wgt::BufferAddress,
1401 ) {
1402 unsafe {
1403 self.device
1404 .raw
1405 .cmd_dispatch_indirect(self.active, buffer.raw, offset)
1406 }
1407 }
1408
1409 unsafe fn begin_ray_tracing_pass(&mut self, desc: &crate::RayTracingPassDescriptor<'_>) {
1412 self.bind_point = vk::PipelineBindPoint::RAY_TRACING_KHR;
1413 if let Some(label) = desc.label {
1414 unsafe { self.begin_debug_marker(label) };
1415 self.rpass_debug_marker_active = true;
1416 }
1417 }
1418 unsafe fn end_ray_tracing_pass(&mut self) {
1419 if self.rpass_debug_marker_active {
1420 unsafe { self.end_debug_marker() };
1421 self.rpass_debug_marker_active = false
1422 }
1423 }
1424
1425 unsafe fn trace_rays(
1426 &mut self,
1427 count: [u32; 3],
1428 ray_generation_group_data: crate::PipelineGroupData<super::Buffer>,
1429 miss_group_data: crate::PipelineGroupData<super::Buffer>,
1430 intersection_group_data: crate::PipelineGroupData<super::Buffer>,
1431 ) {
1432 let ray_tracing_functions = self
1433 .device
1434 .extension_fns
1435 .ray_tracing
1436 .as_ref()
1437 .expect("Feature `EXPERIMENTAL_RAY_TRACING` not enabled");
1438
1439 let ray_tracing_pipeline_functions = self
1440 .device
1441 .extension_fns
1442 .ray_tracing_pipelines
1443 .as_ref()
1444 .expect("Feature `EXPERIMENTAL_RAY_TRACING_PIPELINES` not enabled");
1445
1446 let get_device_address = |buffer: &super::Buffer| unsafe {
1447 ray_tracing_functions
1448 .buffer_device_address
1449 .get_buffer_device_address(
1450 &vk::BufferDeviceAddressInfo::default().buffer(buffer.raw),
1451 )
1452 };
1453
1454 unsafe {
1455 ray_tracing_pipeline_functions.cmd_trace_rays(
1456 self.raw_handle(),
1457 &vk::StridedDeviceAddressRegionKHR {
1458 device_address: get_device_address(ray_generation_group_data.buffer)
1459 + ray_generation_group_data.offset,
1460 stride: ray_generation_group_data.stride,
1461 size: ray_generation_group_data.stride ,
1462 },
1463 &vk::StridedDeviceAddressRegionKHR {
1464 device_address: get_device_address(miss_group_data.buffer)
1465 + miss_group_data.offset,
1466 stride: miss_group_data.stride,
1467 size: miss_group_data.stride * miss_group_data.count,
1468 },
1469 &vk::StridedDeviceAddressRegionKHR {
1470 device_address: get_device_address(intersection_group_data.buffer)
1471 + intersection_group_data.offset,
1472 stride: intersection_group_data.stride,
1473 size: intersection_group_data.stride * intersection_group_data.count,
1474 },
1475 &vk::StridedDeviceAddressRegionKHR {
1476 device_address: 0,
1477 stride: 0,
1478 size: 0,
1479 },
1480 count[0],
1481 count[1],
1482 count[2],
1483 )
1484 };
1485 }
1486
1487 unsafe fn set_ray_tracing_pipeline(&mut self, pipeline: &super::RayTracingPipeline) {
1488 unsafe {
1489 self.device.raw.cmd_bind_pipeline(
1490 self.active,
1491 vk::PipelineBindPoint::RAY_TRACING_KHR,
1492 pipeline.raw,
1493 )
1494 };
1495 }
1496
1497 unsafe fn copy_acceleration_structure_to_acceleration_structure(
1498 &mut self,
1499 src: &super::AccelerationStructure,
1500 dst: &super::AccelerationStructure,
1501 copy: wgt::AccelerationStructureCopy,
1502 ) {
1503 let ray_tracing_functions = self
1504 .device
1505 .extension_fns
1506 .ray_tracing
1507 .as_ref()
1508 .expect("Feature `RAY_TRACING` not enabled");
1509
1510 let mode = match copy {
1511 wgt::AccelerationStructureCopy::Clone => vk::CopyAccelerationStructureModeKHR::CLONE,
1512 wgt::AccelerationStructureCopy::Compact => {
1513 vk::CopyAccelerationStructureModeKHR::COMPACT
1514 }
1515 };
1516
1517 unsafe {
1518 ray_tracing_functions
1519 .acceleration_structure
1520 .cmd_copy_acceleration_structure(
1521 self.active,
1522 &vk::CopyAccelerationStructureInfoKHR {
1523 s_type: vk::StructureType::COPY_ACCELERATION_STRUCTURE_INFO_KHR,
1524 p_next: core::ptr::null(),
1525 src: src.raw,
1526 dst: dst.raw,
1527 mode,
1528 _marker: Default::default(),
1529 },
1530 );
1531 }
1532 }
1533}
1534
1535#[cfg(test)]
1536mod tests {
1537 use super::*;
1538
1539 #[test]
1540 fn check_dst_image_layout() {
1541 assert_eq!(
1542 conv::derive_image_layout(wgt::TextureUses::COPY_DST, wgt::TextureFormat::Rgba8Unorm),
1543 DST_IMAGE_LAYOUT
1544 );
1545 }
1546}