@@ -593,18 +593,7 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
593
593
auto tlas = set.first ;
594
594
// we know the build is completed immediately after performing it, so we get our pending stamp then
595
595
// ideally we should get our build version when the work of the deferred op gets executed for the first time
596
- using iterator = decltype (set.second )::iterator;
597
- struct CustomIterator
598
- {
599
- inline bool operator !=(const CustomIterator& other) const {return ptr!=other.ptr ;}
600
-
601
- inline CustomIterator operator ++() {return {ptr++};}
602
-
603
- inline const IGPUBottomLevelAccelerationStructure* operator *() const {return dynamic_cast <const IGPUBottomLevelAccelerationStructure*>(ptr->get ());}
604
-
605
- iterator ptr;
606
- };
607
- const auto buildVer = tlas->pushTrackedBLASes <CustomIterator>({set.second .begin ()},{set.second .end ()});
596
+ const auto buildVer = tlas->pushTrackedBLASes <IGPUTopLevelAccelerationStructure::DynamicUpCastingSpanIterator>({set.second .begin ()},{set.second .end ()});
608
597
tlas->clearTrackedBLASes (buildVer);
609
598
}
610
599
}
@@ -622,10 +611,7 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
622
611
if constexpr (IsTLAS)
623
612
{
624
613
const auto blasCount = info.trackedBLASes .size ();
625
- if (blasCount)
626
- callback.m_TLASToBLASReferenceSets [info.dstAS ] = {oit-blasCount,blasCount};
627
- else
628
- callback.m_TLASToBLASReferenceSets [info.dstAS ] = {};
614
+ callback.m_TLASToBLASReferenceSets [info.dstAS ] = {oit-blasCount,blasCount};
629
615
}
630
616
}
631
617
if constexpr (IsTLAS)
@@ -685,10 +671,42 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
685
671
}
686
672
auto result = copyAccelerationStructure_impl (deferredOperation,copyInfo);
687
673
if (result==DEFERRABLE_RESULT::DEFERRED)
674
+ {
688
675
deferredOperation->m_resourceTracking .insert (deferredOperation->m_resourceTracking .begin (),{
689
676
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.src ),
690
677
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.dst )
691
678
});
679
+ constexpr bool IsTLAS = std::is_same_v<AccelerationStructure,IGPUTopLevelAccelerationStructure>;
680
+ if constexpr (IsTLAS)
681
+ {
682
+ struct TLASCallback
683
+ {
684
+ // upon completion set the BLASes tracked
685
+ inline void operator ()(IDeferredOperation*) const
686
+ {
687
+ // not sure if even legal, but it would deadlock us
688
+ if (src==dst)
689
+ return ;
690
+ uint32_t buildVer;
691
+ {
692
+ // stop multiple threads messing with us
693
+ std::lock_guard lk (src->m_trackingLock );
694
+ // we know the build is completed immediately after performing it, so we get our pending stamp then
695
+ // ideally we should get the BLAS set from the Source TLAS when the work of the deferred op gets executed for the first time
696
+ const auto * pSrcBLASes = src->getPendingBuildTrackedBLASes (src->getPendingBuildVer ());
697
+ const std::span<IGPUTopLevelAccelerationStructure::blas_smart_ptr_t > emptySpan = {};
698
+ buildVer = pSrcBLASes ? dst->pushTrackedBLASes (pSrcBLASes->begin (),pSrcBLASes->end ()):dst->pushTrackedBLASes (emptySpan.begin (),emptySpan.end ());
699
+ }
700
+ dst->clearTrackedBLASes (buildVer);
701
+ }
702
+
703
+ // the rawpointers are already smartpointers in whatever else the `fillTracking` declared above writes
704
+ const IGPUTopLevelAccelerationStructure* src;
705
+ IGPUTopLevelAccelerationStructure* dst;
706
+ } callback = {.src =copyInfo.src ,.dst =copyInfo.dst };
707
+ deferredOperation->m_callback = std::move (callback);
708
+ }
709
+ }
692
710
693
711
694
712
return result!=DEFERRABLE_RESULT::SOME_ERROR;
@@ -713,10 +731,39 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
713
731
}
714
732
auto result = copyAccelerationStructureToMemory_impl (deferredOperation,copyInfo);
715
733
if (result==DEFERRABLE_RESULT::DEFERRED)
734
+ {
716
735
deferredOperation->m_resourceTracking .insert (deferredOperation->m_resourceTracking .begin (),{
717
736
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.src ),
718
737
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.dst .buffer )
719
738
});
739
+ constexpr bool IsTLAS = std::is_same_v<AccelerationStructure,IGPUTopLevelAccelerationStructure>;
740
+ if constexpr (IsTLAS)
741
+ {
742
+ struct TLASCallback
743
+ {
744
+ // upon completion set the BLASes tracked
745
+ inline void operator ()(IDeferredOperation*) const
746
+ {
747
+ // stop multiple threads messing with us
748
+ std::lock_guard lk (src->m_trackingLock );
749
+ // we know the build is completed immediately after performing it, so we get our pending stamp then
750
+ // ideally we should get the BLAS set from the Source TLAS when the work of the deferred op gets executed for the first time
751
+ const auto ver = src->getPendingBuildVer ();
752
+ uint32_t count = dst->size ();
753
+ src->getPendingBuildTrackedBLASes (&count,dst->data (),ver);
754
+ if (count>dst->size ())
755
+ logger->log (" BLAS output array too small, should be %d, only wrote out %d BLAS references to destination" ,system::ILogger::ELL_ERROR,count,dst->size ());
756
+ }
757
+
758
+ // device keeps it alive for entire lifetime of the callback
759
+ system::ILogger* logger;
760
+ // the rawpointers are already smartpointers in whatever else the `fillTracking` declared above writes
761
+ const IGPUTopLevelAccelerationStructure* src;
762
+ core::smart_refctd_dynamic_array<IGPUTopLevelAccelerationStructure::blas_smart_ptr_t > dst;
763
+ } callback = {.logger =m_logger.get (),.src =copyInfo.src ,.dst =copyInfo.trackedBLASes };
764
+ deferredOperation->m_callback = std::move (callback);
765
+ }
766
+ }
720
767
return result!=DEFERRABLE_RESULT::SOME_ERROR;
721
768
}
722
769
template <typename AccelerationStructure> requires std::is_base_of_v<IGPUAccelerationStructure,AccelerationStructure>
@@ -739,10 +786,32 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
739
786
}
740
787
auto result = copyAccelerationStructureFromMemory_impl (deferredOperation,copyInfo);
741
788
if (result==DEFERRABLE_RESULT::DEFERRED)
789
+ {
742
790
deferredOperation->m_resourceTracking .insert (deferredOperation->m_resourceTracking .begin (),{
743
791
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.src .buffer ),
744
792
core::smart_refctd_ptr<const IReferenceCounted>(copyInfo.dst )
745
793
});
794
+ constexpr bool IsTLAS = std::is_same_v<AccelerationStructure,IGPUTopLevelAccelerationStructure>;
795
+ if constexpr (IsTLAS)
796
+ {
797
+ const size_t offset = deferredOperation->m_resourceTracking .size ();
798
+ deferredOperation->m_resourceTracking .insert (deferredOperation->m_resourceTracking .end (),copyInfo.trackedBLASes .begin (),copyInfo.trackedBLASes .end ());
799
+ struct TLASCallback
800
+ {
801
+ // upon completion set the BLASes tracked
802
+ inline void operator ()(IDeferredOperation*) const
803
+ {
804
+ const auto buildVer = dst->pushTrackedBLASes <IGPUTopLevelAccelerationStructure::DynamicUpCastingSpanIterator>({src->begin ()},{src->end ()});
805
+ dst->clearTrackedBLASes (buildVer);
806
+ }
807
+
808
+ // the rawpointers are already smartpointers in whatever else the `fillTracking` declared above writes
809
+ std::span<const core::smart_refctd_ptr<const IReferenceCounted>> src;
810
+ IGPUTopLevelAccelerationStructure* dst;
811
+ } callback = {.src ={deferredOperation->m_resourceTracking .data ()+offset,copyInfo.trackedBLASes .size ()},.dst =copyInfo.dst };
812
+ deferredOperation->m_callback = std::move (callback);
813
+ }
814
+ }
746
815
return result!=DEFERRABLE_RESULT::SOME_ERROR;
747
816
}
748
817
0 commit comments