1use {
2 crate::{
3 AnyAccelerationStructureNode, AnyResource, Node,
4 driver::{
5 accel_struct::{
6 AccelerationStructureGeometry, AccelerationStructureGeometryInfo,
7 DeviceOrHostAddress,
8 },
9 device::Device,
10 },
11 },
12 ash::vk,
13 log::trace,
14 std::{cell::RefCell, ops::Deref},
15};
16
17#[cfg(debug_assertions)]
18use crate::Execution;
19
20#[derive(Clone, Copy)]
42pub struct CommandRef<'a> {
43 cmd: &'a crate::driver::cmd_buf::CommandBuffer,
44
45 #[cfg(debug_assertions)]
46 exec: &'a Execution,
47
48 resources: &'a [AnyResource],
49}
50
51impl<'a> CommandRef<'a> {
52 pub(crate) fn new(
53 cmd: &'a crate::driver::cmd_buf::CommandBuffer,
54 resources: &'a [AnyResource],
55 #[cfg(debug_assertions)] exec: &'a Execution,
56 ) -> Self {
57 Self {
58 cmd,
59 #[cfg(debug_assertions)]
60 exec,
61 resources,
62 }
63 }
64
65 pub fn build_accel_struct(&self, infos: &[BuildAccelerationStructureInfo]) -> &Self {
158 #[derive(Default)]
159 struct Tls {
160 geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
161 ranges: Vec<vk::AccelerationStructureBuildRangeInfoKHR>,
162 }
163
164 thread_local! {
165 static TLS: RefCell<Tls> = Default::default();
166 }
167
168 TLS.with_borrow_mut(|tls| {
169 tls.geometries.clear();
170 tls.geometries.extend(infos.iter().flat_map(|info| {
171 info.build_data.geometries.iter().map(|(geometry, _)| {
172 <&AccelerationStructureGeometry as Into<
173 vk::AccelerationStructureGeometryKHR,
174 >>::into(geometry)
175 })
176 }));
177
178 tls.ranges.clear();
179 tls.ranges.extend(
180 infos
181 .iter()
182 .flat_map(|info| info.build_data.geometries.iter().map(|(_, range)| *range)),
183 );
184
185 let vk_ranges = {
186 let mut start = 0;
187 let mut vk_ranges = Vec::with_capacity(infos.len());
188 for info in infos {
189 let end = start + info.build_data.geometries.len();
190 vk_ranges.push(&tls.ranges[start..end]);
191 start = end;
192 }
193
194 vk_ranges
195 };
196
197 let vk_infos = {
198 let mut start = 0;
199 let mut vk_infos = Vec::with_capacity(infos.len());
200 for info in infos {
201 let end = start + info.build_data.geometries.len();
202 vk_infos.push(
203 vk::AccelerationStructureBuildGeometryInfoKHR::default()
204 .ty(info.build_data.ty)
205 .flags(info.build_data.flags)
206 .mode(vk::BuildAccelerationStructureModeKHR::BUILD)
207 .dst_acceleration_structure(self.resource(info.accel_struct).handle)
208 .geometries(&tls.geometries[start..end])
209 .scratch_data(info.scratch_addr.into()),
210 );
211 start = end;
212 }
213
214 vk_infos
215 };
216
217 unsafe {
218 Device::expect_accel_struct_ext(&self.cmd.device)
219 .cmd_build_acceleration_structures(self.cmd.handle, &vk_infos, &vk_ranges);
220 }
221 });
222
223 self
224 }
225
226 pub fn build_accel_struct_indirect(
235 &self,
236 infos: &[BuildAccelerationStructureIndirectInfo],
237 ) -> &Self {
238 #[derive(Default)]
239 struct Tls {
240 geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
241 max_primitive_counts: Vec<u32>,
242 range_bases: Vec<vk::DeviceAddress>,
243 range_strides: Vec<u32>,
244 }
245
246 thread_local! {
247 static TLS: RefCell<Tls> = Default::default();
248 }
249
250 TLS.with_borrow_mut(|tls| {
251 tls.geometries.clear();
252 tls.geometries.extend(infos.iter().flat_map(|info| {
253 info.build_data.geometries.iter().map(
254 <&AccelerationStructureGeometry as Into<
255 vk::AccelerationStructureGeometryKHR,
256 >>::into,
257 )
258 }));
259
260 tls.max_primitive_counts.clear();
261 tls.max_primitive_counts
262 .extend(infos.iter().flat_map(|info| {
263 info.build_data
264 .geometries
265 .iter()
266 .map(|geometry| geometry.max_primitive_count)
267 }));
268
269 tls.range_bases.clear();
270 tls.range_strides.clear();
271 let (vk_infos, vk_max_primitive_counts) = {
272 let mut start = 0;
273 let mut vk_infos = Vec::with_capacity(infos.len());
274 let mut vk_max_primitive_counts = Vec::with_capacity(infos.len());
275 for info in infos {
276 let end = start + info.build_data.geometries.len();
277 vk_infos.push(
278 vk::AccelerationStructureBuildGeometryInfoKHR::default()
279 .ty(info.build_data.ty)
280 .flags(info.build_data.flags)
281 .mode(vk::BuildAccelerationStructureModeKHR::BUILD)
282 .dst_acceleration_structure(self.resource(info.accel_struct).handle)
283 .geometries(&tls.geometries[start..end])
284 .scratch_data(info.scratch_data.into()),
285 );
286 vk_max_primitive_counts.push(&tls.max_primitive_counts[start..end]);
287 start = end;
288
289 tls.range_bases.push(info.range_base);
290 tls.range_strides.push(info.range_stride);
291 }
292
293 (vk_infos, vk_max_primitive_counts)
294 };
295
296 unsafe {
297 Device::expect_accel_struct_ext(&self.cmd.device)
298 .cmd_build_acceleration_structures_indirect(
299 self.cmd.handle,
300 &vk_infos,
301 &tls.range_bases,
302 &tls.range_strides,
303 &vk_max_primitive_counts,
304 );
305 }
306 });
307
308 self
309 }
310
311 pub(crate) fn cmd_push_constants(
312 &self,
313 layout: vk::PipelineLayout,
314 push_consts: &[vk::PushConstantRange],
315 offset: u32,
316 data: &[u8],
317 ) {
318 for push_const in push_consts {
319 let push_const_end = push_const.offset + push_const.size;
320 let data_end = offset + data.len() as u32;
321 let end = data_end.min(push_const_end);
322 let start = offset.max(push_const.offset);
323
324 if end > start {
325 trace!(
326 " push constants {:?} {}..{}",
327 push_const.stage_flags, start, end
328 );
329
330 unsafe {
331 self.device.cmd_push_constants(
332 self.handle,
333 layout,
334 push_const.stage_flags,
335 start,
336 &data[(start - offset) as usize..(end - offset) as usize],
337 );
338 }
339 }
340 }
341 }
342
343 pub fn update_accel_struct(&self, infos: &[UpdateAccelerationStructureInfo]) -> &Self {
355 #[derive(Default)]
356 struct Tls {
357 geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
358 ranges: Vec<vk::AccelerationStructureBuildRangeInfoKHR>,
359 }
360
361 thread_local! {
362 static TLS: RefCell<Tls> = Default::default();
363 }
364
365 TLS.with_borrow_mut(|tls| {
366 tls.geometries.clear();
367 tls.geometries.extend(infos.iter().flat_map(|info| {
368 info.update_data.geometries.iter().map(|(geometry, _)| {
369 <&AccelerationStructureGeometry as Into<
370 vk::AccelerationStructureGeometryKHR,
371 >>::into(geometry)
372 })
373 }));
374
375 tls.ranges.clear();
376 tls.ranges.extend(
377 infos
378 .iter()
379 .flat_map(|info| info.update_data.geometries.iter().map(|(_, range)| *range)),
380 );
381
382 let vk_ranges = {
383 let mut start = 0;
384 let mut vk_ranges = Vec::with_capacity(infos.len());
385 for info in infos {
386 let end = start + info.update_data.geometries.len();
387 vk_ranges.push(&tls.ranges[start..end]);
388 start = end;
389 }
390
391 vk_ranges
392 };
393
394 let vk_infos = {
395 let mut start = 0;
396 let mut vk_infos = Vec::with_capacity(infos.len());
397 for info in infos {
398 let end = start + info.update_data.geometries.len();
399 vk_infos.push(
400 vk::AccelerationStructureBuildGeometryInfoKHR::default()
401 .ty(info.update_data.ty)
402 .flags(info.update_data.flags)
403 .mode(vk::BuildAccelerationStructureModeKHR::UPDATE)
404 .dst_acceleration_structure(self.resource(info.dst_accel_struct).handle)
405 .src_acceleration_structure(self.resource(info.src_accel_struct).handle)
406 .geometries(&tls.geometries[start..end])
407 .scratch_data(info.scratch_addr.into()),
408 );
409 start = end;
410 }
411
412 vk_infos
413 };
414
415 unsafe {
416 Device::expect_accel_struct_ext(&self.cmd.device)
417 .cmd_build_acceleration_structures(self.cmd.handle, &vk_infos, &vk_ranges);
418 }
419 });
420
421 self
422 }
423
424 pub fn update_accel_struct_indirect(
433 &self,
434 infos: &[UpdateAccelerationStructureIndirectInfo],
435 ) -> &Self {
436 #[derive(Default)]
437 struct Tls {
438 geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
439 max_primitive_counts: Vec<u32>,
440 range_bases: Vec<vk::DeviceAddress>,
441 range_strides: Vec<u32>,
442 }
443
444 thread_local! {
445 static TLS: RefCell<Tls> = Default::default();
446 }
447
448 TLS.with_borrow_mut(|tls| {
449 tls.geometries.clear();
450 tls.geometries.extend(infos.iter().flat_map(|info| {
451 info.update_data.geometries.iter().map(
452 <&AccelerationStructureGeometry as Into<
453 vk::AccelerationStructureGeometryKHR,
454 >>::into,
455 )
456 }));
457
458 tls.max_primitive_counts.clear();
459 tls.max_primitive_counts
460 .extend(infos.iter().flat_map(|info| {
461 info.update_data
462 .geometries
463 .iter()
464 .map(|geometry| geometry.max_primitive_count)
465 }));
466
467 tls.range_bases.clear();
468 tls.range_strides.clear();
469 let (vk_infos, vk_max_primitive_counts) = {
470 let mut start = 0;
471 let mut vk_infos = Vec::with_capacity(infos.len());
472 let mut vk_max_primitive_counts = Vec::with_capacity(infos.len());
473 for info in infos {
474 let end = start + info.update_data.geometries.len();
475 vk_infos.push(
476 vk::AccelerationStructureBuildGeometryInfoKHR::default()
477 .ty(info.update_data.ty)
478 .flags(info.update_data.flags)
479 .mode(vk::BuildAccelerationStructureModeKHR::UPDATE)
480 .src_acceleration_structure(self.resource(info.src_accel_struct).handle)
481 .dst_acceleration_structure(self.resource(info.dst_accel_struct).handle)
482 .geometries(&tls.geometries[start..end])
483 .scratch_data(info.scratch_addr.into()),
484 );
485 vk_max_primitive_counts.push(&tls.max_primitive_counts[start..end]);
486 start = end;
487
488 tls.range_bases.push(info.range_base);
489 tls.range_strides.push(info.range_stride);
490 }
491
492 (vk_infos, vk_max_primitive_counts)
493 };
494
495 unsafe {
496 Device::expect_accel_struct_ext(&self.cmd.device)
497 .cmd_build_acceleration_structures_indirect(
498 self.cmd.handle,
499 &vk_infos,
500 &tls.range_bases,
501 &tls.range_strides,
502 &vk_max_primitive_counts,
503 );
504 }
505 });
506
507 self
508 }
509
510 pub fn resource<N>(&self, resource_node: N) -> &N::Resource
513 where
514 N: Node,
515 {
516 #[cfg(debug_assertions)]
525 assert!(
526 self.exec.accesses.contains_key(&resource_node.index()),
527 "unexpected node access: call an access function first"
528 );
529
530 resource_node.borrow(self.resources)
531 }
532}
533
534impl<'a> Deref for CommandRef<'a> {
535 type Target = crate::driver::cmd_buf::CommandBuffer;
536
537 fn deref(&self) -> &Self::Target {
538 self.cmd
539 }
540}
541
542#[derive(Clone, Debug)]
546pub struct BuildAccelerationStructureInfo {
547 pub accel_struct: AnyAccelerationStructureNode,
549
550 pub build_data: AccelerationStructureGeometryInfo<(
552 AccelerationStructureGeometry,
553 vk::AccelerationStructureBuildRangeInfoKHR,
554 )>,
555
556 pub scratch_addr: DeviceOrHostAddress,
559}
560
561impl BuildAccelerationStructureInfo {
562 pub fn new(
564 accel_struct: impl Into<AnyAccelerationStructureNode>,
565 scratch_addr: impl Into<DeviceOrHostAddress>,
566 build_data: AccelerationStructureGeometryInfo<(
567 AccelerationStructureGeometry,
568 vk::AccelerationStructureBuildRangeInfoKHR,
569 )>,
570 ) -> Self {
571 let accel_struct = accel_struct.into();
572 let scratch_addr = scratch_addr.into();
573
574 Self {
575 accel_struct,
576 build_data,
577 scratch_addr,
578 }
579 }
580}
581
582#[derive(Clone, Debug)]
587pub struct BuildAccelerationStructureIndirectInfo {
588 pub accel_struct: AnyAccelerationStructureNode,
590
591 pub build_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
593
594 pub range_base: vk::DeviceAddress,
598
599 pub range_stride: u32,
601
602 pub scratch_data: DeviceOrHostAddress,
605}
606
607impl BuildAccelerationStructureIndirectInfo {
608 pub fn new(
610 accel_struct: impl Into<AnyAccelerationStructureNode>,
611 scratch_data: impl Into<DeviceOrHostAddress>,
612 build_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
613 range_base: vk::DeviceAddress,
614 range_stride: u32,
615 ) -> Self {
616 let accel_struct = accel_struct.into();
617 let scratch_data = scratch_data.into();
618
619 Self {
620 accel_struct,
621 build_data,
622 range_base,
623 range_stride,
624 scratch_data,
625 }
626 }
627}
628
629#[derive(Clone, Debug)]
634pub struct UpdateAccelerationStructureIndirectInfo {
635 pub dst_accel_struct: AnyAccelerationStructureNode,
637
638 pub range_base: vk::DeviceAddress,
642
643 pub range_stride: u32,
645
646 pub scratch_addr: DeviceOrHostAddress,
649
650 pub src_accel_struct: AnyAccelerationStructureNode,
652
653 pub update_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
655}
656
657impl UpdateAccelerationStructureIndirectInfo {
658 pub fn new(
660 src_accel_struct: impl Into<AnyAccelerationStructureNode>,
661 dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
662 scratch_addr: impl Into<DeviceOrHostAddress>,
663 update_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
664 range_base: vk::DeviceAddress,
665 range_stride: u32,
666 ) -> Self {
667 let src_accel_struct = src_accel_struct.into();
668 let dst_accel_struct = dst_accel_struct.into();
669 let scratch_addr = scratch_addr.into();
670
671 Self {
672 dst_accel_struct,
673 range_base,
674 range_stride,
675 scratch_addr,
676 src_accel_struct,
677 update_data,
678 }
679 }
680}
681
682#[derive(Clone, Debug)]
684pub struct UpdateAccelerationStructureInfo {
685 pub dst_accel_struct: AnyAccelerationStructureNode,
687
688 pub scratch_addr: DeviceOrHostAddress,
691
692 pub src_accel_struct: AnyAccelerationStructureNode,
694
695 pub update_data: AccelerationStructureGeometryInfo<(
697 AccelerationStructureGeometry,
698 vk::AccelerationStructureBuildRangeInfoKHR,
699 )>,
700}
701
702impl UpdateAccelerationStructureInfo {
703 pub fn new(
705 src_accel_struct: impl Into<AnyAccelerationStructureNode>,
706 dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
707 scratch_addr: impl Into<DeviceOrHostAddress>,
708 update_data: AccelerationStructureGeometryInfo<(
709 AccelerationStructureGeometry,
710 vk::AccelerationStructureBuildRangeInfoKHR,
711 )>,
712 ) -> Self {
713 let src_accel_struct = src_accel_struct.into();
714 let dst_accel_struct = dst_accel_struct.into();
715 let scratch_addr = scratch_addr.into();
716
717 Self {
718 dst_accel_struct,
719 scratch_addr,
720 src_accel_struct,
721 update_data,
722 }
723 }
724}
725
726#[allow(missing_docs)]
727#[allow(deprecated)]
728mod deprecated {
729 use ash::vk;
730
731 use crate::{
732 cmd::{
733 BuildAccelerationStructureIndirectInfo, BuildAccelerationStructureInfo, CommandRef,
734 UpdateAccelerationStructureIndirectInfo, UpdateAccelerationStructureInfo,
735 },
736 driver::accel_struct::{
737 AccelerationStructureGeometry, AccelerationStructureGeometryInfo, DeviceOrHostAddress,
738 },
739 graph::pass_ref::{
740 AccelerationStructureBuildInfo, AccelerationStructureIndirectBuildInfo,
741 AccelerationStructureIndirectUpdateInfo, AccelerationStructureUpdateInfo,
742 },
743 node::AnyAccelerationStructureNode,
744 };
745
746 impl<'a> CommandRef<'a> {
747 #[deprecated = "use build_accel_struct function"]
748 #[doc(hidden)]
749 pub fn build_structure(
750 &self,
751 info: &AccelerationStructureGeometryInfo<(
752 AccelerationStructureGeometry,
753 vk::AccelerationStructureBuildRangeInfoKHR,
754 )>,
755 accel_struct: impl Into<AnyAccelerationStructureNode>,
756 scratch_addr: impl Into<DeviceOrHostAddress>,
757 ) -> &Self {
758 self.build_accel_struct(&[BuildAccelerationStructureInfo {
759 accel_struct: accel_struct.into(),
760 build_data: info.clone(),
761 scratch_addr: scratch_addr.into(),
762 }])
763 }
764
765 #[deprecated = "use build_accel_struct_indirect function"]
766 #[doc(hidden)]
767 pub fn build_structure_indirect(
768 &self,
769 info: &AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
770 accel_struct: impl Into<AnyAccelerationStructureNode>,
771 scratch_addr: impl Into<DeviceOrHostAddress>,
772 range_base: vk::DeviceAddress,
773 range_stride: u32,
774 ) -> &Self {
775 self.build_accel_struct_indirect(&[BuildAccelerationStructureIndirectInfo {
776 accel_struct: accel_struct.into(),
777 build_data: info.clone(),
778 range_base,
779 range_stride,
780 scratch_data: scratch_addr.into(),
781 }])
782 }
783
784 #[deprecated = "use build_accel_struct function"]
785 #[doc(hidden)]
786 pub fn build_structures(&self, infos: &[AccelerationStructureBuildInfo]) -> &Self {
787 for info in infos {
788 self.build_structure(&info.build_data, info.accel_struct, info.scratch_addr);
789 }
790
791 self
792 }
793
794 #[deprecated = "use build_accel_struct_indirect function"]
795 #[doc(hidden)]
796 pub fn build_structures_indirect(
797 &self,
798 infos: &[AccelerationStructureIndirectBuildInfo],
799 ) -> &Self {
800 for info in infos {
801 self.build_structure_indirect(
802 &info.build_data,
803 info.accel_struct,
804 info.scratch_data,
805 info.range_base,
806 info.range_stride,
807 );
808 }
809
810 self
811 }
812
813 #[deprecated = "use update_accel_struct function"]
814 #[doc(hidden)]
815 pub fn update_structure(
816 &self,
817 info: &AccelerationStructureGeometryInfo<(
818 AccelerationStructureGeometry,
819 vk::AccelerationStructureBuildRangeInfoKHR,
820 )>,
821 src_accel_struct: impl Into<AnyAccelerationStructureNode>,
822 dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
823 scratch_addr: impl Into<DeviceOrHostAddress>,
824 ) -> &Self {
825 self.update_accel_struct(&[UpdateAccelerationStructureInfo {
826 src_accel_struct: src_accel_struct.into(),
827 dst_accel_struct: dst_accel_struct.into(),
828 update_data: info.clone(),
829 scratch_addr: scratch_addr.into(),
830 }])
831 }
832
833 #[deprecated = "use update_accel_struct_indirect function"]
834 #[doc(hidden)]
835 pub fn update_structure_indirect(
836 &self,
837 info: &AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
838 src_accel_struct: impl Into<AnyAccelerationStructureNode>,
839 dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
840 scratch_addr: impl Into<DeviceOrHostAddress>,
841 range_base: vk::DeviceAddress,
842 range_stride: u32,
843 ) -> &Self {
844 self.update_accel_struct_indirect(&[UpdateAccelerationStructureIndirectInfo {
845 src_accel_struct: src_accel_struct.into(),
846 dst_accel_struct: dst_accel_struct.into(),
847 update_data: info.clone(),
848 range_base,
849 range_stride,
850 scratch_addr: scratch_addr.into(),
851 }])
852 }
853
854 #[deprecated = "use update_accel_struct function"]
855 #[doc(hidden)]
856 pub fn update_structures(&self, infos: &[AccelerationStructureUpdateInfo]) -> &Self {
857 for info in infos {
858 self.update_structure(
859 &info.update_data,
860 info.src_accel_struct,
861 info.dst_accel_struct,
862 info.scratch_addr,
863 );
864 }
865
866 self
867 }
868
869 #[deprecated = "use update_accel_struct_indirect function"]
870 #[doc(hidden)]
871 pub fn update_structures_indirect(
872 &self,
873 infos: &[AccelerationStructureIndirectUpdateInfo],
874 ) -> &Self {
875 for info in infos {
876 self.update_structure_indirect(
877 &info.update_data,
878 info.src_accel_struct,
879 info.dst_accel_struct,
880 info.scratch_addr,
881 info.range_base,
882 info.range_stride,
883 );
884 }
885
886 self
887 }
888 }
889}