@@ -109,12 +109,11 @@ bool CAssetConverter::acceleration_structure_patch_base::valid(const ILogicalDev
109
109
const auto & features = device->getEnabledFeatures ();
110
110
if (!features.accelerationStructure )
111
111
return false ;
112
+ //
113
+ if (isMotion && !features.rayTracingMotionBlur )
114
+ return false ;
112
115
// just make the flags agree/canonicalize
113
116
allowCompaction = allowCompaction || compactAfterBuild;
114
- // on a second thought, if someone asked for BLAS with data access, they probably intend to use it
115
- const auto & limits = device->getPhysicalDevice ()->getLimits ();
116
- if (allowDataAccess && !limits.rayTracingPositionFetch )
117
- return false ;
118
117
// can always build with the device
119
118
if (hostBuild)
120
119
#ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION_HOST_READY
@@ -134,25 +133,26 @@ CAssetConverter::patch_impl_t<ICPUBottomLevelAccelerationStructure>::patch_impl_
134
133
if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT|build_flags_t ::PREFER_FAST_BUILD_BIT))
135
134
return ;
136
135
136
+ isMotion = blas->usesMotion ();
137
137
allowUpdate = flags.hasFlags (build_flags_t ::ALLOW_UPDATE_BIT);
138
138
allowCompaction = flags.hasFlags (build_flags_t ::ALLOW_COMPACTION_BIT);
139
- allowDataAccess = flags.hasFlags (build_flags_t ::ALLOW_DATA_ACCESS_KHR);
140
139
if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT))
141
140
preference = BuildPreference::FastTrace;
142
141
else if (flags.hasFlags (build_flags_t ::PREFER_FAST_BUILD_BIT))
143
142
preference = BuildPreference::FastBuild;
144
143
else
145
144
preference = BuildPreference::None;
146
145
lowMemory = flags.hasFlags (build_flags_t ::LOW_MEMORY_BIT);
146
+ allowDataAccess = flags.hasFlags (build_flags_t ::ALLOW_DATA_ACCESS);
147
147
}
148
148
auto CAssetConverter::patch_impl_t <ICPUBottomLevelAccelerationStructure>::getBuildFlags(const ICPUBottomLevelAccelerationStructure* blas) const -> core::bitflag<build_flags_t >
149
149
{
150
- 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 ;
150
+ 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 ;
151
151
auto flags = blas->getBuildFlags ()&(~OverridableMask);
152
152
if (lowMemory)
153
153
flags |= build_flags_t ::LOW_MEMORY_BIT;
154
154
if (allowDataAccess)
155
- flags |= build_flags_t ::ALLOW_DATA_ACCESS_KHR ;
155
+ flags |= build_flags_t ::ALLOW_DATA_ACCESS ;
156
156
if (allowCompaction)
157
157
flags |= build_flags_t ::ALLOW_COMPACTION_BIT;
158
158
if (allowUpdate)
@@ -172,6 +172,10 @@ auto CAssetConverter::patch_impl_t<ICPUBottomLevelAccelerationStructure>::getBui
172
172
}
173
173
bool CAssetConverter::patch_impl_t <ICPUBottomLevelAccelerationStructure>::valid(const ILogicalDevice* device)
174
174
{
175
+ // on a second thought, if someone asked for BLAS with data access, they probably intend to use it
176
+ const auto & limits = device->getPhysicalDevice ()->getLimits ();
177
+ if (allowDataAccess && !limits.rayTracingPositionFetch )
178
+ return false ;
175
179
return acceleration_structure_patch_base::valid (device);
176
180
}
177
181
CAssetConverter::patch_impl_t <ICPUTopLevelAccelerationStructure>::patch_impl_t (const ICPUTopLevelAccelerationStructure* tlas)
@@ -183,16 +187,17 @@ CAssetConverter::patch_impl_t<ICPUTopLevelAccelerationStructure>::patch_impl_t(c
183
187
if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT|build_flags_t ::PREFER_FAST_BUILD_BIT))
184
188
return ;
185
189
190
+ isMotion = tlas->usesMotion ();
186
191
allowUpdate = flags.hasFlags (build_flags_t ::ALLOW_UPDATE_BIT);
187
192
allowCompaction = flags.hasFlags (build_flags_t ::ALLOW_COMPACTION_BIT);
188
- allowDataAccess = false ;
189
193
if (flags.hasFlags (build_flags_t ::PREFER_FAST_TRACE_BIT))
190
194
preference = BuildPreference::FastTrace;
191
195
else if (flags.hasFlags (build_flags_t ::PREFER_FAST_BUILD_BIT))
192
196
preference = BuildPreference::FastBuild;
193
197
else
194
198
preference = BuildPreference::None;
195
199
lowMemory = flags.hasFlags (build_flags_t ::LOW_MEMORY_BIT);
200
+ maxInstances = tlas->getInstances ().size ();
196
201
}
197
202
auto CAssetConverter::patch_impl_t <ICPUTopLevelAccelerationStructure>::getBuildFlags(const ICPUTopLevelAccelerationStructure* tlas) const -> core::bitflag<build_flags_t >
198
203
{
@@ -441,7 +446,6 @@ class AssetVisitor : public CRTP
441
446
}
442
447
443
448
private:
444
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
445
449
// there is no `impl()` overload taking `ICPUTopLevelAccelerationStructure` same as there is no `ICPUmage`
446
450
inline bool impl (const instance_t <ICPUTopLevelAccelerationStructure>& instance, const CAssetConverter::patch_t <ICPUTopLevelAccelerationStructure>& userPatch)
447
451
{
@@ -454,14 +458,11 @@ class AssetVisitor : public CRTP
454
458
if (!blas)
455
459
return false ;
456
460
CAssetConverter::patch_t <ICPUBottomLevelAccelerationStructure> patch = {blas};
457
- if (userPatch.allowDataAccess ) // TODO: check if all BLAS within TLAS need to have the flag ON vs OFF or only some
458
- patch.allowDataAccess = true ;
459
461
if (!descend (blas,std::move (patch),i))
460
462
return false ;
461
463
}
462
464
return true ;
463
465
}
464
- #endif
465
466
inline bool impl (const instance_t <ICPUBufferView>& instance, const CAssetConverter::patch_t <ICPUBufferView>& userPatch)
466
467
{
467
468
const auto * dep = instance.asset ->getUnderlyingBuffer ();
@@ -698,15 +699,13 @@ class AssetVisitor : public CRTP
698
699
return false ;
699
700
break ;
700
701
}
701
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
702
702
case IDescriptor::EC_ACCELERATION_STRUCTURE:
703
703
{
704
704
auto tlas = static_cast <const ICPUTopLevelAccelerationStructure*>(untypedDesc);
705
705
if (!descend (tlas,{tlas},type,binding,el))
706
706
return false ;
707
707
break ;
708
708
}
709
- #endif
710
709
default :
711
710
assert (false );
712
711
return false ;
@@ -961,6 +960,45 @@ class DFSVisitor
961
960
core::stack<patched_instance_t >& stack;
962
961
};
963
962
963
+ // because we need to iterate over all BLAS' patches to check is one of them got patched with Motion
964
+ class CheckBLASPatchMotions
965
+ {
966
+ public:
967
+ using AssetType = ICPUTopLevelAccelerationStructure;
968
+
969
+ const CAssetConverter::SInputs& inputs;
970
+ const dfs_cache<ICPUBottomLevelAccelerationStructure>& visitedBLASes;
971
+ bool isMotion = false ;
972
+
973
+ protected:
974
+ template <typename DepType>
975
+ void nullOptional () const {}
976
+
977
+ inline size_t getDependantUniqueCopyGroupID (const size_t usersGroupCopyID, const AssetType* user, const ICPUBottomLevelAccelerationStructure* dep) const
978
+ {
979
+ return inputs.getDependantUniqueCopyGroupID (usersGroupCopyID,user,dep);
980
+ }
981
+
982
+ bool descend_impl (
983
+ const instance_t <AssetType>& user, const CAssetConverter::patch_t <AssetType>& userPatch,
984
+ const instance_t <ICPUBottomLevelAccelerationStructure>& dep, const CAssetConverter::patch_t <ICPUBottomLevelAccelerationStructure>& soloPatch,
985
+ const uint32_t instanceIndex // not the custom index, its literally just an ordinal in `getInstances()`
986
+ )
987
+ {
988
+ // find matching patch in dfsCache
989
+ const auto patchIx = visitedBLASes.find (dep,soloPatch);
990
+ // must be found, must have been visited
991
+ assert (bool (patchIx));
992
+ // want to stop the visits after finding first BLAS with motion
993
+ if (visitedBLASes.nodes [patchIx.value ].patch .isMotion )
994
+ {
995
+ isMotion = true ;
996
+ return false ;
997
+ }
998
+ return true ;
999
+ }
1000
+ };
1001
+
964
1002
// go forth and find first patch that matches
965
1003
class PatchOverride final : public CAssetConverter::CHashCache::IPatchOverride
966
1004
{
@@ -993,10 +1031,8 @@ class PatchOverride final : public CAssetConverter::CHashCache::IPatchOverride
993
1031
inline const patch_t <ICPUSampler>* operator ()(const lookup_t <ICPUSampler>& lookup) const override {return impl (lookup);}
994
1032
inline const patch_t <ICPUShader>* operator ()(const lookup_t <ICPUShader>& lookup) const override {return impl (lookup);}
995
1033
inline const patch_t <ICPUBuffer>* operator ()(const lookup_t <ICPUBuffer>& lookup) const override {return impl (lookup);}
996
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
997
1034
inline const patch_t <ICPUBottomLevelAccelerationStructure>* operator ()(const lookup_t <ICPUBottomLevelAccelerationStructure>& lookup) const override {return impl (lookup);}
998
1035
inline const patch_t <ICPUTopLevelAccelerationStructure>* operator ()(const lookup_t <ICPUTopLevelAccelerationStructure>& lookup) const override {return impl (lookup);}
999
- #endif
1000
1036
inline const patch_t <ICPUImage>* operator ()(const lookup_t <ICPUImage>& lookup) const override {return impl (lookup);}
1001
1037
inline const patch_t <ICPUBufferView>* operator ()(const lookup_t <ICPUBufferView>& lookup) const override {return impl (lookup);}
1002
1038
inline const patch_t <ICPUImageView>* operator ()(const lookup_t <ICPUImageView>& lookup) const override {return impl (lookup);}
@@ -1107,13 +1143,13 @@ bool CAssetConverter::CHashCache::hash_impl::operator()(lookup_t<ICPUBuffer> loo
1107
1143
hasher.update (&patchedParams,sizeof (patchedParams)) << lookup.asset ->getContentHash ();
1108
1144
return true ;
1109
1145
}
1110
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
1111
1146
bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUBottomLevelAccelerationStructure> lookup)
1112
1147
{
1113
1148
// extras from the patch
1114
1149
hasher << lookup.patch ->hostBuild ;
1115
1150
hasher << lookup.patch ->compactAfterBuild ;
1116
1151
// overriden flags
1152
+ hasher << lookup.patch ->isMotion ;
1117
1153
hasher << lookup.patch ->getBuildFlags (lookup.asset );
1118
1154
// finally the contents
1119
1155
// TODO: hasher << lookup.asset->getContentHash();
@@ -1122,6 +1158,7 @@ bool CAssetConverter::CHashCache::hash_impl::operator()(lookup_t<ICPUBottomLevel
1122
1158
bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUTopLevelAccelerationStructure> lookup)
1123
1159
{
1124
1160
const auto * asset = lookup.asset ;
1161
+ #if 0
1125
1162
//
1126
1163
AssetVisitor<HashVisit<ICPUTopLevelAccelerationStructure>> visitor = {
1127
1164
*this,
@@ -1134,6 +1171,7 @@ bool CAssetConverter::CHashCache::hash_impl::operator()(lookup_t<ICPUTopLevelAcc
1134
1171
hasher << lookup.patch->hostBuild;
1135
1172
hasher << lookup.patch->compactAfterBuild;
1136
1173
// overriden flags
1174
+ hasher << lookup.patch->isMotion;
1137
1175
hasher << lookup.patch->getBuildFlags(lookup.asset);
1138
1176
const auto instances = asset->getInstances();
1139
1177
// important two passes to not give identical data due to variable length polymorphic array being hashed
@@ -1150,9 +1188,9 @@ bool CAssetConverter::CHashCache::hash_impl::operator()(lookup_t<ICPUTopLevelAcc
1150
1188
instance.instance
1151
1189
);
1152
1190
}
1191
+ #endif
1153
1192
return true ;
1154
1193
}
1155
- #endif
1156
1194
bool CAssetConverter::CHashCache::hash_impl::operator ()(lookup_t <ICPUImage> lookup)
1157
1195
{
1158
1196
// failed promotion
@@ -1564,10 +1602,8 @@ void CAssetConverter::CHashCache::eraseStale(const IPatchOverride* patchOverride
1564
1602
rehash.operator ()<ICPUBufferView>();
1565
1603
rehash.operator ()<ICPUImage>();
1566
1604
rehash.operator ()<ICPUImageView>();
1567
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
1568
1605
rehash.operator ()<ICPUBottomLevelAccelerationStructure>();
1569
1606
rehash.operator ()<ICPUTopLevelAccelerationStructure>();
1570
- #endif
1571
1607
// only once all the descriptor types have been hashed, we can hash sets
1572
1608
rehash.operator ()<ICPUDescriptorSet>();
1573
1609
// naturally any pipeline depends on shaders and pipeline cache
@@ -1617,12 +1653,11 @@ class GetDependantVisitBase
1617
1653
template <Asset AssetType>
1618
1654
class GetDependantVisit ;
1619
1655
1620
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
1621
1656
template <>
1622
1657
class GetDependantVisit <ICPUTopLevelAccelerationStructure> : public GetDependantVisitBase<ICPUTopLevelAccelerationStructure>
1623
1658
{
1624
1659
public:
1625
- // because of the deferred building of TLASes and lack of lifetime tracking between them, nothing to do on some passes
1660
+ // because of zero access to the lifetime tracking between TLASes and BLASes, do nothing
1626
1661
// core::smart_refctd_ptr<IGPUBottomLevelAccelerationStructure>* const outBLASes;
1627
1662
1628
1663
protected:
@@ -1639,7 +1674,7 @@ class GetDependantVisit<ICPUTopLevelAccelerationStructure> : public GetDependant
1639
1674
return true ;
1640
1675
}
1641
1676
};
1642
- # endif
1677
+
1643
1678
template <>
1644
1679
class GetDependantVisit <ICPUBufferView> : public GetDependantVisitBase<ICPUBufferView>
1645
1680
{
@@ -2072,11 +2107,9 @@ auto CAssetConverter::reserve(const SInputs& inputs) -> SReserveResult
2072
2107
case ICPUImageView::AssetType:
2073
2108
visit.operator ()<ICPUImageView>(entry);
2074
2109
break ;
2075
- #ifdef NBL_ACCELERATION_STRUCTURE_CONVERSION
2076
2110
case ICPUTopLevelAccelerationStructure::AssetType:
2077
2111
visit.operator ()<ICPUTopLevelAccelerationStructure>(entry);
2078
2112
break ;
2079
- #endif
2080
2113
// these assets have no dependants, should have never been pushed on the stack
2081
2114
default :
2082
2115
assert (false );
@@ -2165,6 +2198,28 @@ auto CAssetConverter::reserve(const SInputs& inputs) -> SReserveResult
2165
2198
}
2166
2199
}
2167
2200
);
2201
+ // special pass to propagate Motion Acceleration Structure flag upwards from BLAS to referencing TLAS
2202
+ std::get<dfs_cache<ICPUTopLevelAccelerationStructure>>(dfsCaches).for_each ([device,&inputs,&dfsCaches](const instance_t <ICPUTopLevelAccelerationStructure>& assetInstance, dfs_cache<ICPUTopLevelAccelerationStructure>::created_t & created)->void
2203
+ {
2204
+ auto & patch = created.patch ;
2205
+ // we already have motion, can stop searching
2206
+ if (patch.isMotion )
2207
+ return ;
2208
+ auto visitor = AssetVisitor<CheckBLASPatchMotions>{
2209
+ {
2210
+ .inputs = inputs,
2211
+ .visitedBLASes = std::get<dfs_cache<ICPUBottomLevelAccelerationStructure>>(dfsCaches)
2212
+ },
2213
+ // construct a casted instance type
2214
+ {assetInstance.asset ,assetInstance.uniqueCopyGroupID },
2215
+ patch
2216
+ };
2217
+ // don't care about success, I've abused the termination criteria, will return false sometimes
2218
+ visitor ();
2219
+ // I don't need to check if the new patch is valid, because we checked if the Motion Raytracing feature is enabled when checking BLASes for validity
2220
+ patch.isMotion = visitor.isMotion ;
2221
+ }
2222
+ );
2168
2223
}
2169
2224
// ! `inputsMetadata` is now constant!
2170
2225
// ! `dfsCache` keys are now constant!
0 commit comments