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