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