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