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