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