@@ -40,6 +40,7 @@ bool CAssetConverter::patch_impl_t<ICPUSampler>::valid(const ILogicalDevice* dev
40
40
return true ;
41
41
}
42
42
43
+
43
44
CAssetConverter::patch_impl_t <ICPUShader>::patch_impl_t (const ICPUShader* shader) : stage(shader->getStage ()) {}
44
45
bool CAssetConverter::patch_impl_t <ICPUShader>::valid(const ILogicalDevice* device)
45
46
{
@@ -99,6 +100,67 @@ bool CAssetConverter::patch_impl_t<ICPUBuffer>::valid(const ILogicalDevice* devi
99
100
return true ;
100
101
}
101
102
103
+ bool CAssetConverter::acceleration_structure_patch_base::valid (const ILogicalDevice* device)
104
+ {
105
+ // note that we don't check the validity of things we don't patch, all the instance and geometry data, but it will be checked by the driver anyway during creation/build
106
+ if (preference==BuildPreference::Invalid) // unititialized or just wrong
107
+ return false ;
108
+ // just make the flags agree/canonicalize
109
+ allowCompaction = allowCompaction || compactAfterBuild;
110
+ // don't make invalid, just soft fail
111
+ const auto & limits = device->getPhysicalDevice ()->getLimits ();
112
+ if (allowDataAccess) // TODO: && !limits.rayTracingPositionFetch)
113
+ allowDataAccess = false ;
114
+ const auto & features = device->getEnabledFeatures ();
115
+ if (hostBuild && !features.accelerationStructureHostCommands )
116
+ hostBuild = false ;
117
+ return true ;
118
+ }
119
+ CAssetConverter::patch_impl_t <ICPUBottomLevelAccelerationStructure>::patch_impl_t (const ICPUBottomLevelAccelerationStructure* blas)
120
+ {
121
+ const auto flags = blas->getBuildFlags ();
122
+ // straight up invalid
123
+ if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT | build_flags_t ::PREFER_FAST_BUILD_BIT))
124
+ return ;
125
+
126
+ allowUpdate = flags.hasFlags (build_flags_t ::ALLOW_UPDATE_BIT);
127
+ allowCompaction = flags.hasFlags (build_flags_t ::ALLOW_COMPACTION_BIT);
128
+ allowDataAccess = flags.hasFlags (build_flags_t ::ALLOW_DATA_ACCESS_KHR);
129
+ if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT))
130
+ preference = BuildPreference::FastTrace;
131
+ else if (flags.hasFlags (build_flags_t ::PREFER_FAST_BUILD_BIT))
132
+ preference = BuildPreference::FastBuild;
133
+ else
134
+ preference = BuildPreference::None;
135
+ lowMemory = flags.hasFlags (build_flags_t ::LOW_MEMORY_BIT);
136
+ }
137
+ bool CAssetConverter::patch_impl_t <ICPUBottomLevelAccelerationStructure>::valid(const ILogicalDevice* device)
138
+ {
139
+ return acceleration_structure_patch_base::valid (device);
140
+ }
141
+ CAssetConverter::patch_impl_t <ICPUTopLevelAccelerationStructure>::patch_impl_t (const ICPUTopLevelAccelerationStructure* blas)
142
+ {
143
+ const auto flags = blas->getBuildFlags ();
144
+ // straight up invalid
145
+ if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT|build_flags_t ::PREFER_FAST_BUILD_BIT))
146
+ return ;
147
+
148
+ allowUpdate = flags.hasFlags (build_flags_t ::ALLOW_UPDATE_BIT);
149
+ allowCompaction = flags.hasFlags (build_flags_t ::ALLOW_COMPACTION_BIT);
150
+ allowDataAccess = false ;
151
+ if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT))
152
+ preference = BuildPreference::FastTrace;
153
+ else if (flags.hasFlags (build_flags_t ::PREFER_FAST_BUILD_BIT))
154
+ preference = BuildPreference::FastBuild;
155
+ else
156
+ preference = BuildPreference::None;
157
+ lowMemory = flags.hasFlags (build_flags_t ::LOW_MEMORY_BIT);
158
+ }
159
+ bool CAssetConverter::patch_impl_t <ICPUTopLevelAccelerationStructure>::valid(const ILogicalDevice* device)
160
+ {
161
+ return acceleration_structure_patch_base::valid (device);
162
+ }
163
+
102
164
// smol utility function
103
165
template <typename Patch>
104
166
void deduceMetaUsages (Patch& patch, const core::bitflag<IGPUImage::E_USAGE_FLAGS> usages, const E_FORMAT originalFormat, const bool hasDepthAspect=true )
@@ -330,6 +392,24 @@ class AssetVisitor : public CRTP
330
392
patch.usage |= IGPUBuffer::E_USAGE_FLAGS::EUF_STORAGE_TEXEL_BUFFER_BIT;
331
393
return descend<ICPUBuffer>(dep,std::move (patch));
332
394
}
395
+ inline bool impl (const instance_t <ICPUTopLevelAccelerationStructure>& instance, const CAssetConverter::patch_t <ICPUTopLevelAccelerationStructure>& userPatch)
396
+ {
397
+ const auto blasInstances = instance.asset ->getInstances ();
398
+ if (blasInstances.empty ()) // TODO: is it valid to have a BLASless TLAS?
399
+ return false ;
400
+ for (size_t i=0 ; i<blasInstances.size (); i++)
401
+ {
402
+ const auto * blas = blasInstances[i].getBase ().blas .get ();
403
+ if (!blas)
404
+ return false ;
405
+ CAssetConverter::patch_t <ICPUBottomLevelAccelerationStructure> patch = {blas};
406
+ if (userPatch.allowDataAccess ) // TODO: check if all BLAS within TLAS need to have the flag ON vs OFF or only some
407
+ patch.allowDataAccess = true ;
408
+ if (!descend (blas,std::move (patch),i))
409
+ return false ;
410
+ }
411
+ return true ;
412
+ }
333
413
inline bool impl (const instance_t <ICPUImageView>& instance, const CAssetConverter::patch_t <ICPUImageView>& userPatch)
334
414
{
335
415
const auto & params = instance.asset ->getCreationParameters ();
@@ -556,8 +636,10 @@ class AssetVisitor : public CRTP
556
636
}
557
637
case IDescriptor::EC_ACCELERATION_STRUCTURE:
558
638
{
559
- _NBL_TODO ();
560
- [[fallthrough]];
639
+ auto tlas = static_cast <const ICPUTopLevelAccelerationStructure*>(untypedDesc);
640
+ if (!descend (tlas,{tlas},type,binding,el))
641
+ return false ;
642
+ break ;
561
643
}
562
644
default :
563
645
assert (false );
@@ -845,6 +927,8 @@ class PatchOverride final : public CAssetConverter::CHashCache::IPatchOverride
845
927
inline const patch_t <ICPUSampler>* operator ()(const lookup_t <ICPUSampler>& lookup) const override {return impl (lookup);}
846
928
inline const patch_t <ICPUShader>* operator ()(const lookup_t <ICPUShader>& lookup) const override {return impl (lookup);}
847
929
inline const patch_t <ICPUBuffer>* operator ()(const lookup_t <ICPUBuffer>& lookup) const override {return impl (lookup);}
930
+ inline const patch_t <ICPUBottomLevelAccelerationStructure>* operator ()(const lookup_t <ICPUBottomLevelAccelerationStructure>& lookup) const override {return impl (lookup);}
931
+ inline const patch_t <ICPUTopLevelAccelerationStructure>* operator ()(const lookup_t <ICPUTopLevelAccelerationStructure>& lookup) const override {return impl (lookup);}
848
932
inline const patch_t <ICPUImage>* operator ()(const lookup_t <ICPUImage>& lookup) const override {return impl (lookup);}
849
933
inline const patch_t <ICPUBufferView>* operator ()(const lookup_t <ICPUBufferView>& lookup) const override {return impl (lookup);}
850
934
inline const patch_t <ICPUImageView>* operator ()(const lookup_t <ICPUImageView>& lookup) const override {return impl (lookup);}
@@ -955,6 +1039,68 @@ bool CAssetConverter::CHashCache::hash_impl::operator()(lookup_t<ICPUBuffer> loo
955
1039
hasher.update (&patchedParams,sizeof (patchedParams)) << lookup.asset ->getContentHash ();
956
1040
return true ;
957
1041
}
1042
+ bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUBottomLevelAccelerationStructure> lookup)
1043
+ {
1044
+ // extras from the patch
1045
+ hasher << lookup.patch ->hostBuild ;
1046
+ hasher << lookup.patch ->compactAfterBuild ;
1047
+ // overriden flags
1048
+ using build_flags_t = ICPUBottomLevelAccelerationStructure::BUILD_FLAGS;
1049
+ constexpr build_flags_t OverridableMask = build_flags_t ::LOW_MEMORY_BIT|build_flags_t ::PREFER_FAST_TRACE_BIT|build_flags_t ::PREFER_FAST_BUILD_BIT|build_flags_t ::ALLOW_COMPACTION_BIT|build_flags_t ::ALLOW_UPDATE_BIT|build_flags_t ::ALLOW_DATA_ACCESS_KHR;
1050
+ auto patchedBuildFlags = lookup.asset ->getBuildFlags ()&(~OverridableMask);
1051
+ if (lookup.patch ->lowMemory )
1052
+ patchedBuildFlags |= build_flags_t ::LOW_MEMORY_BIT;
1053
+ if (lookup.patch ->allowDataAccess )
1054
+ patchedBuildFlags |= build_flags_t ::ALLOW_DATA_ACCESS_KHR;
1055
+ if (lookup.patch ->allowCompaction )
1056
+ patchedBuildFlags |= build_flags_t ::ALLOW_COMPACTION_BIT;
1057
+ if (lookup.patch ->allowUpdate )
1058
+ patchedBuildFlags |= build_flags_t ::ALLOW_UPDATE_BIT;
1059
+ switch (lookup.patch ->preference )
1060
+ {
1061
+ case acceleration_structure_patch_base::BuildPreference::FastTrace:
1062
+ patchedBuildFlags |= build_flags_t ::PREFER_FAST_TRACE_BIT;
1063
+ break ;
1064
+ case acceleration_structure_patch_base::BuildPreference::FastBuild:
1065
+ patchedBuildFlags |= build_flags_t ::PREFER_FAST_BUILD_BIT;
1066
+ break ;
1067
+ default :
1068
+ break ;
1069
+ }
1070
+ hasher << patchedBuildFlags;
1071
+ // TODO: hash the geometry metadata thats not already in the dependents (c.f. Renderpass, Descriptor Set)
1072
+ return true ;
1073
+ }
1074
+ bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUTopLevelAccelerationStructure> lookup)
1075
+ {
1076
+ // extras from the patch
1077
+ hasher << lookup.patch ->hostBuild ;
1078
+ hasher << lookup.patch ->compactAfterBuild ;
1079
+ // overriden flags
1080
+ using build_flags_t = ICPUTopLevelAccelerationStructure::BUILD_FLAGS;
1081
+ constexpr build_flags_t OverridableMask = build_flags_t ::LOW_MEMORY_BIT|build_flags_t ::PREFER_FAST_TRACE_BIT|build_flags_t ::PREFER_FAST_BUILD_BIT|build_flags_t ::ALLOW_COMPACTION_BIT|build_flags_t ::ALLOW_UPDATE_BIT;
1082
+ auto patchedBuildFlags = lookup.asset ->getBuildFlags ()&(~OverridableMask);
1083
+ if (lookup.patch ->lowMemory )
1084
+ patchedBuildFlags |= build_flags_t ::LOW_MEMORY_BIT;
1085
+ if (lookup.patch ->allowCompaction )
1086
+ patchedBuildFlags |= build_flags_t ::ALLOW_COMPACTION_BIT;
1087
+ if (lookup.patch ->allowUpdate )
1088
+ patchedBuildFlags |= build_flags_t ::ALLOW_UPDATE_BIT;
1089
+ switch (lookup.patch ->preference )
1090
+ {
1091
+ case acceleration_structure_patch_base::BuildPreference::FastTrace:
1092
+ patchedBuildFlags |= build_flags_t ::PREFER_FAST_TRACE_BIT;
1093
+ break ;
1094
+ case acceleration_structure_patch_base::BuildPreference::FastBuild:
1095
+ patchedBuildFlags |= build_flags_t ::PREFER_FAST_BUILD_BIT;
1096
+ break ;
1097
+ default :
1098
+ break ;
1099
+ }
1100
+ hasher << patchedBuildFlags;
1101
+ // TODO: hash the instance metadata thats not already in the dependents (c.f. Renderpass, Descriptor Set)
1102
+ return true ;
1103
+ }
958
1104
bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUImage> lookup)
959
1105
{
960
1106
// failed promotion
@@ -1366,8 +1512,8 @@ void CAssetConverter::CHashCache::eraseStale(const IPatchOverride* patchOverride
1366
1512
rehash.operator ()<ICPUBufferView>();
1367
1513
rehash.operator ()<ICPUImage>();
1368
1514
rehash.operator ()<ICPUImageView>();
1369
- // rehash.operator()<ICPUBottomLevelAccelerationStructure>();
1370
- // rehash.operator()<ICPUTopLevelAccelerationStructure>();
1515
+ rehash.operator ()<ICPUBottomLevelAccelerationStructure>();
1516
+ rehash.operator ()<ICPUTopLevelAccelerationStructure>();
1371
1517
// only once all the descriptor types have been hashed, we can hash sets
1372
1518
rehash.operator ()<ICPUDescriptorSet>();
1373
1519
// naturally any pipeline depends on shaders and pipeline cache
@@ -1417,6 +1563,52 @@ class GetDependantVisitBase
1417
1563
template <Asset AssetType>
1418
1564
class GetDependantVisit ;
1419
1565
1566
+ template <>
1567
+ class GetDependantVisit <ICPUBottomLevelAccelerationStructure> : public GetDependantVisitBase<ICPUBottomLevelAccelerationStructure>
1568
+ {
1569
+ public:
1570
+ SBufferRange<IGPUBuffer> underlying = {};
1571
+
1572
+ protected:
1573
+ bool descend_impl (
1574
+ const instance_t <AssetType>& user, const CAssetConverter::patch_t <AssetType>& userPatch,
1575
+ const instance_t <ICPUBuffer>& dep, const CAssetConverter::patch_t <ICPUBuffer>& soloPatch
1576
+ )
1577
+ {
1578
+ auto depObj = getDependant<ICPUBuffer>(dep,soloPatch);
1579
+ if (!depObj)
1580
+ return false ;
1581
+ underlying = {
1582
+ .offset = user.asset ->getOffsetInBuffer (),
1583
+ .size = user.asset ->getByteSize (),
1584
+ .buffer = std::move (depObj)
1585
+ };
1586
+ return underlying.isValid ();
1587
+ }
1588
+ };
1589
+ template <>
1590
+ class GetDependantVisit <ICPUTopLevelAccelerationStructure> : public GetDependantVisitBase<ICPUTopLevelAccelerationStructure>
1591
+ {
1592
+ public:
1593
+ SBufferRange<IGPUBuffer> underlying = {};
1594
+
1595
+ protected:
1596
+ bool descend_impl (
1597
+ const instance_t <AssetType>& user, const CAssetConverter::patch_t <AssetType>& userPatch,
1598
+ const instance_t <ICPUBuffer>& dep, const CAssetConverter::patch_t <ICPUBuffer>& soloPatch
1599
+ )
1600
+ {
1601
+ auto depObj = getDependant<ICPUBuffer>(dep,soloPatch);
1602
+ if (!depObj)
1603
+ return false ;
1604
+ underlying = {
1605
+ .offset = user.asset ->getOffsetInBuffer (),
1606
+ .size = user.asset ->getByteSize (),
1607
+ .buffer = std::move (depObj)
1608
+ };
1609
+ return underlying.isValid ();
1610
+ }
1611
+ };
1420
1612
template <>
1421
1613
class GetDependantVisit <ICPUBufferView> : public GetDependantVisitBase<ICPUBufferView>
1422
1614
{
0 commit comments