summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-11-05 00:43:05 +0000
committerazhirnov <zh1dron@gmail.com>2020-11-05 00:53:36 +0000
commit5e81b867be771dc7f2add0d7b403af4aeaa744db (patch)
tree0f1f3835149f8887d80d558203956fcdbb233f60 /Graphics/GraphicsEngine
parentfixed compilation (diff)
downloadDiligentCore-5e81b867be771dc7f2add0d7b403af4aeaa744db.tar.gz
DiligentCore-5e81b867be771dc7f2add0d7b403af4aeaa744db.zip
Added AS copy with compacting.
Added UB & SB size checks for Vulkan. Some improvements for ray tracing & tests.
Diffstat (limited to 'Graphics/GraphicsEngine')
-rw-r--r--Graphics/GraphicsEngine/include/BottomLevelASBase.hpp247
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp341
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp8
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp126
-rw-r--r--Graphics/GraphicsEngine/include/TopLevelASBase.hpp142
-rw-r--r--Graphics/GraphicsEngine/interface/BottomLevelAS.h67
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h410
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h7
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h86
-rw-r--r--Graphics/GraphicsEngine/interface/Shader.h2
-rw-r--r--Graphics/GraphicsEngine/interface/ShaderBindingTable.h10
-rw-r--r--Graphics/GraphicsEngine/interface/TopLevelAS.h40
12 files changed, 1072 insertions, 414 deletions
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
index 2bdd51dc..5a6db4bd 100644
--- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
@@ -36,7 +36,7 @@
#include "BottomLevelAS.h"
#include "DeviceObjectBase.hpp"
#include "RenderDeviceBase.hpp"
-#include "StringPool.hpp"
+#include "LinearAllocator.hpp"
#include "HashUtils.hpp"
namespace Diligent
@@ -67,84 +67,21 @@ public:
{
ValidateBottomLevelASDesc(Desc);
- // Memory must be released if an exception is thrown.
- auto RawMemDeleter = [](void* ptr) {
- if (ptr != nullptr)
- GetRawAllocator().Free(ptr);
- };
-
- if (Desc.pTriangles != nullptr)
+ if (Desc.CompactedSize > 0)
+ {}
+ else
{
- size_t StringPoolSize = 0;
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
- {
- if (Desc.pTriangles[i].GeometryName == nullptr)
- LOG_ERROR_AND_THROW("Geometry name can not be null!");
-
- StringPoolSize += strlen(Desc.pTriangles[i].GeometryName) + 1;
- }
-
- m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
-
- std::unique_ptr<BLASTriangleDesc[], decltype(RawMemDeleter)> pTriangles{
- ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount),
- RawMemDeleter};
-
- std::memcpy(pTriangles.get(), Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount);
- this->m_Desc.pBoxes = nullptr;
-
- // copy strings
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
- {
- pTriangles[i].GeometryName = m_StringPool.CopyString(pTriangles[i].GeometryName);
- bool IsUniqueName = m_NameToIndex.emplace(pTriangles[i].GeometryName, i).second;
- if (!IsUniqueName)
- LOG_ERROR_AND_THROW("Geometry name must be unique!");
- }
- this->m_Desc.pTriangles = pTriangles.release();
+ LinearAllocator MemPool{GetRawAllocator()};
+ CopyDescription(Desc, this->m_Desc, MemPool, m_NameToIndex);
+ this->m_pRawPtr = MemPool.ReleaseOwnership();
}
- else if (Desc.pBoxes != nullptr)
- {
- size_t StringPoolSize = 0;
- for (Uint32 i = 0; i < Desc.BoxCount; ++i)
- {
- if (Desc.pBoxes[i].GeometryName == nullptr)
- LOG_ERROR_AND_THROW("Geometry name can not be null!");
-
- StringPoolSize += strlen(Desc.pBoxes[i].GeometryName) + 1;
- }
-
- m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
-
- std::unique_ptr<BLASBoundingBoxDesc[], decltype(RawMemDeleter)> pBoxes{
- ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount),
- RawMemDeleter};
-
- std::memcpy(pBoxes.get(), Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount);
- this->m_Desc.pTriangles = nullptr;
-
- // copy strings
- for (Uint32 i = 0; i < Desc.BoxCount; ++i)
- {
- pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName);
- bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second;
- if (!IsUniqueName)
- LOG_ERROR_AND_THROW("Geometry name must be unique!");
- }
- this->m_Desc.pBoxes = pBoxes.release();
- }
- VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0);
}
~BottomLevelASBase()
{
- if (this->m_Desc.pTriangles != nullptr)
+ if (this->m_pRawPtr)
{
- GetRawAllocator().Free(const_cast<BLASTriangleDesc*>(this->m_Desc.pTriangles));
- }
- if (this->m_Desc.pBoxes != nullptr)
- {
- GetRawAllocator().Free(const_cast<BLASBoundingBoxDesc*>(this->m_Desc.pBoxes));
+ GetRawAllocator().Free(this->m_pRawPtr);
}
}
@@ -164,6 +101,8 @@ public:
virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
{
+ VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE,
+ "Unsupported state for bottom-level acceleration structure");
this->m_State = State;
}
@@ -184,6 +123,36 @@ public:
return (this->m_State & State) == State;
}
+ void CopyDescription(const BottomLevelASBase& Src)
+ {
+ const auto& SrcDesc = Src.GetDesc();
+ auto& DstDesc = this->m_Desc;
+
+ try
+ {
+ if (this->m_pRawPtr)
+ {
+ GetRawAllocator().Free(this->m_pRawPtr);
+ this->m_pRawPtr = nullptr;
+ }
+ m_NameToIndex.clear();
+
+ DstDesc.TriangleCount = SrcDesc.TriangleCount;
+ DstDesc.BoxCount = SrcDesc.BoxCount;
+
+ LinearAllocator MemPool{GetRawAllocator()};
+ CopyDescription(SrcDesc, DstDesc, MemPool, m_NameToIndex);
+ this->m_pRawPtr = MemPool.ReleaseOwnership();
+ }
+ catch (...)
+ {
+ // memory for arrays is not allocated or have been freed
+ DstDesc.pTriangles = nullptr;
+ DstDesc.pBoxes = nullptr;
+ m_NameToIndex.clear();
+ }
+ }
+
#ifdef DILIGENT_DEVELOPMENT
void UpdateVersion()
{
@@ -194,29 +163,143 @@ public:
{
return m_Version.load();
}
-#endif
+
+ bool ValidateContent() const
+ {
+ return true;
+ }
+#endif // DILIGENT_DEVELOPMENT
protected:
static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc)
{
#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)
- if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr)))
+ if (Desc.CompactedSize > 0)
{
- LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined");
- }
+ if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr)
+ LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then pTriangles and pBoxes must be null");
- if (Desc.pBoxes == nullptr && Desc.BoxCount > 0)
+ if (Desc.Flags != RAYTRACING_BUILD_AS_NONE)
+ LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE");
+ }
+ else
{
- LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0");
+ if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr)))
+ LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined");
+
+ if (Desc.pBoxes == nullptr && Desc.BoxCount > 0)
+ LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0");
+
+ if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0");
+
+ if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD))
+ LOG_BLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD");
+
+#ifdef DILIGENT_DEVELOPMENT
+ for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
+ {
+ const auto& tri = Desc.pTriangles[i];
+
+ if (tri.GeometryName == nullptr)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null");
+
+ if (tri.VertexValueType >= VT_NUM_TYPES)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be valid type");
+
+ if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3");
+
+ if (tri.MaxVertexCount == 0)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater then 0");
+
+ if (tri.MaxPrimitiveCount == 0)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater then 0");
+
+ if (tri.IndexType == VT_UNDEFINED)
+ {
+ if (tri.MaxVertexCount != tri.MaxPrimitiveCount * 3)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must equal to (MaxPrimitiveCount * 3)");
+ }
+ else
+ {
+ if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16)
+ LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType must be VT_UINT16 or VT_UINT32");
+ }
+ }
+
+ for (Uint32 i = 0; i < Desc.BoxCount; ++i)
+ {
+ const auto& box = Desc.pBoxes[i];
+
+ if (box.GeometryName == nullptr)
+ LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].GeometryName must not be null");
+
+ if (box.MaxBoxCount == 0)
+ LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].MaxBoxCount must be greater then 0");
+ }
+#endif // DILIGENT_DEVELOPMENT
}
- if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0)
+#undef LOG_BLAS_ERROR_AND_THROW
+ }
+
+ static void CopyDescription(const BottomLevelASDesc& SrcDesc,
+ BottomLevelASDesc& DstDesc,
+ LinearAllocator& MemPool,
+ std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>& NameToIndex)
+ {
+ if (SrcDesc.pTriangles != nullptr)
{
- LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0");
+ MemPool.AddSpace<decltype(*SrcDesc.pTriangles)>(SrcDesc.TriangleCount);
+
+ for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i)
+ MemPool.AddSpaceForString(SrcDesc.pTriangles[i].GeometryName);
+
+ MemPool.Reserve();
+
+ auto* pTriangles = MemPool.CopyArray(SrcDesc.pTriangles, SrcDesc.TriangleCount);
+
+ // copy strings
+ for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i)
+ {
+ pTriangles[i].GeometryName = MemPool.CopyString(SrcDesc.pTriangles[i].GeometryName);
+ bool IsUniqueName = NameToIndex.emplace(SrcDesc.pTriangles[i].GeometryName, i).second;
+ if (!IsUniqueName)
+ LOG_ERROR_AND_THROW("Geometry name must be unique!");
+ }
+ DstDesc.pTriangles = pTriangles;
+ DstDesc.pBoxes = nullptr;
+ DstDesc.BoxCount = 0;
}
+ else if (SrcDesc.pBoxes != nullptr)
+ {
+ MemPool.AddSpace<decltype(*SrcDesc.pBoxes)>(SrcDesc.BoxCount);
-#undef LOG_BLAS_ERROR_AND_THROW
+ for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i)
+ MemPool.AddSpaceForString(SrcDesc.pBoxes[i].GeometryName);
+
+ MemPool.Reserve();
+
+ auto* pBoxes = MemPool.CopyArray(SrcDesc.pBoxes, SrcDesc.BoxCount);
+
+ // copy strings
+ for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i)
+ {
+ pBoxes[i].GeometryName = MemPool.CopyString(SrcDesc.pBoxes[i].GeometryName);
+ bool IsUniqueName = NameToIndex.emplace(SrcDesc.pBoxes[i].GeometryName, i).second;
+ if (!IsUniqueName)
+ LOG_ERROR_AND_THROW("Geometry name must be unique!");
+ }
+ DstDesc.pBoxes = pBoxes;
+ DstDesc.pTriangles = nullptr;
+ DstDesc.TriangleCount = 0;
+ }
+ else
+ {
+ LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null");
+ }
}
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase)
@@ -226,7 +309,7 @@ protected:
std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
- StringPool m_StringPool;
+ void* m_pRawPtr = nullptr;
#ifdef DILIGENT_DEVELOPMENT
std::atomic<Uint32> m_Version{0};
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index ba586f4b..f7abedb8 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -279,11 +279,13 @@ protected:
// clang-format on
#endif
- bool BuildBLAS(const BLASBuildAttribs& Attribs, int);
- bool BuildTLAS(const TLASBuildAttribs& Attribs, int);
- bool CopyBLAS(const CopyBLASAttribs& Attribs, int);
- bool CopyTLAS(const CopyTLASAttribs& Attribs, int);
- bool TraceRays(const TraceRaysAttribs& Attribs, int);
+ bool BuildBLAS(const BLASBuildAttribs& Attribs, int) const;
+ bool BuildTLAS(const TLASBuildAttribs& Attribs, int) const;
+ bool CopyBLAS(const CopyBLASAttribs& Attribs, int) const;
+ bool CopyTLAS(const CopyTLASAttribs& Attribs, int) const;
+ bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const;
+ bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const;
+ bool TraceRays(const TraceRaysAttribs& Attribs, int) const;
/// Strong reference to the device.
RefCntAutoPtr<DeviceImplType> m_pDevice;
@@ -1503,6 +1505,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
return true;
+ if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device");
+ return false;
+ }
+
if (!m_pPipelineState)
{
LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound.");
@@ -1521,6 +1529,11 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero.");
}
+ if (Attribs.ThreadGroupCount > m_pDevice->GetMaxDrawMeshTasksCount())
+ {
+ LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetMaxDrawMeshTasksCount());
+ }
+
return true;
}
@@ -1635,6 +1648,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
return true;
+ if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("DrawMeshIndirect: mesh shaders are not supported by this device");
+ return false;
+ }
+
if (!m_pPipelineState)
{
LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: no pipeline state is bound.");
@@ -1860,7 +1879,7 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>::
const auto& BLASDesc = pBottomLevelAS->GetDesc();
OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
- DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING,
+ DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE,
"Invlaid new state specified for BLAS '", BLASDesc.Name, "'");
DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS");
}
@@ -1951,11 +1970,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
#endif // DILIGENT_DEVELOPMENT
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLASBuildAttribs& Attribs, int)
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLASBuildAttribs& Attribs, int) const
{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device");
+ return false;
+ }
+
if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("BuildBLAS command must be performed outside of render pass");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass");
return false;
}
@@ -1989,22 +2014,51 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
+ const auto& BLASDesc = Attribs.pBLAS->GetDesc();
+
+ if (Attribs.BoxDataCount > BLASDesc.BoxCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount");
+ return false;
+ }
+
+ if (Attribs.TriangleDataCount > BLASDesc.TriangleCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount");
+ return false;
+ }
+
#ifdef DILIGENT_DEVELOPMENT
for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
{
const auto& tri = Attribs.pTriangleData[i];
const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount;
const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount;
+ const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName);
+
+ if (GeomIndex == BottomLevelASType::InvalidGeometryIndex)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].GeometryName not found in BLAS description");
+ return false;
+ }
+
+ const auto& TriDesc = BLASDesc.pTriangles[GeomIndex];
+
+ if (tri.VertexValueType != VT_UNDEFINED && tri.VertexValueType != TriDesc.VertexValueType)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description");
+ return false;
+ }
- if (tri.VertexValueType >= VT_NUM_TYPES)
+ if (tri.VertexComponentCount != 0 && tri.VertexComponentCount != TriDesc.VertexComponentCount)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 0 or match the VertexComponentCount in geometry description");
return false;
}
- if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3)
+ if (tri.VertexCount > TriDesc.MaxVertexCount)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must not be greater then MaxVertexCount(", TriDesc.MaxVertexCount, ")");
return false;
}
@@ -2032,20 +2086,20 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
- if (tri.IndexType != VT_UNDEFINED)
+ if (tri.IndexType != VT_UNDEFINED && tri.IndexType != TriDesc.IndexType)
{
- if (tri.IndexType != VT_UINT16 && tri.IndexType != VT_UINT32)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must not be VT_UNDEFINED, VT_UINT16 or VT_UINT32");
- return false;
- }
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must match the IndexType in geometry description");
+ return false;
+ }
- if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid");
- return false;
- }
+ if (tri.PrimitiveCount > TriDesc.MaxPrimitiveCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].PrimitiveCount must not be greater then MaxPrimitiveCount(", TriDesc.MaxPrimitiveCount, ")");
+ return false;
+ }
+ if (TriDesc.IndexType != VT_UNDEFINED)
+ {
if (tri.pIndexBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null");
@@ -2058,7 +2112,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
- const Uint32 IndexDataSize = tri.IndexCount * GetValueSize(tri.IndexType);
+ const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType);
if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount");
@@ -2067,10 +2121,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
}
else
{
+ if (tri.VertexCount != tri.PrimitiveCount * 3)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must equal to (PrimitiveCount * 3)");
+ return false;
+ }
+
VERIFY(tri.pIndexBuffer == nullptr,
"IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED");
- VERIFY(tri.IndexCount == 0,
- "IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be zero if IndexType is VT_UNDEFINED");
}
if (tri.pTransformBuffer != nullptr)
@@ -2080,13 +2138,34 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+
+ if (!TriDesc.AllowsTransforms)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "] use transform buffer but AllowsTransforms is false");
+ return false;
+ }
}
}
for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
{
- const auto& box = Attribs.pBoxData[i];
- const Uint32 BoxSize = sizeof(float) * 6;
+ const auto& box = Attribs.pBoxData[i];
+ const Uint32 BoxSize = sizeof(float) * 6;
+ const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName);
+
+ if (GeomIndex == BottomLevelASType::InvalidGeometryIndex)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].GeometryName not found in BLAS description");
+ return false;
+ }
+
+ const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex];
+
+ if (box.BoxCount > BoxDesc.MaxBoxCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxCount must not be greated then MaxBoxCount (", BoxDesc.MaxBoxCount, ")");
+ return false;
+ }
if (box.BoxStride < BoxSize)
{
@@ -2108,20 +2187,6 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
}
#endif // DILIGENT_DEVELOPMENT
- const auto& BLASDesc = Attribs.pBLAS->GetDesc();
-
- if (Attribs.BoxDataCount > BLASDesc.BoxCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to Attribs.pBLAS->GetDesc().BoxCount");
- return false;
- }
-
- if (Attribs.TriangleDataCount > BLASDesc.TriangleCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to Attribs.pBLAS->GetDesc().TriangleCount");
- return false;
- }
-
const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc();
if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes)
@@ -2146,11 +2211,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLASBuildAttribs& Attribs, int)
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLASBuildAttribs& Attribs, int) const
{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device");
+ return false;
+ }
+
if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("BuildTLAS command must be performed outside of render pass");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass");
return false;
}
@@ -2201,9 +2272,11 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
// calculate instance data size
for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
{
- VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0);
- VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
- (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0);
+ VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only first 24 bits are used");
+
+ VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
+ (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0,
+ "Only first 24 bits are used");
if (Attribs.pInstances[i].InstanceName == nullptr)
{
@@ -2219,6 +2292,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
++AutoOffsetCounter;
+
+
+ if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO "
+ "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED");
+ return false;
+ }
}
if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount)
@@ -2270,8 +2351,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int)
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) const
{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device");
+ return false;
+ }
+
if (Attribs.pSrc == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null");
@@ -2286,11 +2373,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("CopyBLAS command must be performed outside of render pass");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass");
return false;
}
#ifdef DILIGENT_DEVELOPMENT
+ if (!ValidatedCast<BottomLevelASType>(Attribs.pSrc)->ValidateContent())
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid");
+ return false;
+ }
+
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2323,7 +2416,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount ||
SrcTri.VertexValueType != DstTri.VertexValueType ||
SrcTri.VertexComponentCount != DstTri.VertexComponentCount ||
- SrcTri.MaxIndexCount != DstTri.MaxIndexCount ||
+ SrcTri.MaxPrimitiveCount != DstTri.MaxPrimitiveCount ||
SrcTri.IndexType != DstTri.IndexType ||
SrcTri.AllowsTransforms != DstTri.AllowsTransforms)
// clang-format on
@@ -2342,6 +2435,23 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
}
}
}
+ else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ return false;
+ }
+
+ if (DstDesc.CompactedSize == 0)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must be create with defined CompactedSize");
+ return false;
+ }
+ }
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode");
@@ -2353,8 +2463,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int)
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) const
{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device");
+ return false;
+ }
+
if (Attribs.pSrc == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null");
@@ -2369,14 +2485,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("CopyTLAS command must be performed outside of render pass");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass");
return false;
}
#ifdef DILIGENT_DEVELOPMENT
- if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->CheckBLASVersion())
+ if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->ValidateContent())
{
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be rebuilded to apply BLAS changes before being copied to another TLAS");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid");
return false;
}
@@ -2392,6 +2508,23 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
return false;
}
}
+ else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ return false;
+ }
+
+ if (DstDesc.CompactedSize == 0)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must be create with defined CompactedSize");
+ return false;
+ }
+ }
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode");
@@ -2403,8 +2536,104 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int)
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const
{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device");
+ return false;
+ }
+
+ if (Attribs.pBLAS == nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must not be null");
+ return false;
+ }
+ if (!(Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ return false;
+ }
+
+ if (Attribs.pDestBuffer == nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must not be null");
+ return false;
+ }
+ if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer is too small");
+ return false;
+ }
+ if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 &&
+ !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag");
+ return false;
+ }
+
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass");
+ return false;
+ }
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device");
+ return false;
+ }
+
+ if (Attribs.pTLAS == nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must not be null");
+ return false;
+ }
+ if (!(Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ return false;
+ }
+
+ if (Attribs.pDestBuffer == nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must not be null");
+ return false;
+ }
+ if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer is too small");
+ return false;
+ }
+ if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 &&
+ !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag");
+ return false;
+ }
+
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass");
+ return false;
+ }
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device");
+ return false;
+ }
+
if (Attribs.pSBT == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null");
@@ -2431,7 +2660,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const Tra
return false;
}
- if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState)
+ if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState.RawPtr())
{
LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name,
"doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable");
diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
index 6ce6280b..5a2db2f8 100644
--- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
+++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
@@ -228,13 +228,19 @@ public:
inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const
{
- VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline());
VERIFY_EXPR(m_pRayTracingPipelineData != nullptr);
const auto ShaderHandleSize = m_pRayTracingPipelineData->ShaderHandleSize;
VERIFY_EXPR(ShaderHandleSize <= DataSize);
+ if (Name == nullptr || Name[0] == '\0')
+ {
+ // set shader binding to zero to skip shader execution
+ std::memset(pData, 0, ShaderHandleSize);
+ return;
+ }
+
auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name);
if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end())
{
diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
index b5642a75..04870876 100644
--- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
@@ -225,10 +225,133 @@ public:
Bool DILIGENT_CALL_TYPE Verify() const override final
{
- // AZ TODO
+ Uint32 ShCounter = 0;
+ Uint32 RecCounter = 0;
+ const auto Stride = this->m_ShaderRecordStride;
+ const auto ShSize = this->m_pDevice->GetShaderGroupHandleSize();
+ const auto FindPattern = [&ShCounter, &RecCounter, Stride, ShSize](const std::vector<Uint8>& Data, const char* Name) -> bool //
+ {
+ for (size_t i = 0; i < Data.size(); i += Stride)
+ {
+ Uint32 Count = 0;
+ for (size_t j = 0; j < ShSize; ++j)
+ Count += (Data[i + j] == EmptyElem);
+
+ if (Count == ShSize)
+ {
+ LOG_ERROR_MESSAGE("Shader binding table is not valid: shader in '", Name, "'(", i / Stride, ") is not bound");
+ return false;
+ }
+
+ Count = 0;
+ for (size_t j = ShSize; j < Stride; ++j)
+ Count += (Data[i + j] == EmptyElem);
+
+ if (Count > Stride - ShSize)
+ LOG_WARNING_MESSAGE("Shader binding table is not valid: shader record data in '", Name, "'(", i / Stride, ") is not initialized");
+ }
+ return true;
+ };
+
+ if (m_RayGenShaderRecord.empty())
+ {
+ LOG_ERROR_MESSAGE("Shader binding table is not valid: ray generation shader is not bound");
+ return false;
+ }
+
+ if (!FindPattern(m_RayGenShaderRecord, "ray generation") ||
+ !FindPattern(m_MissShadersRecord, "miss") ||
+ !FindPattern(m_CallableShadersRecord, "callable") ||
+ !FindPattern(m_HitGroupsRecord, "hit groups"))
+ return false;
+
return true;
}
+ struct BindingTable
+ {
+ const void* pData = nullptr;
+ Uint32 Size = 0;
+ Uint32 Offset = 0;
+ Uint32 Stride = 0;
+ };
+ void GetData(IBuffer*& pSBTBuffer,
+ BindingTable& RaygenShaderBindingTable,
+ BindingTable& MissShaderBindingTable,
+ BindingTable& HitShaderBindingTable,
+ BindingTable& CallableShaderBindingTable)
+ {
+ const auto ShaderGroupBaseAlignment = GetDevice()->GetShaderGroupBaseAlignment();
+
+ const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 {
+ return Align(static_cast<Uint32>(offset), ShaderGroupBaseAlignment);
+ };
+
+ const Uint32 RayGenOffset = 0;
+ const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size());
+ const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size());
+ const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size());
+ const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size());
+
+ // recreate buffer
+ if (this->m_pBuffer == nullptr || this->m_pBuffer->GetDesc().uiSizeInBytes < BufSize)
+ {
+ this->m_pBuffer = nullptr;
+
+ String BuffName = String{GetDesc().Name} + " - internal buffer";
+ BufferDesc BuffDesc;
+ BuffDesc.Name = BuffName.c_str();
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.BindFlags = BIND_RAY_TRACING;
+ BuffDesc.uiSizeInBytes = BufSize;
+
+ GetDevice()->CreateBuffer(BuffDesc, nullptr, &this->m_pBuffer);
+ VERIFY_EXPR(this->m_pBuffer != nullptr);
+ }
+
+ if (this->m_pBuffer == nullptr)
+ return; // something goes wrong
+
+ pSBTBuffer = this->m_pBuffer;
+
+ if (m_RayGenShaderRecord.size())
+ {
+ RaygenShaderBindingTable.pData = this->m_Changed ? m_RayGenShaderRecord.data() : nullptr;
+ RaygenShaderBindingTable.Offset = RayGenOffset;
+ RaygenShaderBindingTable.Size = static_cast<Uint32>(m_RayGenShaderRecord.size());
+ RaygenShaderBindingTable.Stride = this->m_ShaderRecordStride;
+ }
+
+ if (m_MissShadersRecord.size())
+ {
+ MissShaderBindingTable.pData = this->m_Changed ? m_MissShadersRecord.data() : nullptr;
+ MissShaderBindingTable.Offset = MissShaderOffset;
+ MissShaderBindingTable.Size = static_cast<Uint32>(m_MissShadersRecord.size());
+ MissShaderBindingTable.Stride = this->m_ShaderRecordStride;
+ }
+
+ if (m_HitGroupsRecord.size())
+ {
+ HitShaderBindingTable.pData = this->m_Changed ? m_HitGroupsRecord.data() : nullptr;
+ HitShaderBindingTable.Offset = HitGroupOffset;
+ HitShaderBindingTable.Size = static_cast<Uint32>(m_HitGroupsRecord.size());
+ HitShaderBindingTable.Stride = this->m_ShaderRecordStride;
+ }
+
+ if (m_CallableShadersRecord.size())
+ {
+ CallableShaderBindingTable.pData = this->m_Changed ? m_CallableShadersRecord.data() : nullptr;
+ CallableShaderBindingTable.Offset = CallableShadersOffset;
+ CallableShaderBindingTable.Size = static_cast<Uint32>(m_CallableShadersRecord.size());
+ CallableShaderBindingTable.Stride = this->m_ShaderRecordStride;
+ }
+
+ if (!this->m_Changed)
+ return;
+
+ this->m_Changed = false;
+ }
+
protected:
void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const
{
@@ -270,6 +393,7 @@ protected:
std::vector<Uint8> m_HitGroupsRecord;
RefCntAutoPtr<PipelineStateImplType> m_pPSO;
+ RefCntAutoPtr<IBuffer> m_pBuffer;
Uint32 m_ShaderRecordSize = 0;
Uint32 m_ShaderRecordStride = 0;
diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
index b03d9e5c..a8896abb 100644
--- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
@@ -33,6 +33,7 @@
#include <unordered_map>
#include "TopLevelAS.h"
+#include "BottomLevelAS.h"
#include "DeviceObjectBase.hpp"
#include "RenderDeviceBase.hpp"
#include "StringPool.hpp"
@@ -71,59 +72,66 @@ public:
{
}
- void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance)
+ void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) noexcept
{
- this->m_Instances.clear();
- this->m_StringPool.Release();
- this->m_HitShadersPerInstance = HitShadersPerInstance;
-
- size_t StringPoolSize = 0;
- for (Uint32 i = 0; i < InstanceCount; ++i)
+ try
{
- StringPoolSize += strlen(pInstances[i].InstanceName) + 1;
- }
+ this->m_Instances.clear();
+ this->m_StringPool.Release();
+ this->m_HitShadersPerInstance = HitShadersPerInstance;
+
+ size_t StringPoolSize = 0;
+ for (Uint32 i = 0; i < InstanceCount; ++i)
+ {
+ StringPoolSize += strlen(pInstances[i].InstanceName) + 1;
+ }
- this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
+ this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
- Uint32 InstanceOffset = 0;
+ Uint32 InstanceOffset = 0;
- for (Uint32 i = 0; i < InstanceCount; ++i)
- {
- auto& inst = pInstances[i];
- const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName);
- InstanceDesc Desc = {};
+ for (Uint32 i = 0; i < InstanceCount; ++i)
+ {
+ auto& inst = pInstances[i];
+ const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName);
+ InstanceDesc Desc = {};
- Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex;
- Desc.pBLAS = ValidatedCast<BottomLevelASType>(inst.pBLAS);
+ Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex;
+ Desc.pBLAS = ValidatedCast<BottomLevelASType>(inst.pBLAS);
#ifdef DILIGENT_DEVELOPMENT
- Desc.Version = Desc.pBLAS->GetVersion();
+ Desc.Version = Desc.pBLAS->GetVersion();
#endif
- if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
- {
- Desc.ContributionToHitGroupIndex = InstanceOffset;
- auto& BLASDesc = Desc.pBLAS->GetDesc();
- switch (this->m_Desc.BindingMode)
+ if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
{
- // clang-format off
- case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break;
- case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break;
- case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break;
- default: UNEXPECTED("unknown ray tracing shader binding mode");
- // clang-format on
+ Desc.ContributionToHitGroupIndex = InstanceOffset;
+ auto& BLASDesc = Desc.pBLAS->GetDesc();
+ switch (this->m_Desc.BindingMode)
+ {
+ // clang-format off
+ case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break;
+ case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break;
+ case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break;
+ default: UNEXPECTED("unknown ray tracing shader binding mode");
+ // clang-format on
+ }
}
+
+ bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second;
+ if (!IsUniqueName)
+ LOG_ERROR_AND_THROW("Instance name must be unique!");
}
- bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second;
- if (!IsUniqueName)
- LOG_ERROR_AND_THROW("Instance name must be unique!");
+ VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0);
+ }
+ catch (...)
+ {
+ this->m_Instances.clear();
}
-
- VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0);
}
- void CopyInstancceData(const TopLevelASBase& Src)
+ void CopyInstancceData(const TopLevelASBase& Src) noexcept
{
this->m_Instances.clear();
this->m_StringPool.Release();
@@ -162,6 +170,8 @@ public:
virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
{
+ VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE || State == RESOURCE_STATE_RAY_TRACING,
+ "Unsupported state for top-level acceleration structure");
this->m_State = State;
}
@@ -183,18 +193,42 @@ public:
}
#ifdef DILIGENT_DEVELOPMENT
- bool CheckBLASVersion() const
+ bool ValidateContent() const
{
+ bool result = true;
+
+ if (m_Instances.empty())
+ {
+ LOG_ERROR_MESSAGE("TLAS with name ('", GetDesc().Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content");
+ result = false;
+ }
+
+ // validate instances
for (auto& NameAndInst : m_Instances)
{
- auto& Inst = NameAndInst.second;
+ const InstanceDesc& Inst = NameAndInst.second;
+ const BottomLevelASDesc& Desc = Inst.pBLAS->GetDesc();
+
if (Inst.Version != Inst.pBLAS->GetVersion())
{
- LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS that was changed after TLAS build, you must rebuild TLAS.");
- return false;
+ LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that was changed after TLAS build, you must rebuild TLAS");
+ result = false;
+ }
+
+ if (Inst.pBLAS->GetState() != RESOURCE_STATE_BUILD_AS_READ)
+ {
+ LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that must be in BUILD_AS_READ state, but current state is ",
+ GetResourceStateFlagString(Inst.pBLAS->GetState()));
+ result = false;
+ }
+
+ if (!Inst.pBLAS->ValidateContent())
+ {
+ LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that is not valid");
+ result = false;
}
}
- return true;
+ return result;
}
#endif
@@ -203,15 +237,29 @@ protected:
{
#define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)
- if (Desc.MaxInstanceCount == 0)
+ if (Desc.CompactedSize > 0)
{
- LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero");
- }
+ if (Desc.MaxInstanceCount != 0)
+ {
+ LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then MaxInstanceCount must be zero");
+ }
- if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 ||
- (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0)
+ if (Desc.Flags != RAYTRACING_BUILD_AS_NONE)
+ {
+ LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE");
+ }
+ }
+ else
{
- LOG_TLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD are invalid");
+ if (Desc.MaxInstanceCount == 0)
+ {
+ LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero");
+ }
+
+ if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD))
+ {
+ LOG_TLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD");
+ }
}
#undef LOG_TLAS_ERROR_AND_THROW
diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
index d2f1ed0f..ac521756 100644
--- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
@@ -46,39 +46,37 @@ static const INTERFACE_ID IID_BottomLevelAS =
/// Defines bottom level acceleration structure triangles description.
-/// AZ TODO
+/// Triangle geometry description.
struct BLASTriangleDesc
{
/// Geometry name.
- /// The name is used to map BLASBuildTriangleData to this geometry.
+ /// The name is used to map triangles data (BLASBuildTriangleData) to this geometry.
const char* GeometryName DEFAULT_INITIALIZER(nullptr);
/// The maximum vertex count for this geometry.
/// Current number of vertices is defined in BLASBuildTriangleData::VertexCount.
Uint32 MaxVertexCount DEFAULT_INITIALIZER(0);
- /// The type of vertices in this geometry.
- /// Float, Int16 are supported.
+ /// The type of vertices in this geometry, see Diligent::VALUE_TYPE.
VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED);
/// The number of components in vertex.
/// 2 and 3 are supported.
Uint8 VertexComponentCount DEFAULT_INITIALIZER(0);
- /// The maximum index count for this geometry.
- /// The current number of indices is defined in BLASBuildTriangleData::IndexCount.
- /// It must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise.
- Uint32 MaxIndexCount DEFAULT_INITIALIZER(0);
+ /// The maximum primitive count of this geometry.
+ /// The current number of primitives is defined in BLASBuildTriangleData::PrimitiveCount.
+ Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0);
- /// Index type of this geometry.
+ /// Index type of this geometry, see Diligent::VALUE_TYPE.
/// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED.
+ /// If not defined then used vertex array instead of indexed vertices.
VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED);
- /// AZ TODO
+ /// Vulkan only, allows to use transformations in BLASBuildTriangleData.
Bool AllowsTransforms DEFAULT_INITIALIZER(False);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BLASTriangleDesc() noexcept {}
#endif
};
@@ -87,11 +85,11 @@ typedef struct BLASTriangleDesc BLASTriangleDesc;
/// Defines bottom level acceleration structure axis aligned bounding boxes description.
-/// AZ TODO
+/// AABB geometry description.
struct BLASBoundingBoxDesc
{
/// Geometry name.
- /// The name is used to map BLASBuildBoundingBoxData to this geometry.
+ /// The name is used to map AABB data (BLASBuildBoundingBoxData) to this geometry.
const char* GeometryName DEFAULT_INITIALIZER(nullptr);
/// The maximum AABBs count.
@@ -99,25 +97,22 @@ struct BLASBoundingBoxDesc
Uint32 MaxBoxCount DEFAULT_INITIALIZER(0);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BLASBoundingBoxDesc() noexcept {}
#endif
};
typedef struct BLASBoundingBoxDesc BLASBoundingBoxDesc;
-/// AZ TODO
-
-/// AZ TODO
+/// Defines acceleration structures build flags.
DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8)
{
- /// AZ TODO
RAYTRACING_BUILD_AS_NONE = 0,
- /// AZ TODO
+ /// AZ TODO: not supported yet
RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01,
- /// Indicates that the specified acceleration structure can act as the source for a copy acceleration structure command
+ /// Indicates that the specified acceleration structure can act as the source for
+ /// a copy acceleration structure command IDeviceContext::CopyBLAS() or IDeviceContext::CopyTLAS()
/// with mode of COPY_AS_MODE_COMPACT to produce a compacted acceleration structure.
RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02,
@@ -131,15 +126,12 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8)
/// result build, potentially at the expense of build time or trace performance.
RAYTRACING_BUILD_AS_LOW_MEMORY = 0x10,
- RAYTRACING_BUILD_AS_FLAGS_LAST = 0x10
+ RAYTRACING_BUILD_AS_FLAGS_LAST = RAYTRACING_BUILD_AS_LOW_MEMORY
};
DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_BUILD_AS_FLAGS)
-/// AZ TODO
-
-// Here we allocate space for geometry data.
-// Geometry can be dynamically updated.
+/// Bottom-level AS description.
struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs)
/// Array of triangle geometry descriptions.
@@ -156,29 +148,37 @@ struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs)
/// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS.
RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE);
+
+ /// Size from the result of IDeviceContext::WriteBLASCompactedSize() if this acceleration structure
+ /// is going to be the target of a compacting copy (IDeviceContext::CopyBLAS() with COPY_AS_MODE_COMPACT).
+ Uint32 CompactedSize DEFAULT_INITIALIZER(0);
/// Defines which command queues this BLAS can be used with
Uint64 CommandQueueMask DEFAULT_INITIALIZER(1);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BottomLevelASDesc() noexcept {}
#endif
};
typedef struct BottomLevelASDesc BottomLevelASDesc;
+
+/// Defines scratch buffer info for acceleration structure.
struct ScratchBufferSizes
{
+ /// Scratch buffer size for acceleration structure building.
Uint32 Build DEFAULT_INITIALIZER(0);
+
+ /// AZ TODO: not supported yet
Uint32 Update DEFAULT_INITIALIZER(0);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
ScratchBufferSizes() noexcept {}
#endif
};
typedef struct ScratchBufferSizes ScratchBufferSizes;
+
#define DILIGENT_INTERFACE_NAME IBottomLevelAS
#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
@@ -186,7 +186,9 @@ typedef struct ScratchBufferSizes ScratchBufferSizes;
IDeviceObjectInclusiveMethods; \
IBottomLevelASMethods BottomLevelAS
-/// AZ TODO
+/// Bottom-level AS interface
+
+/// Defines the methods to manipulate a BLAS object
DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject)
{
#if DILIGENT_CPP_INTERFACE
@@ -194,11 +196,16 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject)
virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0;
#endif
- /// AZ TODO
+ /// Returns geometry index that can be used in shader binding table.
+
+ /// \param [in] Name - Geometry name that specified in BLASTriangleDesc or BLASBoundingBoxDesc.
+ /// \return Geometry index.
VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_
const char* Name) CONST PURE;
- /// AZ TODO
+ /// Returns scratch buffer info for current acceleration structure.
+
+ /// \return structure object.
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
/// Returns native acceleration structure handle specific to the underlying graphics API
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index 0cb7fe7d..6c035ded 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -719,10 +719,10 @@ struct BeginRenderPassAttribs
};
typedef struct BeginRenderPassAttribs BeginRenderPassAttribs;
-/// AZ TODO
+
+/// TLAS instance flags that used in IDeviceContext::BuildTLAS().
DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8)
{
- /// AZ TODO
RAYTRACING_INSTANCE_NONE = 0,
/// Disables face culling for this instance.
@@ -734,38 +734,40 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8)
RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02,
/// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all
- /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag.
+ /// geometries referenced by this instance. This behavior can be overridden in shader by ray flags.
RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04,
- /// causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all
- /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag.
+ /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all
+ /// geometries referenced by this instance. This behavior can be overridden shader by ray flags.
RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08,
RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE
};
DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS)
-/// AZ TODO
+
+/// Defines acceleration structure copy mode.
+
+/// These flags are used by IDeviceContext::CopyBLAS() and IDeviceContext::CopyTLAS().
DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8)
{
- /// Creates a direct copy of the acceleration structure specified in src into the one specified by dst.
- /// The dst acceleration structure must have been created with the same parameters as src.
+ /// Creates a direct copy of the acceleration structure specified in pSrc into the one specified by pDst.
+ /// The pDst acceleration structure must have been created with the same parameters as pSrc.
COPY_AS_MODE_CLONE = 0,
- // creates a more compact version of an acceleration structure src into dst.
- // The acceleration structure dst must have been created with a compactedSize corresponding to the one returned by vkCmdWriteAccelerationStructuresPropertiesKHR
- // after the build of the acceleration structure specified by src.
- //COPY_AS_MODE_COMPACT,
+ /// Creates a more compact version of an acceleration structure pSrc into pDst.
+ /// The acceleration structure pDst must have been created with a CompactedSize corresponding
+ /// to the one returned by IDeviceContext::WriteBLASCompactedSize() or IDeviceContext::WriteTLASCompactedSize()
+ /// after the build of the acceleration structure specified by pSrc.
+ COPY_AS_MODE_COMPACT,
- COPY_AS_MODE_LAST = COPY_AS_MODE_CLONE,
+ COPY_AS_MODE_LAST = COPY_AS_MODE_COMPACT,
};
-/// Defines geometry flags for ray tracing.
-/// AZ TODO
+/// Defines geometry flags for ray tracing.
DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8)
{
- /// AZ TODO
RAYTRACING_GEOMETRY_NONE = 0,
/// Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group.
@@ -779,148 +781,168 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8)
};
DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS)
-/// AZ TODO
+
+/// Triangle geometry data description.
struct BLASBuildTriangleData
{
- // put geometry data to geometry that allocated by BLASTriangleDesc
+ /// Geometry name used to map geometry to hit group in shader binding table.
+ /// Put geometry data to geometry that allocated by BLASTriangleDesc with the same name.
const char* GeometryName DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); // specs: Triangles are considered "inactive" (but legal input to acceleration structure build) if the x component of each vertex is NaN
+ /// Triangle vertices data source.
+ /// Triangles are considered "inactive" if the x component of each vertex is NaN.
+ /// Buffer must be created with BIND_RAY_TRACING flag.
+ IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Data offset in bytes in pVertexBuffer.
Uint32 VertexOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Stride in bytes between each vertex.
Uint32 VertexStride DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Number of triangle vertices.
+ /// Must be less than or equal to BLASTriangleDesc::MaxVertexCount.
Uint32 VertexCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
- VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration
- Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); // optional, value may be taken from declaration
-
- // optional
+ /// The type of vertex and number of components.
+ /// This is optional values. Must be undefined or same as in BLASTriangleDesc.
+ VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED);
+ Uint8 VertexComponentCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Number of triangles.
+ /// Must equal to VertexCount / 3 if pIndexBuffer is null or must equal to index count / 3.
+ Uint32 PrimitiveCount DEFAULT_INITIALIZER(0);
+
+ /// Triangle indices data source.
+ /// Must be null if BLASTriangleDesc::IndexType is undefined.
+ /// Buffer must be created with BIND_RAY_TRACING flag.
IBuffer* pIndexBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Data offset in bytes in pIndexBuffer.
Uint32 IndexOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
- Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ?
+ /// Type of triangle indices, see Diligent::VALUE_TYPE.
+ /// This is optional value. Must be undefined or same as in BLASTriangleDesc.
+ VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED);
- /// AZ TODO
- VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration
-
- // optional, buffer that contains 3x4 matrix with local transformation for this triangles/mesh
-
- /// AZ TODO
+ /// Geometry transformation data source.
+ /// Buffer must be created with BIND_RAY_TRACING flag.
IBuffer* pTransformBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Data offset in bytes in pTransformBuffer.
Uint32 TransformBufferOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Geometry flags.
RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BLASBuildTriangleData() noexcept {}
#endif
};
typedef struct BLASBuildTriangleData BLASBuildTriangleData;
-/// AZ TODO
+
+/// AABB geometry data description.
struct BLASBuildBoundingBoxData
{
- /// AZ TODO
- // put geometry data to geometry that allocated by BLASBoundingBoxDesc
+ /// Geometry name used to map geometry to hit group in shader binding table.
+ /// Put geometry data to geometry that allocated by BLASBoundingBoxDesc with the same name.
const char* GeometryName DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); // specs: AABBs are considered inactive if AABB.MinX is NaN
+ /// AABB data source.
+ /// Each AABB defined as { float3 Min; float3 Max } structure.
+ /// AABB are considered inactive if AABB.Min.x is NaN.
+ /// Buffer must be created with BIND_RAY_TRACING flag.
+ IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Data offset in bytes in pBoxBuffer.
Uint32 BoxOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Stride in bytes between each AABB.
Uint32 BoxStride DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Number of AABBs.
+ /// Must be less than or equal to BLASBoundingBoxDesc::MaxBoxCount.
Uint32 BoxCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Geometry flags, see Diligent::RAYTRACING_GEOMETRY_FLAGS.
RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BLASBuildBoundingBoxData() noexcept {}
#endif
};
typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData;
-/// AZ TODO
+/// This structure is used by IDeviceContext::BuildBLAS().
struct BLASBuildAttribs
{
- /// AZ TODO
+ /// Target bottom-level AS.
IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr);
-
- /// AZ TODO
+
+ /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
- /// AZ TODO
+ /// Geometry data source buffers state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
- /// AZ TODO
+ /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data.
BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Number of triangle grometries.
+ /// Must be less than or equal to BottomLevelASDesc::TriangleCount.
Uint32 TriangleDataCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contains AABB geometry data.
BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Number of AABB geometries.
+ /// Must be less than or equal to BottomLevelASDesc::BoxCount.
Uint32 BoxDataCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Buffer that used for acceleration structure building.
+ /// Must be created with BIND_RAY_TRACING.
+ /// Call IBottomLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer.
IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Offset from the beginning of the buffer.
Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BLASBuildAttribs() noexcept {}
#endif
};
typedef struct BLASBuildAttribs BLASBuildAttribs;
-/// AZ TODO
+/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate index
+/// depending on geometry count in TLASBuildInstanceData::pBLAS and shader binding mode in TopLevelASDesc::BindingMode.
+///
+/// Example:
+/// For each instance in TLAS
+/// if (Instance.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+/// Instance.ContributionToHitGroupIndex = InstanceOffset;
+/// if (BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY) InstanceOffset += Instance.pBLAS->GeometryCount() * HitShadersPerInstance;
+/// if (BindingMode == SHADER_BINDING_MODE_PER_INSTANCE) InstanceOffset += HitShadersPerInstance;
static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u;
-/// AZ TODO
-static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64;
-/// AZ TODO
+/// Row-major matrix
struct InstanceMatrix
{
- /// rotation translation
- /// (0 1 2) [ 3]
- /// (4 5 6) [ 7]
- /// (8 9 10) [11]
+ /// (0.0 1.0 2.0)
+ /// (0.1 1.1 2.1) - rotation
+ /// (0.2 1.2 2.2)
+ ///
+ /// [0.3 1.3 2.3] - translation
float data [3][4];
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
+ /// Construct identity matrix.
InstanceMatrix() noexcept :
data{{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
@@ -928,7 +950,8 @@ struct InstanceMatrix
{}
InstanceMatrix(const InstanceMatrix&) noexcept = default;
-
+
+ /// Set matrix translation.
InstanceMatrix& SetTranslation(float x, float y, float z) noexcept
{
data[0][3] = x;
@@ -936,151 +959,229 @@ struct InstanceMatrix
data[2][3] = z;
return *this;
}
+
+ /// Set matrix rotation basis.
+ InstanceMatrix& SetRotation(const float* pMatrix3x3) noexcept
+ {
+ data[0][0] = pMatrix3x3[0]; data[1][0] = pMatrix3x3[1]; data[2][0] = pMatrix3x3[2];
+ data[0][1] = pMatrix3x3[3]; data[1][1] = pMatrix3x3[4]; data[2][1] = pMatrix3x3[5];
+ data[0][2] = pMatrix3x3[6]; data[1][2] = pMatrix3x3[7]; data[2][2] = pMatrix3x3[8];
+ return *this;
+ }
#endif
};
typedef struct InstanceMatrix InstanceMatrix;
-/// AZ TODO
+
+/// This structure is used by TLASBuildAttribs.
struct TLASBuildInstanceData
{
- /// AZ TODO
+ /// Instance name that used to map instance to hit group in shader binding table.
const char* InstanceName DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance
+ /// Bottom-level AS that represents instance geometry.
+ IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Instace to world transformation.
InstanceMatrix Transform;
- /// AZ TODO
- Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
+ /// User-defined value that can be accessed in shader via InstanceID() in HLSL and gl_InstanceCustomIndex in GLSL.
+ /// Used only first 24 bits.
+ Uint32 CustomId DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Instance flags, see Diligent::RAYTRACING_INSTANCE_FLAGS.
RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE);
- /// AZ TODO
- Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0
+ /// Visibility mask for the geometry, the instance may only be hit if rayMask & instance.Mask != 0.
+ /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is a InstanceInclusionMask argument of TraceRay()).
+ Uint8 Mask DEFAULT_INITIALIZER(0xFF);
- /// AZ TODO
- Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll()
+ /// Index used to calculate hit group location in shader binding table.
+ /// Must be TLAS_INSTANCE_OFFSET_AUTO is TLAS created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY or SHADER_BINDING_MODE_PER_INSTANCE.
+ /// Used only first 24 bits.
+ Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
TLASBuildInstanceData() noexcept {}
#endif
};
typedef struct TLASBuildInstanceData TLASBuildInstanceData;
-/// AZ TODO
+/// Instance size in GPU side.
+/// Used to calculate size of TLASBuildAttribs::pInstanceBuffer.
+static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64;
+
+
+/// This structure is used by IDeviceContext::BuildTLAS().
struct TLASBuildAttribs
{
- /// AZ TODO
+ /// Target top-level AS.
ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
- /// AZ TODO
+ /// Bottom-level AS (in TLASBuildInstanceData::pBLAS) state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
-
- /// AZ TODO
+
+ /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contains instance data.
TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Number of instances.
+ /// Must be less than or equal to TopLevelASDesc::MaxInstanceCount.
Uint32 InstanceCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Buffer that will be used to store instance data during AS building.
+ /// Buffer size must be at least TLAS_INSTANCE_DATA_SIZE * InstanceCount.
+ /// Buffer must be created with BIND_RAY_TRACING flag.
IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr);
-
- /// AZ TODO
+
+ /// Offset from the beginning of the buffer to location of instance data.
Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0);
-
- /// AZ TODO
+
+ /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
-
- /// AZ TODO
+
+ /// Buffer that used for acceleration structure building.
+ /// Must be created with BIND_RAY_TRACING.
+ /// Call ITopLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer.
IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Offset from the beginning of the buffer.
Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
TLASBuildAttribs() noexcept {}
#endif
};
typedef struct TLASBuildAttribs TLASBuildAttribs;
-/// AZ TODO
+/// This structure is used by IDeviceContext::CopyBLAS().
struct CopyBLASAttribs
{
- /// AZ TODO
- IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr);
+ /// Source bottom-level AS.
+ IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr);
+ /// Destination bottom-level AS.
+ /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize
+ /// that is greater or equal to size that returned by IDeviceContext::WriteBLASCompactedSize.
+ IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE);
+ /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE.
+ COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE);
- /// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ /// Source bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// Destination bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
CopyBLASAttribs() noexcept {}
#endif
};
typedef struct CopyBLASAttribs CopyBLASAttribs;
-/// AZ TODO
+/// This structure is used by IDeviceContext::CopyTLAS().
struct CopyTLASAttribs
{
- /// AZ TODO
- ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr);
+ /// Source top-level AS.
+ ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr);
+ /// Destination top-level AS.
+ /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize
+ /// that is greater or equal to size that returned by IDeviceContext::WriteTLASCompactedSize.
+ ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE);
+ /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE.
+ COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE);
- /// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ /// Source top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// Destination top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
CopyTLASAttribs() noexcept {}
#endif
};
typedef struct CopyTLASAttribs CopyTLASAttribs;
-/// AZ TODO
+/// This structure is used by IDeviceContext::WriteBLASCompactedSize().
+struct WriteBLASCompactedSizeAttribs
+{
+ /// Bottom-level AS.
+ IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr);
+
+ /// Command will writes 64 bit value with acceleration structure compacted size into buffer.
+ IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr);
+
+ /// Offset from the beginning of the buffer to location of AS compacted size.
+ Uint32 DestBufferOffset DEFAULT_INITIALIZER(0);
+
+ /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+#if DILIGENT_CPP_INTERFACE
+ WriteBLASCompactedSizeAttribs() noexcept {}
+#endif
+};
+typedef struct WriteBLASCompactedSizeAttribs WriteBLASCompactedSizeAttribs;
+
+
+/// This structure is used by IDeviceContext::WriteTLASCompactedSize().
+struct WriteTLASCompactedSizeAttribs
+{
+ /// Top-level AS.
+ ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
+
+ /// Command will writes 64 bit value with acceleration structure compacted size into buffer.
+ IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr);
+
+ /// Offset from the beginning of the buffer to location of AS compacted size.
+ Uint32 DestBufferOffset DEFAULT_INITIALIZER(0);
+
+ /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+#if DILIGENT_CPP_INTERFACE
+ WriteTLASCompactedSizeAttribs() noexcept {}
+#endif
+};
+typedef struct WriteTLASCompactedSizeAttribs WriteTLASCompactedSizeAttribs;
+
+
+/// This structure is used by IDeviceContext::TraceRays().
struct TraceRaysAttribs
{
- /// AZ TODO
- IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr);
+ /// Shader binding table.
+ IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- Uint32 DimensionX DEFAULT_INITIALIZER(1);
- Uint32 DimensionY DEFAULT_INITIALIZER(1);
- Uint32 DimensionZ DEFAULT_INITIALIZER(1);
+ Uint32 DimensionX DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in X direction.
+ Uint32 DimensionY DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Y direction.
+ Uint32 DimensionZ DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Z direction.
- /// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ /// Shader binding table buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE).
+ RESOURCE_STATE_TRANSITION_MODE SBTTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
TraceRaysAttribs() noexcept {}
#endif
};
@@ -1981,23 +2082,52 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject)
ITexture* pDstTexture,
const ResolveTextureSubresourceAttribs REF ResolveAttribs) PURE;
- /// AZ TODO
+
+ /// Build Bottom-level acceleration structure with the specified geometries.
+
+ /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BLASBuildAttribs for details.
VIRTUAL void METHOD(BuildBLAS)(THIS_
const BLASBuildAttribs REF Attribs) PURE;
- /// AZ TODO
+
+ /// Build Top-level acceleration structure with the specified instances.
+
+ /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::TLASBuildAttribs for details.
VIRTUAL void METHOD(BuildTLAS)(THIS_
const TLASBuildAttribs REF Attribs) PURE;
- /// AZ TODO
+
+ /// Copies data from one acceleration structure to another.
+
+ /// \param [in] Attribs - Structure describing copy BLAS command attributes, see Diligent::CopyBLASAttribs for details.
VIRTUAL void METHOD(CopyBLAS)(THIS_
const CopyBLASAttribs REF Attribs) PURE;
- /// AZ TODO
+
+ /// Copies data from one acceleration structure to another.
+
+ /// \param [in] Attribs - Structure describing copy TLAS command attributes, see Diligent::CopyTLASAttribs for details.
VIRTUAL void METHOD(CopyTLAS)(THIS_
const CopyTLASAttribs REF Attribs) PURE;
- /// AZ TODO
+
+ /// Writes acceleration structure memory size to the buffer for compacting operation.
+
+ /// \param [in] Attribs - Structure describing write BLAS compacted size command attributes, see Diligent::WriteBLASCompactedSizeAttribs for details.
+ VIRTUAL void METHOD(WriteBLASCompactedSize)(THIS_
+ const WriteBLASCompactedSizeAttribs REF Attribs) PURE;
+
+
+ /// Writes acceleration structure memory size to the buffer for compacting operation.
+
+ /// \param [in] Attribs - Structure describing write TLAS compacted size command attributes, see Diligent::WriteTLASCompactedSizeAttribs for details.
+ VIRTUAL void METHOD(WriteTLASCompactedSize)(THIS_
+ const WriteTLASCompactedSizeAttribs REF Attribs) PURE;
+
+
+ /// Executes a trace rays command.
+
+ /// \param [in] Attribs - Trace rays command attributes, see Diligent::TraceRaysAttribs for details.
VIRTUAL void METHOD(TraceRays)(THIS_
const TraceRaysAttribs REF Attribs) PURE;
};
@@ -2054,6 +2184,8 @@ DILIGENT_END_INTERFACE
# define IDeviceContext_BuildTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, BuildTLAS, This, __VA_ARGS__)
# define IDeviceContext_CopyBLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyBLAS, This, __VA_ARGS__)
# define IDeviceContext_CopyTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyTLAS, This, __VA_ARGS__)
+# define IDeviceContext_WriteBLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteBLASCompactedSize, This, __VA_ARGS__)
+# define IDeviceContext_WriteTLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteTLASCompactedSize, This, __VA_ARGS__)
# define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__)
// clang-format on
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 76f8dcd6..cd32efc4 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -2731,9 +2731,14 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32)
/// The resource is used for present
RESOURCE_STATE_PRESENT = 0x10000,
- /// AZ TODO
+ /// The resource is used as vertex/index/instance buffer in a AS building operation
+ /// or as acceleration structure source in a AS copy operation.
RESOURCE_STATE_BUILD_AS_READ = 0x20000,
+
+ /// The resource is used as target in a AS building or AS copy operations.
RESOURCE_STATE_BUILD_AS_WRITE = 0x40000,
+
+ /// The resource is used as top-level AS shader resource in a trace rays operation.
RESOURCE_STATE_RAY_TRACING = 0x80000,
RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING,
diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h
index ebec8344..a630b1f1 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -152,7 +152,7 @@ typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc;
/// Graphics pipeline state description
-/// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure.
+/// This structure describes the graphics pipeline state and is part of the GraphicsPipelineStateCreateInfo structure.
struct GraphicsPipelineDesc
{
/// Blend state description.
@@ -215,13 +215,13 @@ struct GraphicsPipelineDesc
typedef struct GraphicsPipelineDesc GraphicsPipelineDesc;
-/// AZ TODO
+/// Ray tracing general shader group description
struct RayTracingGeneralShaderGroup
{
- /// AZ TODO
+ /// Unique group name.
const char* Name DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Shader type must be SHADER_TYPE_RAY_GEN or SHADER_TYPE_RAY_MISS or SHADER_TYPE_CALLABLE.
IShader* pShader DEFAULT_INITIALIZER(nullptr);
#if DILIGENT_CPP_INTERFACE
@@ -237,16 +237,18 @@ struct RayTracingGeneralShaderGroup
};
typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup;
-/// AZ TODO
+/// Ray tracing triangle hit shader group description.
struct RayTracingTriangleHitShaderGroup
{
- /// AZ TODO
+ /// Unique group name.
const char* Name DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Closest hit shader.
+ /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT.
IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Any-hit shader. Can be null.
+ /// Shader type must be SHADER_TYPE_RAY_ANY_HIT.
IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
#if DILIGENT_CPP_INTERFACE
@@ -264,20 +266,23 @@ struct RayTracingTriangleHitShaderGroup
};
typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup;
-/// AZ TODO
+/// Ray tracing procedural hit shader group description.
struct RayTracingProceduralHitShaderGroup
{
- /// AZ TODO
+ /// Unique group name.
const char* Name DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
+ /// Intersection shader.
+ /// Shader type must be SHADER_TYPE_RAY_INTERSECTION.
IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr);
-
- /// AZ TODO
- IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null
-
- /// AZ TODO
- IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
+
+ /// Closest hit shader. Can be null.
+ /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT.
+ IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr);
+
+ /// Any-hit shader. Can be null.
+ /// Shader type must be SHADER_TYPE_RAY_ANY_HIT.
+ IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr);
#if DILIGENT_CPP_INTERFACE
RayTracingProceduralHitShaderGroup() noexcept
@@ -296,14 +301,16 @@ struct RayTracingProceduralHitShaderGroup
};
typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup;
-/// AZ TODO
+/// This structure describes the ray tracing pipeline state and is part of the RayTracingPipelineStateCreateInfo structure.
struct RayTracingPipelineDesc
{
- // Size of the additional data passed to the shader.
- Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0);
+ /// Size of the additional data passed to the shader.
+ /// Shader record size plus shader group size (32 bytes) must be aligned to 32 bytes.
+ /// Shader record size plus shader group size (32 bytes) must not exceed 4096 bytes.
+ Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0);
- /// AZ TODO
- Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits)
+ /// Number of recursive call of TraceRay() in HLSL or traceRay() in GLSL.
+ Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits)
};
typedef struct RayTracingPipelineDesc RayTracingPipelineDesc;
@@ -440,26 +447,28 @@ typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo;
/// Ray tracing pipeline state description.
struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo)
- /// AZ TODO
+ /// Ray tracing pipeline description.
RayTracingPipelineDesc RayTracingPipeline;
- /// AZ TODO
+ /// A pointer to an array of GeneralShaderCount RayTracingGeneralShaderGroup structures that contains shader group description.
const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); // can be null
+ /// Number of general shader groups.
+ Uint32 GeneralShaderCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
- const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); // can be null
+ /// A pointer to an array of TriangleHitShaderCount RayTracingTriangleHitShaderGroup structures that contains shader group description.
+ /// Can be null.
+ const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0);
+ /// Number of triangle hit shader groups.
+ Uint32 TriangleHitShaderCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
- Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0);
+ /// A pointer to an array of ProceduralHitShaderCount RayTracingProceduralHitShaderGroup structures that contains shader group description.
+ /// Can be null.
+ const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr);
- /// AZ TODO
- Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0);
+ /// Number of procedural shader groups.
+ Uint32 ProceduralHitShaderCount DEFAULT_INITIALIZER(0);
/// Direct3D12 only: set name of constant buffer that will be used by local root signature.
/// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero.
@@ -575,11 +584,16 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject)
VIRTUAL bool METHOD(IsCompatibleWith)(THIS_
const struct IPipelineState* pPSO) CONST PURE;
- /// AZ TODO
+
+ /// Returns index of shader group that is used by shader binding table.
+ /// This method must only be called for a ray tracing pipeline.
+
+ /// \param [in] Name - Shader group name.
VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_
const char* Name) CONST PURE;
- /// AZ TODO
+
+ /// AZ TODO: remove ?
VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h
index 28e0bb17..fddffeba 100644
--- a/Graphics/GraphicsEngine/interface/Shader.h
+++ b/Graphics/GraphicsEngine/interface/Shader.h
@@ -356,7 +356,7 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8)
/// Input attachment in a render pass
SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT,
- /// AZ TODO
+ /// Acceleration structure
SHADER_RESOURCE_TYPE_ACCEL_STRUCT,
SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_ACCEL_STRUCT
diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
index d6f0740f..da650349 100644
--- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
+++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
@@ -46,17 +46,16 @@ static const INTERFACE_ID IID_ShaderBindingTable =
// clang-format off
-/// AZ TODO
+/// Shader binding table description.
struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs)
- /// AZ TODO
+ /// Ray tracing pipeline state object from which shaders will be taken.
IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
ShaderBindingTableDesc() noexcept {}
#endif
};
@@ -89,7 +88,6 @@ struct BindAllAttribs
Uint32 HitSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (HitSRDataSize / HitGroupCount)
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
BindAllAttribs() noexcept {}
#endif
};
@@ -102,7 +100,9 @@ typedef struct BindAllAttribs BindAllAttribs;
IDeviceObjectInclusiveMethods; \
IShaderBindingTableMethods ShaderBindingTable
-/// AZ TODO
+/// Shader binding table interface
+
+/// Defines the methods to manipulate a SBT object
DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject)
{
#if DILIGENT_CPP_INTERFACE
diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h
index 630f8ddd..2efd8518 100644
--- a/Graphics/GraphicsEngine/interface/TopLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h
@@ -45,7 +45,7 @@ static const INTERFACE_ID IID_TopLevelAS =
// clang-format off
-/// AZ TODO
+/// Defines shader binding mode.
DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8)
{
/// Each geometry in each instance can have a unique shader.
@@ -58,41 +58,44 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8)
SHADER_BINDING_USER_DEFINED,
};
-/// AZ TODO
+
+/// Top-level AS description.
struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs)
- /// Here we allocate space for instances.
- /// Instances can be dynamicaly updated.
+ /// Allocate space for specified number of instances.
Uint32 MaxInstanceCount DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS.
RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE);
+
+ /// Size from the result of IDeviceContext::WriteTLASCompactedSize() if this acceleration structure
+ /// is going to be the target of a compacting copy (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT).
+ Uint32 CompactedSize DEFAULT_INITIALIZER(0);
- // binding mode used for instanceOffset calculation.
+ /// Binding mode that used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation,
+ /// see Diligent::SHADER_BINDING_MODE.
SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY);
- /// Defines which command queues this BLAS can be used with
+ /// Defines which command queues this BLAS can be used with.
Uint64 CommandQueueMask DEFAULT_INITIALIZER(1);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
TopLevelASDesc() noexcept {}
#endif
};
typedef struct TopLevelASDesc TopLevelASDesc;
-/// AZ TODO
+/// Top-level AS instance description.
struct TLASInstanceDesc
{
- /// AZ TODO
+ /// Index that specified in TLASBuildInstanceData::ContributionToHitGroupIndex.
Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0);
- /// AZ TODO
+ /// Bottom-level AS that specified in TLASBuildInstanceData::pBLAS.
IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr);
#if DILIGENT_CPP_INTERFACE
- /// AZ TODO
TLASInstanceDesc() noexcept {}
#endif
};
@@ -106,7 +109,9 @@ typedef struct TLASInstanceDesc TLASInstanceDesc;
IDeviceObjectInclusiveMethods; \
ITopLevelASMethods TopLevelAS
-/// AZ TODO
+/// Top-level AS interface
+
+/// Defines the methods to manipulate a TLAS object
DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject)
{
#if DILIGENT_CPP_INTERFACE
@@ -114,11 +119,16 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject)
virtual const TopLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0;
#endif
- /// AZ TODO
+ /// Returns instance description that can be used in shader binding table.
+
+ /// \param [in] Name - Instance name that specified in TLASBuildInstanceData::InstanceName.
+ /// \return structure object.
VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_
const char* Name) CONST PURE;
- /// AZ TODO
+ /// Returns scratch buffer info for current acceleration structure.
+
+ /// \return structure object.
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
/// Returns native acceleration structure handle specific to the underlying graphics API