33 #include <unordered_map>
52 template <
typename EngineImplTraits>
57 using BaseInterface =
typename EngineImplTraits::ShaderBindingTableInterface;
81 bool bIsDeviceInternal =
false) :
84 const auto& DeviceProps = this->
m_pDevice->GetProperties();
101 #ifdef DILIGENT_DEVELOPMENT
102 this->m_DbgHitGroupBindings.clear();
113 const auto& DeviceProps = this->
m_pDevice->GetProperties();
118 catch (
const std::runtime_error&)
131 #ifdef DILIGENT_DEVELOPMENT
132 this->m_DbgHitGroupBindings.clear();
141 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
147 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
155 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
158 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
160 const size_t Offset = MissIndex * Stride;
170 const char* pShaderGroupName,
172 Uint32 DataSize)
override final
174 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
178 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
179 const size_t Offset = BindingIndex * Stride;
184 std::memcpy(this->
m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
187 #ifdef DILIGENT_DEVELOPMENT
188 OnBindHitGroup(
nullptr, BindingIndex);
194 const char* pInstanceName,
195 const char* pGeometryName,
196 Uint32 RayOffsetInHitGroupIndex,
197 const char* pShaderGroupName,
199 Uint32 DataSize)
override final
201 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
205 auto*
const pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
206 const auto Info = pTLASImpl->GetBuildInfo();
207 const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName);
210 VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
211 VERIFY_EXPR(Desc.ContributionToHitGroupIndex != ~0u);
214 const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex;
215 const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName);
218 const Uint32 Index = InstanceOffset + GeometryIndex * Info.HitGroupStride + RayOffsetInHitGroupIndex;
220 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
221 const size_t Offset = Index * Stride;
226 std::memcpy(this->
m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
229 #ifdef DILIGENT_DEVELOPMENT
230 VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex);
231 OnBindHitGroup(pTLASImpl, Index);
237 const char* pInstanceName,
238 Uint32 RayOffsetInHitGroupIndex,
239 const char* pShaderGroupName,
241 Uint32 DataSize)
override final
243 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
247 auto*
const pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
248 const auto Info = pTLASImpl->GetBuildInfo();
249 const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName);
253 VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
254 VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX);
257 const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex;
260 switch (Info.BindingMode)
269 const Uint32 BeginIndex = InstanceOffset;
270 const size_t EndIndex = InstanceOffset + GeometryCount * Info.HitGroupStride;
271 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
277 for (
Uint32 i = 0; i < GeometryCount; ++i)
279 Uint32 Index = BeginIndex + i * Info.HitGroupStride + RayOffsetInHitGroupIndex;
280 size_t Offset = Index * Stride;
283 std::memcpy(this->
m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
285 #ifdef DILIGENT_DEVELOPMENT
286 VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex);
287 OnBindHitGroup(pTLASImpl, Index);
294 Uint32 RayOffsetInHitGroupIndex,
295 const char* pShaderGroupName,
297 Uint32 DataSize)
override final
299 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
303 auto* pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
304 const auto Info = pTLASImpl->GetBuildInfo();
308 VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
310 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
315 for (
Uint32 Index = RayOffsetInHitGroupIndex + Info.FirstContributionToHitGroupIndex;
316 Index <= Info.LastContributionToHitGroupIndex;
317 Index += Info.HitGroupStride)
319 const size_t Offset = Index * Stride;
321 std::memcpy(this->
m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
323 #ifdef DILIGENT_DEVELOPMENT
324 OnBindHitGroup(pTLASImpl, Index);
333 Uint32 DataSize)
override final
335 VERIFY_EXPR((pData ==
nullptr) == (DataSize == 0));
338 const Uint32 GroupSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
350 #ifdef DILIGENT_DEVELOPMENT
351 static_assert(
EmptyElem != 0,
"must not be zero");
354 const auto ShSize = this->
m_pDevice->GetProperties().ShaderGroupHandleSize;
355 const auto FindPattern = [&](
const std::vector<Uint8>& Data,
const char* GroupName) ->
bool
357 for (
size_t i = 0; i < Data.size(); i += Stride)
362 for (
size_t j = 0; j < ShSize; ++j)
367 LOG_INFO_MESSAGE(
"Shader binding table '", this->
m_Desc.
Name,
"' is not valid: shader in '", GroupName,
"'(", i / Stride,
") is not bound.");
375 for (
size_t j = ShSize; j < Stride; ++j)
379 if (
Count == Stride - ShSize)
381 LOG_INFO_MESSAGE(
"Shader binding table '", this->
m_Desc.
Name,
"' is not valid: shader record data in '", GroupName,
"' (", i / Stride,
") is not initialized.");
397 for (
size_t i = 0; i < m_DbgHitGroupBindings.size(); ++i)
399 auto& Binding = m_DbgHitGroupBindings[i];
400 auto pTLAS = Binding.pTLAS.Lock();
401 if (!Binding.IsBound)
408 LOG_INFO_MESSAGE(
"Shader binding table '", this->
m_Desc.
Name,
"' is not valid: TLAS that was used to bind hit group at index (", i,
") was deleted.");
411 if (pTLAS->GetVersion() != Binding.Version)
413 LOG_INFO_MESSAGE(
"Shader binding table '", this->
m_Desc.
Name,
"' is not valid: TLAS that was used to bind hit group at index '(", i,
414 ") with name '", pTLAS->GetDesc().Name,
" was changed and no longer compatible with SBT.");
429 #endif // DILIGENT_DEVELOPMENT
444 BindingTable& RaygenShaderBindingTable,
445 BindingTable& MissShaderBindingTable,
446 BindingTable& HitShaderBindingTable,
447 BindingTable& CallableShaderBindingTable)
449 const auto ShaderGroupBaseAlignment = this->
m_pDevice->GetProperties().ShaderGroupBaseAlignment;
451 const auto AlignToLarger = [ShaderGroupBaseAlignment](
size_t offset) ->
Uint32 {
452 return AlignUp(
static_cast<Uint32>(offset), ShaderGroupBaseAlignment);
455 const Uint32 RayGenOffset = 0;
468 BuffDesc.
Name = BuffName.c_str();
473 this->
m_pDevice->CreateBuffer(BuffDesc,
nullptr,
m_pBuffer.template DblPtr<IBuffer>());
485 RaygenShaderBindingTable.Offset = RayGenOffset;
493 MissShaderBindingTable.Offset = MissShaderOffset;
501 HitShaderBindingTable.Offset = HitGroupOffset;
509 CallableShaderBindingTable.Offset = CallableShadersOffset;
530 #ifdef DILIGENT_DEVELOPMENT
539 #ifdef DILIGENT_DEVELOPMENT
540 struct HitGroupBinding
544 bool IsBound =
false;
546 mutable std::vector<HitGroupBinding> m_DbgHitGroupBindings;
550 this->m_DbgHitGroupBindings.resize(
std::max(this->m_DbgHitGroupBindings.size(), Index + 1));
552 auto& Binding = this->m_DbgHitGroupBindings[Index];
553 Binding.pTLAS = pTLAS;
554 Binding.Version = pTLAS ? pTLAS->GetVersion() : ~0u;
555 Binding.IsBound =
true;