Diligent Engine  v.2.4.g
ShaderBindingTableBase.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
32 
33 #include <unordered_map>
34 #include <cstring>
35 
36 #include "ShaderBindingTable.h"
37 #include "TopLevelASBase.hpp"
38 #include "DeviceObjectBase.hpp"
39 #include "RenderDeviceBase.hpp"
40 #include "StringPool.hpp"
41 #include "HashUtils.hpp"
42 
43 namespace Diligent
44 {
45 
47 void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc, Uint32 ShaderGroupHandleSize, Uint32 MaxShaderRecordStride) noexcept(false);
48 
50 
52 template <typename EngineImplTraits>
53 class ShaderBindingTableBase : public DeviceObjectBase<typename EngineImplTraits::ShaderBindingTableInterface, typename EngineImplTraits::RenderDeviceImplType, ShaderBindingTableDesc>
54 {
55 public:
56  // Base interface this class inherits (IShaderBindingTableD3D12, IShaderBindingTableVk, etc.)
57  using BaseInterface = typename EngineImplTraits::ShaderBindingTableInterface;
58 
59  // Render device implementation type (RenderDeviceD3D12Impl, RenderDeviceVkImpl, etc.).
60  using RenderDeviceImplType = typename EngineImplTraits::RenderDeviceImplType;
61 
62  // Pipeline state implementation type (PipelineStateD3D12Impl, PipelineStateVkImpl, etc.).
63  using PipelineStateImplType = typename EngineImplTraits::PipelineStateImplType;
64 
65  // Top-level AS implementation type (TopLevelASD3D12Impl, TopLevelASVkImpl, etc.).
66  using TopLevelASImplType = typename EngineImplTraits::TopLevelASImplType;
67 
68  // Buffer implementation type (BufferVkImpl, BufferD3D12Impl, etc.).
69  using BufferImplType = typename EngineImplTraits::BufferImplType;
70 
72 
79  RenderDeviceImplType* pDevice,
80  const ShaderBindingTableDesc& Desc,
81  bool bIsDeviceInternal = false) :
82  TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
83  {
84  const auto& DeviceProps = this->m_pDevice->GetProperties();
85  ValidateShaderBindingTableDesc(this->m_Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride);
86 
87  this->m_pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
88  this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize;
89  this->m_ShaderRecordStride = this->m_ShaderRecordSize + DeviceProps.ShaderGroupHandleSize;
90  }
91 
93  {
94  }
95 
97 
98 
99  void DILIGENT_CALL_TYPE Reset(IPipelineState* pPSO) override final
100  {
101 #ifdef DILIGENT_DEVELOPMENT
102  this->m_DbgHitGroupBindings.clear();
103 #endif
104  this->m_RayGenShaderRecord.clear();
105  this->m_MissShadersRecord.clear();
106  this->m_CallableShadersRecord.clear();
107  this->m_HitGroupsRecord.clear();
108  this->m_Changed = true;
109  this->m_pPSO = nullptr;
110 
111  this->m_Desc.pPSO = pPSO;
112 
113  const auto& DeviceProps = this->m_pDevice->GetProperties();
114  try
115  {
116  ValidateShaderBindingTableDesc(this->m_Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride);
117  }
118  catch (const std::runtime_error&)
119  {
120  return;
121  }
122 
123  this->m_pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
124  this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize;
125  this->m_ShaderRecordStride = this->m_ShaderRecordSize + DeviceProps.ShaderGroupHandleSize;
126  }
127 
128 
129  void DILIGENT_CALL_TYPE ResetHitGroups() override final
130  {
131 #ifdef DILIGENT_DEVELOPMENT
132  this->m_DbgHitGroupBindings.clear();
133 #endif
134  this->m_HitGroupsRecord.clear();
135  this->m_Changed = true;
136  }
137 
138 
139  void DILIGENT_CALL_TYPE BindRayGenShader(const char* pShaderGroupName, const void* pData, Uint32 DataSize) override final
140  {
141  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
142  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
143 
145  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride);
146 
147  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
148  std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, pData, DataSize);
149  this->m_Changed = true;
150  }
151 
152 
153  void DILIGENT_CALL_TYPE BindMissShader(const char* pShaderGroupName, Uint32 MissIndex, const void* pData, Uint32 DataSize) override final
154  {
155  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
156  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
157 
158  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
159  const size_t Stride = this->m_ShaderRecordStride;
160  const size_t Offset = MissIndex * Stride;
161  this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + Stride), Uint8{EmptyElem});
162 
163  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_MissShadersRecord.data() + Offset, Stride);
164  std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, pData, DataSize);
165  this->m_Changed = true;
166  }
167 
168 
170  const char* pShaderGroupName,
171  const void* pData,
172  Uint32 DataSize) override final
173  {
174  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
175  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
176 
177  const size_t Stride = this->m_ShaderRecordStride;
178  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
179  const size_t Offset = BindingIndex * Stride;
180 
181  this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + Stride), Uint8{EmptyElem});
182 
183  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride);
184  std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
185  this->m_Changed = true;
186 
187 #ifdef DILIGENT_DEVELOPMENT
188  OnBindHitGroup(nullptr, BindingIndex);
189 #endif
190  }
191 
192 
194  const char* pInstanceName,
195  const char* pGeometryName,
196  Uint32 RayOffsetInHitGroupIndex,
197  const char* pShaderGroupName,
198  const void* pData,
199  Uint32 DataSize) override final
200  {
201  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
202  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
203  VERIFY_EXPR(pTLAS != nullptr);
204 
205  auto* const pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
206  const auto Info = pTLASImpl->GetBuildInfo();
207  const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName);
208 
210  VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
211  VERIFY_EXPR(Desc.ContributionToHitGroupIndex != ~0u);
212  VERIFY_EXPR(Desc.pBLAS != nullptr);
213 
214  const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex;
215  const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName);
216  VERIFY_EXPR(GeometryIndex != INVALID_INDEX);
217 
218  const Uint32 Index = InstanceOffset + GeometryIndex * Info.HitGroupStride + RayOffsetInHitGroupIndex;
219  const size_t Stride = this->m_ShaderRecordStride;
220  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
221  const size_t Offset = Index * Stride;
222 
223  this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + Stride), Uint8{EmptyElem});
224 
225  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride);
226  std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
227  this->m_Changed = true;
228 
229 #ifdef DILIGENT_DEVELOPMENT
230  VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex);
231  OnBindHitGroup(pTLASImpl, Index);
232 #endif
233  }
234 
235 
237  const char* pInstanceName,
238  Uint32 RayOffsetInHitGroupIndex,
239  const char* pShaderGroupName,
240  const void* pData,
241  Uint32 DataSize) override final
242  {
243  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
244  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
245  VERIFY_EXPR(pTLAS != nullptr);
246 
247  auto* const pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
248  const auto Info = pTLASImpl->GetBuildInfo();
249  const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName);
250 
251  VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY ||
252  Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE);
253  VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
254  VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX);
255  VERIFY_EXPR(Desc.pBLAS != nullptr);
256 
257  const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex;
258  Uint32 GeometryCount = 0;
259 
260  switch (Info.BindingMode)
261  {
262  // clang-format off
263  case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS->GetActualGeometryCount(); break;
264  case HIT_GROUP_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break;
265  default: UNEXPECTED("unknown binding mode");
266  // clang-format on
267  }
268 
269  const Uint32 BeginIndex = InstanceOffset;
270  const size_t EndIndex = InstanceOffset + GeometryCount * Info.HitGroupStride;
271  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
272  const size_t Stride = this->m_ShaderRecordStride;
273 
274  this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * Stride), Uint8{EmptyElem});
275  this->m_Changed = true;
276 
277  for (Uint32 i = 0; i < GeometryCount; ++i)
278  {
279  Uint32 Index = BeginIndex + i * Info.HitGroupStride + RayOffsetInHitGroupIndex;
280  size_t Offset = Index * Stride;
281  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride);
282 
283  std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
284 
285 #ifdef DILIGENT_DEVELOPMENT
286  VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex);
287  OnBindHitGroup(pTLASImpl, Index);
288 #endif
289  }
290  }
291 
292 
294  Uint32 RayOffsetInHitGroupIndex,
295  const char* pShaderGroupName,
296  const void* pData,
297  Uint32 DataSize) override final
298  {
299  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
300  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
301  VERIFY_EXPR(pTLAS != nullptr);
302 
303  auto* pTLASImpl = ValidatedCast<TopLevelASImplType>(pTLAS);
304  const auto Info = pTLASImpl->GetBuildInfo();
305  VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY ||
306  Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE ||
307  Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_TLAS);
308  VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride);
309 
310  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
311  const size_t Stride = this->m_ShaderRecordStride;
312  this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), (Info.LastContributionToHitGroupIndex + 1) * Stride), Uint8{EmptyElem});
313  this->m_Changed = true;
314 
315  for (Uint32 Index = RayOffsetInHitGroupIndex + Info.FirstContributionToHitGroupIndex;
316  Index <= Info.LastContributionToHitGroupIndex;
317  Index += Info.HitGroupStride)
318  {
319  const size_t Offset = Index * Stride;
320  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride);
321  std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize);
322 
323 #ifdef DILIGENT_DEVELOPMENT
324  OnBindHitGroup(pTLASImpl, Index);
325 #endif
326  }
327  }
328 
329 
330  void DILIGENT_CALL_TYPE BindCallableShader(const char* pShaderGroupName,
331  Uint32 CallableIndex,
332  const void* pData,
333  Uint32 DataSize) override final
334  {
335  VERIFY_EXPR((pData == nullptr) == (DataSize == 0));
336  VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize));
337 
338  const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
339  const size_t Offset = CallableIndex * this->m_ShaderRecordStride;
340  this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), Uint8{EmptyElem});
341 
342  this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride);
343  std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, pData, DataSize);
344  this->m_Changed = true;
345  }
346 
347 
349  {
350 #ifdef DILIGENT_DEVELOPMENT
351  static_assert(EmptyElem != 0, "must not be zero");
352 
353  const auto Stride = this->m_ShaderRecordStride;
354  const auto ShSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize;
355  const auto FindPattern = [&](const std::vector<Uint8>& Data, const char* GroupName) -> bool //
356  {
357  for (size_t i = 0; i < Data.size(); i += Stride)
358  {
360  {
361  Uint32 Count = 0;
362  for (size_t j = 0; j < ShSize; ++j)
363  Count += (Data[i + j] == EmptyElem);
364 
365  if (Count == ShSize)
366  {
367  LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: shader in '", GroupName, "'(", i / Stride, ") is not bound.");
368  return false;
369  }
370  }
371 
373  {
374  Uint32 Count = 0;
375  for (size_t j = ShSize; j < Stride; ++j)
376  Count += (Data[i + j] == EmptyElem);
377 
378  // shader record data may not be used in the shader
379  if (Count == Stride - ShSize)
380  {
381  LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: shader record data in '", GroupName, "' (", i / Stride, ") is not initialized.");
382  return false;
383  }
384  }
385  }
386  return true;
387  };
388 
389  if (m_RayGenShaderRecord.empty())
390  {
391  LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: ray generation shader is not bound.");
392  return false;
393  }
394 
396  {
397  for (size_t i = 0; i < m_DbgHitGroupBindings.size(); ++i)
398  {
399  auto& Binding = m_DbgHitGroupBindings[i];
400  auto pTLAS = Binding.pTLAS.Lock();
401  if (!Binding.IsBound)
402  {
403  LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: hit group at index (", i, ") is not bound.");
404  return false;
405  }
406  if (!pTLAS)
407  {
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.");
409  return false;
410  }
411  if (pTLAS->GetVersion() != Binding.Version)
412  {
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.");
415  return false;
416  }
417  }
418  }
419 
420  bool valid = true;
421  valid = valid && FindPattern(m_RayGenShaderRecord, "ray generation");
422  valid = valid && FindPattern(m_MissShadersRecord, "miss");
423  valid = valid && FindPattern(m_CallableShadersRecord, "callable");
424  valid = valid && FindPattern(m_HitGroupsRecord, "hit groups");
425  return valid;
426 #else
427  return true;
428 
429 #endif // DILIGENT_DEVELOPMENT
430  }
431 
432  bool HasPendingData() const { return this->m_Changed; }
433  const BufferImplType* GetInternalBuffer() const { return this->m_pBuffer; }
434 
435 protected:
437  {
438  const void* pData = nullptr;
442  };
443  void GetData(BufferImplType*& pSBTBuffer,
444  BindingTable& RaygenShaderBindingTable,
445  BindingTable& MissShaderBindingTable,
446  BindingTable& HitShaderBindingTable,
447  BindingTable& CallableShaderBindingTable)
448  {
449  const auto ShaderGroupBaseAlignment = this->m_pDevice->GetProperties().ShaderGroupBaseAlignment;
450 
451  const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 {
452  return AlignUp(static_cast<Uint32>(offset), ShaderGroupBaseAlignment);
453  };
454 
455  const Uint32 RayGenOffset = 0;
456  const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size());
457  const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size());
458  const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size());
459  const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size());
460 
461  // Recreate buffer
462  if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize)
463  {
464  m_pBuffer = nullptr;
465 
466  String BuffName = String{this->m_Desc.Name} + " - internal buffer";
467  BufferDesc BuffDesc;
468  BuffDesc.Name = BuffName.c_str();
469  BuffDesc.Usage = USAGE_DEFAULT;
470  BuffDesc.BindFlags = BIND_RAY_TRACING;
471  BuffDesc.uiSizeInBytes = BufSize;
472 
473  this->m_pDevice->CreateBuffer(BuffDesc, nullptr, m_pBuffer.template DblPtr<IBuffer>());
474  VERIFY_EXPR(m_pBuffer != nullptr);
475  }
476 
477  if (m_pBuffer == nullptr)
478  return; // Something went wrong
479 
480  pSBTBuffer = m_pBuffer;
481 
482  if (!m_RayGenShaderRecord.empty())
483  {
484  RaygenShaderBindingTable.pData = m_Changed ? m_RayGenShaderRecord.data() : nullptr;
485  RaygenShaderBindingTable.Offset = RayGenOffset;
486  RaygenShaderBindingTable.Size = static_cast<Uint32>(m_RayGenShaderRecord.size());
487  RaygenShaderBindingTable.Stride = this->m_ShaderRecordStride;
488  }
489 
490  if (!m_MissShadersRecord.empty())
491  {
492  MissShaderBindingTable.pData = m_Changed ? m_MissShadersRecord.data() : nullptr;
493  MissShaderBindingTable.Offset = MissShaderOffset;
494  MissShaderBindingTable.Size = static_cast<Uint32>(m_MissShadersRecord.size());
495  MissShaderBindingTable.Stride = this->m_ShaderRecordStride;
496  }
497 
498  if (!m_HitGroupsRecord.empty())
499  {
500  HitShaderBindingTable.pData = m_Changed ? m_HitGroupsRecord.data() : nullptr;
501  HitShaderBindingTable.Offset = HitGroupOffset;
502  HitShaderBindingTable.Size = static_cast<Uint32>(m_HitGroupsRecord.size());
503  HitShaderBindingTable.Stride = this->m_ShaderRecordStride;
504  }
505 
506  if (!m_CallableShadersRecord.empty())
507  {
508  CallableShaderBindingTable.pData = m_Changed ? m_CallableShadersRecord.data() : nullptr;
509  CallableShaderBindingTable.Offset = CallableShadersOffset;
510  CallableShaderBindingTable.Size = static_cast<Uint32>(m_CallableShadersRecord.size());
511  CallableShaderBindingTable.Stride = this->m_ShaderRecordStride;
512  }
513 
514  m_Changed = false;
515  }
516 
517 protected:
518  std::vector<Uint8> m_RayGenShaderRecord;
519  std::vector<Uint8> m_MissShadersRecord;
520  std::vector<Uint8> m_CallableShadersRecord;
521  std::vector<Uint8> m_HitGroupsRecord;
522 
525 
528  bool m_Changed = true;
529 
530 #ifdef DILIGENT_DEVELOPMENT
531  static constexpr Uint8 EmptyElem = 0xA7;
532 #else
533  // In release mode clear uninitialized data by zeros.
534  // This makes shader inactive, wich hides errors but prevents crashes.
535  static constexpr Uint8 EmptyElem = 0;
536 #endif
537 
538 private:
539 #ifdef DILIGENT_DEVELOPMENT
540  struct HitGroupBinding
541  {
543  Uint32 Version = ~0u;
544  bool IsBound = false;
545  };
546  mutable std::vector<HitGroupBinding> m_DbgHitGroupBindings;
547 
548  void OnBindHitGroup(TopLevelASImplType* pTLAS, size_t Index)
549  {
550  this->m_DbgHitGroupBindings.resize(std::max(this->m_DbgHitGroupBindings.size(), Index + 1));
551 
552  auto& Binding = this->m_DbgHitGroupBindings[Index];
553  Binding.pTLAS = pTLAS;
554  Binding.Version = pTLAS ? pTLAS->GetVersion() : ~0u;
555  Binding.IsBound = true;
556  }
557 #endif
558 };
559 
560 } // namespace Diligent
Diligent::ShaderBindingTableBase::BindHitGroupForGeometry
void BindHitGroupForGeometry(ITopLevelAS *pTLAS, const char *pInstanceName, const char *pGeometryName, Uint32 RayOffsetInHitGroupIndex, const char *pShaderGroupName, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:193
Diligent::ShaderBindingTableBase::m_Changed
bool m_Changed
Definition: ShaderBindingTableBase.hpp:528
Diligent::ShaderBindingTableBase::Verify
Bool Verify(VERIFY_SBT_FLAGS Flags) const override final
Definition: ShaderBindingTableBase.hpp:348
Diligent::IReferenceCounters
Base interface for a reference counter object that stores the number of strong and weak references an...
Definition: ReferenceCounters.h:44
Diligent::DeviceObjectBase< EngineImplTraits::ShaderBindingTableInterface, EngineImplTraits::RenderDeviceImplType, ShaderBindingTableDesc >::m_pDevice
EngineImplTraits::RenderDeviceImplType *const m_pDevice
Pointer to the device.
Definition: DeviceObjectBase.hpp:179
Diligent::BufferDesc::uiSizeInBytes
Uint32 uiSizeInBytes
Size of the buffer, in bytes. For a uniform buffer, this must be multiple of 16.
Definition: Buffer.h:77
Diligent::ShaderBindingTableBase::BindMissShader
void BindMissShader(const char *pShaderGroupName, Uint32 MissIndex, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:153
Diligent::ShaderBindingTableBase::m_CallableShadersRecord
std::vector< Uint8 > m_CallableShadersRecord
Definition: ShaderBindingTableBase.hpp:520
Diligent::ShaderBindingTableBase::BindRayGenShader
void BindRayGenShader(const char *pShaderGroupName, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:139
DeviceObjectBase.hpp
Diligent::ValidateShaderBindingTableDesc
void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc &Desc, Uint32 ShaderGroupHandleSize, Uint32 MaxShaderRecordStride) noexcept(false)
Validates SBT description and throws an exception in case of an error.
Definition: ShaderBindingTableBase.cpp:33
Diligent::IPipelineState
Pipeline state interface.
Definition: PipelineState.h:505
Diligent::HIT_GROUP_BINDING_MODE_PER_GEOMETRY
@ HIT_GROUP_BINDING_MODE_PER_GEOMETRY
Each geometry in every instance may use a unique hit shader group. In this mode, the SBT reserves spa...
Definition: TopLevelAS.h:78
Diligent::ShaderBindingTableBase::~ShaderBindingTableBase
~ShaderBindingTableBase()
Definition: ShaderBindingTableBase.hpp:92
Flags
Uint32 Flags
Definition: DXBCUtils.cpp:71
Diligent::ShaderBindingTableBase::m_HitGroupsRecord
std::vector< Uint8 > m_HitGroupsRecord
Definition: ShaderBindingTableBase.hpp:521
Diligent::RefCntWeakPtr
Implementation of weak pointers.
Definition: RefCntAutoPtr.hpp:40
Diligent::ITopLevelAS
Top-level AS interface.
Definition: TopLevelAS.h:151
UNEXPECTED
#define UNEXPECTED(...)
Definition: DebugUtilities.hpp:77
Diligent::ShaderBindingTableDesc
struct ShaderBindingTableDesc ShaderBindingTableDesc
Definition: ShaderBindingTable.h:59
Diligent::BufferDesc::BindFlags
BIND_FLAGS BindFlags
Buffer bind flags, see Diligent::BIND_FLAGS for details.
Definition: Buffer.h:85
Diligent::DeviceObjectBase< EngineImplTraits::ShaderBindingTableInterface, EngineImplTraits::RenderDeviceImplType, ShaderBindingTableDesc >::m_Desc
ShaderBindingTableDesc m_Desc
Object description.
Definition: DeviceObjectBase.hpp:182
Diligent::ShaderBindingTableBase::BindHitGroupForInstance
void BindHitGroupForInstance(ITopLevelAS *pTLAS, const char *pInstanceName, Uint32 RayOffsetInHitGroupIndex, const char *pShaderGroupName, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:236
Diligent::ShaderBindingTableBase::m_RayGenShaderRecord
std::vector< Uint8 > m_RayGenShaderRecord
Definition: ShaderBindingTableBase.hpp:518
Diligent::ShaderBindingTableBase< EngineD3D12ImplTraits >::RenderDeviceImplType
typename EngineD3D12ImplTraits ::RenderDeviceImplType RenderDeviceImplType
Definition: ShaderBindingTableBase.hpp:60
Diligent::ShaderBindingTableBase< EngineD3D12ImplTraits >::TopLevelASImplType
typename EngineD3D12ImplTraits ::TopLevelASImplType TopLevelASImplType
Definition: ShaderBindingTableBase.hpp:66
RenderDeviceBase.hpp
Diligent::ShaderBindingTableBase::BindCallableShader
void BindCallableShader(const char *pShaderGroupName, Uint32 CallableIndex, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:330
Diligent::ShaderBindingTableBase::BindingTable::pData
const void * pData
Definition: ShaderBindingTableBase.hpp:438
Diligent::ShaderBindingTableDesc
Shader binding table description.
Definition: ShaderBindingTable.h:50
Diligent::ShaderBindingTableBase::m_pBuffer
RefCntAutoPtr< BufferImplType > m_pBuffer
Definition: ShaderBindingTableBase.hpp:524
ShaderBindingTable.h
Diligent::ShaderBindingTableBase::BindingTable
Definition: ShaderBindingTableBase.hpp:436
Diligent::ShaderBindingTableBase::Reset
void Reset(IPipelineState *pPSO) override final
Definition: ShaderBindingTableBase.hpp:99
Diligent::DescriptorType::Count
@ Count
Diligent::ShaderBindingTableBase::BindingTable::Offset
Uint32 Offset
Definition: ShaderBindingTableBase.hpp:440
LOG_INFO_MESSAGE
#define LOG_INFO_MESSAGE(...)
Definition: Errors.hpp:124
Diligent::ShaderBindingTableBase::TDeviceObjectBase
DeviceObjectBase< BaseInterface, RenderDeviceImplType, ShaderBindingTableDesc > TDeviceObjectBase
Definition: ShaderBindingTableBase.hpp:71
IMPLEMENT_QUERY_INTERFACE_IN_PLACE
#define IMPLEMENT_QUERY_INTERFACE_IN_PLACE(InterfaceID, ParentClassName)
Definition: ObjectBase.hpp:59
Diligent::RefCntAutoPtr< PipelineStateImplType >
Diligent::ShaderBindingTableBase::BindHitGroupByIndex
void BindHitGroupByIndex(Uint32 BindingIndex, const char *pShaderGroupName, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:169
DILIGENT_CALL_TYPE
#define DILIGENT_CALL_TYPE
Definition: CommonDefinitions.h:45
Diligent::ShaderBindingTableBase::ResetHitGroups
void ResetHitGroups() override final
Definition: ShaderBindingTableBase.hpp:129
Diligent::ShaderBindingTableBase::GetData
void GetData(BufferImplType *&pSBTBuffer, BindingTable &RaygenShaderBindingTable, BindingTable &MissShaderBindingTable, BindingTable &HitShaderBindingTable, BindingTable &CallableShaderBindingTable)
Definition: ShaderBindingTableBase.hpp:443
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
Diligent::Bool
bool Bool
Boolean.
Definition: BasicTypes.h:59
Diligent::ShaderBindingTableBase::m_MissShadersRecord
std::vector< Uint8 > m_MissShadersRecord
Definition: ShaderBindingTableBase.hpp:519
Diligent::ShaderBindingTableBase::m_ShaderRecordStride
Uint32 m_ShaderRecordStride
Definition: ShaderBindingTableBase.hpp:527
Diligent::ShaderBindingTableBase
Template class implementing base functionality of the shader binding table object.
Definition: ShaderBindingTableBase.hpp:53
Diligent::ShaderBindingTableBase< EngineD3D12ImplTraits >::BaseInterface
typename EngineD3D12ImplTraits ::ShaderBindingTableInterface BaseInterface
Definition: ShaderBindingTableBase.hpp:57
Diligent::BufferDesc
Buffer description.
Definition: Buffer.h:74
HashUtils.hpp
Diligent::VERIFY_SBT_FLAG_SHADER_ONLY
@ VERIFY_SBT_FLAG_SHADER_ONLY
Check that all shaders are bound or inactive.
Definition: ShaderBindingTable.h:66
Diligent::HIT_GROUP_BINDING_MODE_PER_TLAS
@ HIT_GROUP_BINDING_MODE_PER_TLAS
All instances in each TLAS will use the same hit group. In this mode, the SBT reserves a single slot ...
Definition: TopLevelAS.h:90
Diligent::VERIFY_SBT_FLAG_TLAS
@ VERIFY_SBT_FLAG_TLAS
Check that all TLASes that were used in the SBT are alive and shader binding indices have not changed...
Definition: ShaderBindingTable.h:73
Diligent::ShaderBindingTableBase::m_pPSO
RefCntAutoPtr< PipelineStateImplType > m_pPSO
Definition: ShaderBindingTableBase.hpp:523
std::max
Diligent::Vector2< T > max(const Diligent::Vector2< T > &Left, const Diligent::Vector2< T > &Right)
Definition: BasicMath.hpp:2261
Diligent::Uint8
uint8_t Uint8
8-bit unsigned integer
Definition: BasicTypes.h:53
Diligent::String
std::basic_string< Char > String
String variable.
Definition: BasicTypes.h:66
VERIFY_EXPR
#define VERIFY_EXPR(...)
Definition: DebugUtilities.hpp:79
Diligent::ShaderBindingTableBase< EngineD3D12ImplTraits >::PipelineStateImplType
typename EngineD3D12ImplTraits ::PipelineStateImplType PipelineStateImplType
Definition: ShaderBindingTableBase.hpp:63
Diligent::ShaderBindingTableDesc::pPSO
IPipelineState * pPSO
Ray tracing pipeline state object from which shaders will be taken.
Definition: ShaderBindingTable.h:53
StringPool.hpp
Diligent::BufferDesc::Usage
USAGE Usage
Buffer usage, see Diligent::USAGE for details.
Definition: Buffer.h:88
Diligent::VERIFY_SBT_FLAGS
VERIFY_SBT_FLAGS
Defines shader binding table validation flags, see IShaderBindingTable::Verify().
Definition: ShaderBindingTable.h:63
Diligent::AlignUp
T2 ::type AlignUp(T1 val, T2 alignment)
Definition: Align.hpp:47
Diligent::ShaderBindingTableBase::BindingTable::Stride
Uint32 Stride
Definition: ShaderBindingTableBase.hpp:441
Diligent::BIND_RAY_TRACING
@ BIND_RAY_TRACING
A buffer can be used as a scratch buffer or as the source of primitive data for acceleration structur...
Definition: GraphicsTypes.h:130
Diligent::ShaderBindingTableBase::m_ShaderRecordSize
Uint32 m_ShaderRecordSize
Definition: ShaderBindingTableBase.hpp:526
Diligent::ShaderBindingTableBase::BindHitGroupForTLAS
void BindHitGroupForTLAS(ITopLevelAS *pTLAS, Uint32 RayOffsetInHitGroupIndex, const char *pShaderGroupName, const void *pData, Uint32 DataSize) override final
Definition: ShaderBindingTableBase.hpp:293
Diligent::ShaderBindingTableBase::EmptyElem
static constexpr Uint8 EmptyElem
Definition: ShaderBindingTableBase.hpp:535
Diligent::VERIFY_SBT_FLAG_SHADER_RECORD
@ VERIFY_SBT_FLAG_SHADER_RECORD
Check that shader record data are initialized.
Definition: ShaderBindingTable.h:69
Diligent::ShaderBindingTableBase::ShaderBindingTableBase
ShaderBindingTableBase(IReferenceCounters *pRefCounters, RenderDeviceImplType *pDevice, const ShaderBindingTableDesc &Desc, bool bIsDeviceInternal=false)
Definition: ShaderBindingTableBase.hpp:78
Diligent::ShaderBindingTableBase::BindingTable::Size
Uint32 Size
Definition: ShaderBindingTableBase.hpp:439
Diligent::HIT_GROUP_BINDING_MODE_PER_INSTANCE
@ HIT_GROUP_BINDING_MODE_PER_INSTANCE
Each instance may use a unique hit shader group. In this mode, the SBT reserves one slot for each ins...
Definition: TopLevelAS.h:84
TopLevelASBase.hpp
Diligent::ShaderBindingTableBase::HasPendingData
bool HasPendingData() const
Definition: ShaderBindingTableBase.hpp:432
Diligent::ShaderBindingTableBase< EngineD3D12ImplTraits >::BufferImplType
typename EngineD3D12ImplTraits ::BufferImplType BufferImplType
Definition: ShaderBindingTableBase.hpp:69
Diligent::DeviceObjectAttribs::Name
const Char * Name
Object name.
Definition: GraphicsTypes.h:1199
Diligent::DeviceObjectBase
Template class implementing base functionality of the device object.
Definition: DeviceObjectBase.hpp:45
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37
Diligent::ShaderBindingTableBase::GetInternalBuffer
const BufferImplType * GetInternalBuffer() const
Definition: ShaderBindingTableBase.hpp:433
Diligent::USAGE_DEFAULT
@ USAGE_DEFAULT
A resource that requires read and write access by the GPU and can also be occasionally written by the...
Definition: GraphicsTypes.h:156