summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-28 16:33:03 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-28 18:04:08 +0000
commit135d5dc6743fc89d7a19c539fa06eca33506f51b (patch)
tree9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics/GraphicsEngine
parentFixed vexing gcc/clang liker error (diff)
downloadDiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.tar.gz
DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.zip
added ray tracing implementation for dx12 and vulkan
Diffstat (limited to 'Graphics/GraphicsEngine')
-rw-r--r--Graphics/GraphicsEngine/include/BottomLevelASBase.hpp34
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp192
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp105
-rw-r--r--Graphics/GraphicsEngine/include/TopLevelASBase.hpp48
-rw-r--r--Graphics/GraphicsEngine/interface/BottomLevelAS.h25
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h155
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h128
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h39
-rw-r--r--Graphics/GraphicsEngine/interface/ShaderBindingTable.h8
-rw-r--r--Graphics/GraphicsEngine/interface/TopLevelAS.h25
-rw-r--r--Graphics/GraphicsEngine/src/BufferBase.cpp2
11 files changed, 576 insertions, 185 deletions
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
index 879d73ab..9f37fb3f 100644
--- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
@@ -106,7 +106,7 @@ public:
else if (Desc.pBoxes != nullptr)
{
size_t StringPoolSize = 0;
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
+ for (Uint32 i = 0; i < Desc.BoxCount; ++i)
{
if (Desc.pBoxes[i].GeometryName == nullptr)
LOG_ERROR_AND_THROW("Geometry name can not be null!");
@@ -124,7 +124,7 @@ public:
this->m_Desc.pTriangles = nullptr;
// copy strings
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
+ 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;
@@ -147,7 +147,9 @@ public:
}
}
- virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override
+ static constexpr Uint32 InvalidGeometryIndex = ~0u;
+
+ virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final
{
VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
@@ -156,7 +158,29 @@ public:
return iter->second;
UNEXPECTED("Can't find geometry with specified name");
- return ~0u; // AZ TODO
+ return InvalidGeometryIndex;
+ }
+
+ virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
+ {
+ this->m_State = State;
+ }
+
+ virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final
+ {
+ return this->m_State;
+ }
+
+ bool IsInKnownState() const
+ {
+ return this->m_State != RESOURCE_STATE_UNKNOWN;
+ }
+
+ bool CheckState(RESOURCE_STATE State) const
+ {
+ VERIFY((State & (State - 1)) == 0, "Single state is expected");
+ VERIFY(IsInKnownState(), "BLAS state is unknown");
+ return (this->m_State & State) == State;
}
protected:
@@ -185,6 +209,8 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase)
protected:
+ RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+
std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
StringPool m_StringPool;
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index c16219da..0d98bae3 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -78,6 +78,8 @@ public:
using QueryImplType = typename ImplementationTraits::QueryType;
using FramebufferImplType = typename ImplementationTraits::FramebufferType;
using RenderPassImplType = typename ImplementationTraits::RenderPassType;
+ using BottomLevelASType = typename ImplementationTraits::BottomLevelASType;
+ using TopLevelASType = typename ImplementationTraits::TopLevelASType;
/// \param pRefCounters - reference counters object that controls the lifetime of this device context.
/// \param pRenderDevice - render device.
@@ -253,8 +255,10 @@ protected:
void DvpVerifyRenderTargets()const;
void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const;
- bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const;
- bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
#else
bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
@@ -268,8 +272,10 @@ protected:
void DvpVerifyRenderTargets()const {}
void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {}
- bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
- bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
// clang-format on
#endif
@@ -279,8 +285,6 @@ protected:
bool CopyTLAS(const CopyTLASAttribs& Attribs, int);
bool TraceRays(const TraceRaysAttribs& Attribs, int);
- static const Uint32 TLASInstanceDataSize = 64; // bytes
-
/// Strong reference to the device.
RefCntAutoPtr<DeviceImplType> m_pDevice;
@@ -1803,15 +1807,19 @@ template <typename BaseInterface, typename ImplementationTraits>
void DeviceContextBase<BaseInterface, ImplementationTraits>::
DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
{
- DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null");
+ DEV_CHECK_ERR(Barrier.pResource != nullptr, "pResource must not be null");
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
- if (Barrier.pTexture)
+
+ RefCntAutoPtr<ITexture> pTexture{Barrier.pResource, IID_Texture};
+ RefCntAutoPtr<IBuffer> pBuffer{Barrier.pResource, IID_Buffer};
+
+ if (pTexture)
{
- const auto& TexDesc = Barrier.pTexture->GetDesc();
+ const auto& TexDesc = pTexture->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'");
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN,
"The state of texture '", TexDesc.Name,
"' is unknown to the engine and is not explicitly specified in the barrier");
@@ -1842,17 +1850,17 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>::
"Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
}
}
- else if (Barrier.pBuffer)
+ else if (pBuffer)
{
- const auto& BuffDesc = Barrier.pBuffer->GetDesc();
+ const auto& BuffDesc = pBuffer->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'");
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'");
}
else
{
- // AZ TODO: global barrier
+ UNEXPECTED("unsupported resource type");
}
if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
@@ -1896,6 +1904,35 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return true;
}
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyBLASState(const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+{
+ if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState))
+ {
+ LOG_ERROR_MESSAGE(OperationName, " requires BLAS '", BLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
+ " state. Actual BLAS state: ", GetResourceStateString(BLAS.GetState()),
+ ". Use appropriate state transiton flags or explicitly transition the BLAS using IDeviceContext::TransitionResourceStates() method.");
+ return false;
+ }
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyTLASState(const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+{
+ if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState))
+ {
+ LOG_ERROR_MESSAGE(OperationName, " requires TLAS '", TLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
+ " state. Actual TLAS state: ", GetResourceStateString(TLAS.GetState()),
+ ". Use appropriate state transiton flags or explicitly transition the TLAS using IDeviceContext::TransitionResourceStates() method.");
+ return false;
+ }
+
+ return true;
+}
#endif // DILIGENT_DEVELOPMENT
template <typename BaseInterface, typename ImplementationTraits>
@@ -1913,7 +1950,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
- if ((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr))
+ if (!((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)))
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined");
return false;
@@ -1931,39 +1968,93 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
{
- if (Attribs.pTriangleData[i].pVertexBuffer == nullptr)
+ const auto& tri = Attribs.pTriangleData[i];
+ const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount;
+ const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount;
+
+ if (tri.VertexValueType >= VT_NUM_TYPES)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type");
+ return false;
+ }
+
+ if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3");
+ return false;
+ }
+
+ if (tri.VertexStride < VertexSize)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexStride must be at least ", VertexSize, " bytes");
+ return false;
+ }
+
+ if (tri.pVertexBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must not be null");
return false;
}
- if ((Attribs.pTriangleData[i].pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
- if (Attribs.pTriangleData[i].IndexType != VT_UNDEFINED)
+ if (tri.VertexOffset + VertexDataSize > tri.pVertexBuffer->GetDesc().uiSizeInBytes)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer is too small for specified VertexStride and VertexCount");
+ return false;
+ }
+
+ if (tri.IndexType != VT_UNDEFINED)
{
- if (Attribs.pTriangleData[i].pIndexBuffer == nullptr)
+ 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;
+ }
+
+ if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid");
+ return false;
+ }
+
+ if (tri.pIndexBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null");
return false;
}
- if ((Attribs.pTriangleData[i].pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+
+ const Uint32 IndexDataSize = tri.IndexCount * 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");
+ return false;
+ }
+ }
+ else
+ {
+ 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");
}
- // AZ TODO: check AllosTransforms flags in create info
- if (Attribs.pTriangleData[i].pTransformBuffer != nullptr)
+ if (tri.pTransformBuffer != nullptr)
{
- if ((Attribs.pTriangleData[i].pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag");
return false;
@@ -1973,13 +2064,22 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
{
- if (Attribs.pBoxData[i].pBoxBuffer == nullptr)
+ const auto& box = Attribs.pBoxData[i];
+ const Uint32 BoxSize = sizeof(float) * 6;
+
+ if (box.BoxStride < BoxSize)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxStride must be at least ", BoxSize, " bytes");
+ return false;
+ }
+
+ if (box.pBoxBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must not be null");
return false;
}
- if ((Attribs.pBoxData[i].pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must be created with BIND_RAY_TRACING flag");
return false;
@@ -2019,6 +2119,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
return true;
}
@@ -2044,18 +2145,19 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- if (Attribs.pInstancesBuffer == nullptr)
+ if (Attribs.pInstanceBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must not be null");
return false;
}
- if (Attribs.HitShadersPerInstance > 0)
+ if (Attribs.HitShadersPerInstance == 0)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0");
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
const auto& TLASDesc = Attribs.pTLAS->GetDesc();
if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount)
@@ -2064,14 +2166,16 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- const auto& InstDesc = Attribs.pInstancesBuffer->GetDesc();
- const size_t InstDataSize = Attribs.InstanceCount * TLASInstanceDataSize;
+ const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
+ const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE;
+ Uint32 AutoOffsetCounter = 0;
// 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 & 0x00FFFFFF) == 0);
+ VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0);
+ VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
+ (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0);
if (Attribs.pInstances[i].InstanceName == nullptr)
{
@@ -2084,15 +2188,24 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null");
return false;
}
+
+ if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+ ++AutoOffsetCounter;
+ }
+
+ if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not");
+ return false;
}
- if (Attribs.InstancesBufferOffset > InstDesc.uiSizeInBytes)
+ if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstancesBufferOffset is greater than buffer size");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceBufferOffset is greater than buffer size");
return false;
}
- if (InstDesc.uiSizeInBytes - Attribs.InstancesBufferOffset > InstDataSize)
+ if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset > InstDataSize)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ...");
return false;
@@ -2123,6 +2236,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
return true;
}
@@ -2142,6 +2256,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2192,13 +2307,15 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
return false;
}
}
- return true;
}
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
+
+ return true;
}
template <typename BaseInterface, typename ImplementationTraits>
@@ -2216,6 +2333,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2227,13 +2345,15 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc");
return false;
}
- return true;
}
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
+
+ return true;
}
template <typename BaseInterface, typename ImplementationTraits>
diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
index cce40b11..155ecb66 100644
--- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
@@ -47,7 +47,7 @@ namespace Diligent
/// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk).
/// \tparam RenderDeviceImplType - type of the render device implementation
/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl)
-template <class BaseInterface, class RenderDeviceImplType>
+template <class BaseInterface, class PipelineStateImplType, class RenderDeviceImplType>
class ShaderBindingTableBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, ShaderBindingTableDesc>
{
public:
@@ -71,6 +71,100 @@ public:
{
}
+ void BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride);
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ const Uint32 Offset = MissIndex * this->m_ShaderRecordStride;
+ this->m_MissShadersRecord.resize(std::max<size_t>(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindHitGroup(ITopLevelAS* pTLAS,
+ const char* InstanceName,
+ const char* GeometryName,
+ Uint32 RayOffsetInHitGroupIndex,
+ const char* ShaderGroupName,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR(pTLAS != nullptr);
+ VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
+ VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY);
+
+ const auto Desc = pTLAS->GetInstanceDesc(InstanceName);
+ VERIFY_EXPR(Desc.pBLAS != nullptr);
+
+ const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex;
+ const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName);
+ const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 Offset = Index * this->m_ShaderRecordStride;
+
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindHitGroups(ITopLevelAS* pTLAS,
+ const char* InstanceName,
+ Uint32 RayOffsetInHitGroupIndex,
+ const char* ShaderGroupName,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR(pTLAS != nullptr);
+ VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
+ VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY ||
+ pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_INSTANCE);
+
+ const auto Desc = pTLAS->GetInstanceDesc(InstanceName);
+ VERIFY_EXPR(Desc.pBLAS != nullptr);
+
+ const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex;
+ const auto& GeometryDesc = Desc.pBLAS->GetDesc();
+ const Uint32 GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount;
+ const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ PipelineStateImplType* pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
+
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride));
+
+ for (Uint32 i = 0; i < GeometryCount; ++i)
+ {
+ Uint32 Offset = (BeginIndex + i) * this->m_ShaderRecordStride;
+ pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ }
+ this->m_Changed = true;
+ }
+
+ void BindCallableShader(const char* ShaderGroupName,
+ Uint32 CallableIndex,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride;
+ this->m_CallableShadersRecord.resize(std::max<size_t>(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
protected:
static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc)
{
@@ -92,10 +186,13 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase)
protected:
- StringPool m_StringPool;
+ std::vector<Uint8> m_RayGenShaderRecord;
+ std::vector<Uint8> m_MissShadersRecord;
+ std::vector<Uint8> m_CallableShadersRecord;
+ std::vector<Uint8> m_HitGroupsRecord;
- std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
- std::unordered_map<HashMapStringKey, TLASInstanceDesc, HashMapStringKey::Hasher> m_Instances;
+ Uint32 m_ShaderRecordStride = 0;
+ bool m_Changed = true;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
index 2d2049af..ab56636f 100644
--- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
@@ -71,7 +71,7 @@ public:
{
}
- void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount)
+ void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance)
{
m_Instances.clear();
m_StringPool.Release();
@@ -84,22 +84,31 @@ public:
m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
+ Uint32 InstanceOffset = 0;
+
for (Uint32 i = 0; i < InstanceCount; ++i)
{
auto& inst = pInstances[i];
const char* NameCopy = m_StringPool.CopyString(inst.InstanceName);
InstanceDesc Desc = {};
- Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex;
+ Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex;
Desc.pBLAS = inst.pBLAS;
+ if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+ {
+ Desc.ContributionToHitGroupIndex = InstanceOffset;
+ auto& BLASDesc = Desc.pBLAS->GetDesc();
+ InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance;
+ }
+
bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second;
if (!IsUniqueName)
LOG_ERROR_AND_THROW("Instance name must be unique!");
}
}
- virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override
+ virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final
{
VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
@@ -108,7 +117,7 @@ public:
auto iter = m_Instances.find(Name);
if (iter != m_Instances.end())
{
- Result.ContributionToHitGroupIndex = iter->second.contributionToHitGroupIndex;
+ Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex;
Result.pBLAS = iter->second.pBLAS;
}
else
@@ -119,6 +128,28 @@ public:
return Result;
}
+ virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
+ {
+ this->m_State = State;
+ }
+
+ virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final
+ {
+ return this->m_State;
+ }
+
+ bool IsInKnownState() const
+ {
+ return this->m_State != RESOURCE_STATE_UNKNOWN;
+ }
+
+ bool CheckState(RESOURCE_STATE State) const
+ {
+ VERIFY((State & (State - 1)) == 0, "Single state is expected");
+ VERIFY(IsInKnownState(), "TLAS state is unknown");
+ return (this->m_State & State) == State;
+ }
+
protected:
static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc)
{
@@ -141,14 +172,15 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase)
protected:
+ RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+
+ StringPool m_StringPool;
+
struct InstanceDesc
{
- Uint32 contributionToHitGroupIndex = 0;
+ Uint32 ContributionToHitGroupIndex = 0;
mutable RefCntAutoPtr<IBottomLevelAS> pBLAS;
};
-
- StringPool m_StringPool;
-
std::unordered_map<HashMapStringKey, InstanceDesc, HashMapStringKey::Hasher> m_Instances;
};
diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
index cc8c4aec..264720ff 100644
--- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
@@ -200,6 +200,25 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject)
/// AZ TODO
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
+
+ /// Returns native acceleration structure handle specific to the underlying graphics API
+
+ /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n
+ /// VkAccelerationStructureKHR handle, for Vulkan implementation
+ VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE;
+
+ /// Sets the acceleration structure usage state.
+
+ /// \note This method does not perform state transition, but
+ /// resets the internal acceleration structure state to the given value.
+ /// This method should be used after the application finished
+ /// manually managing the acceleration structure state and wants to hand over
+ /// state management back to the engine.
+ VIRTUAL void METHOD(SetState)(THIS_
+ RESOURCE_STATE State) PURE;
+
+ /// Returns the internal acceleration structure state
+ VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -209,7 +228,11 @@ DILIGENT_END_INTERFACE
// clang-format off
-# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__)
+# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__)
+# define IBottomLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(BottomLevelAS, GetScratchBufferSizes, This)
+# define IBottomLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(BottomLevelAS, GetNativeHandle, This)
+# define IBottomLevelAS_SetState(This, ...) CALL_IFACE_METHOD(BottomLevelAS, SetState, This, __VA_ARGS__)
+# define IBottomLevelAS_GetState(This) CALL_IFACE_METHOD(BottomLevelAS, GetState, This)
// clang-format on
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index a294b066..04ff3030 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -809,7 +809,7 @@ struct BLASBuildTriangleData
Uint32 IndexOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- Uint32 IndexCount DEFAULT_INITIALIZER(0);
+ Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ?
/// AZ TODO
VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration
@@ -872,6 +872,9 @@ struct BLASBuildAttribs
RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
+ RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// AZ TODO
BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
@@ -903,6 +906,9 @@ typedef struct BLASBuildAttribs BLASBuildAttribs;
/// AZ TODO
static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u;
+/// AZ TODO
+static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64;
+
/// AZ TODO
struct TLASBuildInstanceData
@@ -917,7 +923,7 @@ struct TLASBuildInstanceData
float Transform[3][4] DEFAULT_INITIALIZER({});
/// AZ TODO
- Uint32 customId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
+ Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
/// AZ TODO
RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE);
@@ -926,7 +932,7 @@ struct TLASBuildInstanceData
Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0
/// AZ TODO
- Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll()
+ Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll()
#if DILIGENT_CPP_INTERFACE
/// AZ TODO
@@ -940,37 +946,40 @@ typedef struct TLASBuildInstanceData TLASBuildInstanceData;
struct TLASBuildAttribs
{
/// AZ TODO
- ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
+ ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
- TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr);
+ RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// AZ TODO
+ TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 InstanceCount DEFAULT_INITIALIZER(0);
+ Uint32 InstanceCount DEFAULT_INITIALIZER(0);
/// AZ TODO
- IBuffer* pInstancesBuffer DEFAULT_INITIALIZER(nullptr);
+ IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 InstancesBufferOffset DEFAULT_INITIALIZER(0);
+ Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
- Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
+ Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
/// AZ TODO
- IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
+ IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
+ Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
/// AZ TODO
@@ -1048,6 +1057,124 @@ struct TraceRaysAttribs
typedef struct TraceRaysAttribs TraceRaysAttribs;
+static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU;
+static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU;
+
+/// Resource state transition barrier description
+struct StateTransitionDesc
+{
+ /// Resource to transition.
+ /// Can be ITexture, IBuffer, IBottomLevelAS, ITopLevelAS.
+ struct IDeviceObject* pResource DEFAULT_INITIALIZER(nullptr);
+
+ /// When transitioning a texture, first mip level of the subresource range to transition.
+ Uint32 FirstMipLevel DEFAULT_INITIALIZER(0);
+
+ /// When transitioning a texture, number of mip levels of the subresource range to transition.
+ Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS);
+
+ /// When transitioning a texture, first array slice of the subresource range to transition.
+ Uint32 FirstArraySlice DEFAULT_INITIALIZER(0);
+
+ /// When transitioning a texture, number of array slices of the subresource range to transition.
+ Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES);
+
+ /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN,
+ /// internal resource state will be used, which must be defined in this case.
+ RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
+
+ /// Resource state after transition.
+ RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
+
+ /// State transition type, see Diligent::STATE_TRANSITION_TYPE.
+
+ /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS),
+ /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE.
+ STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE);
+
+ /// If set to true, the internal resource state will be set to NewState and the engine
+ /// will be able to take over the resource state management. In this case it is the
+ /// responsibility of the application to make sure that all subresources are indeed in
+ /// designated state.
+ /// If set to false, internal resource state will be unchanged.
+ /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false.
+ bool UpdateResourceState DEFAULT_INITIALIZER(false);
+
+#if DILIGENT_CPP_INTERFACE
+ StateTransitionDesc()noexcept{}
+
+ StateTransitionDesc(ITexture* _pTexture,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ Uint32 _FirstMipLevel = 0,
+ Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS,
+ Uint32 _FirstArraySlice = 0,
+ Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES,
+ STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE,
+ bool _UpdateState = false)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pTexture)},
+ FirstMipLevel {_FirstMipLevel },
+ MipLevelsCount {_MipLevelsCount },
+ FirstArraySlice {_FirstArraySlice},
+ ArraySliceCount {_ArraySliceCount},
+ OldState {_OldState },
+ NewState {_NewState },
+ TransitionType {_TransitionType },
+ UpdateResourceState {_UpdateState }
+ {}
+
+ StateTransitionDesc(ITexture* _pTexture,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ StateTransitionDesc
+ {
+ _pTexture,
+ _OldState,
+ _NewState,
+ 0,
+ REMAINING_MIP_LEVELS,
+ 0,
+ REMAINING_ARRAY_SLICES,
+ STATE_TRANSITION_TYPE_IMMEDIATE,
+ _UpdateState
+ }
+ {}
+
+ StateTransitionDesc(IBuffer* _pBuffer,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pBuffer)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+
+ StateTransitionDesc(IBottomLevelAS* _pBLAS,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pBLAS)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+
+ StateTransitionDesc(ITopLevelAS* _pTLAS,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pTLAS)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+#endif
+};
+typedef struct StateTransitionDesc StateTransitionDesc;
+
+
#define DILIGENT_INTERFACE_NAME IDeviceContext
#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 10a84f1d..093039bd 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -41,9 +41,6 @@
/// Graphics engine namespace
DILIGENT_BEGIN_NAMESPACE(Diligent)
-struct ITexture;
-struct IBuffer;
-
/// Value type
/// This enumeration describes value type. It is used by
@@ -86,7 +83,7 @@ DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32)
BIND_UNORDERED_ACCESS = 0x80L, ///< A buffer or a texture can be bound as an unordered access view
BIND_INDIRECT_DRAW_ARGS = 0x100L, ///< A buffer can be bound as the source buffer for indirect draw commands
BIND_INPUT_ATTACHMENT = 0x200L, ///< A texture can be used as render pass input attachment
- BIND_RAY_TRACING = 0x400L, ///< AZ TODO
+ BIND_RAY_TRACING = 0x400L, ///< A buffer can be used as scratch buffer for acceleration structure building.
BIND_FLAGS_LAST = 0x400L
};
DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS)
@@ -1253,16 +1250,22 @@ typedef struct DisplayModeAttribs DisplayModeAttribs;
DILIGENT_TYPED_ENUM(SWAP_CHAIN_USAGE_FLAGS, Uint32)
{
/// No allowed usage
- SWAP_CHAIN_USAGE_NONE = 0x00L,
+ SWAP_CHAIN_USAGE_NONE = 0x00L,
/// Swap chain can be used as render target ouput
- SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L,
+ SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L,
/// Swap chain images can be used as shader inputs
- SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L,
+ SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L,
/// Swap chain images can be used as source of copy operation
- SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L
+ SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L,
+
+ /// Swap chain images will define an unordered access view that will be used
+ /// for unordered read/write operations from the shaders
+ SWAP_CHAIN_USAGE_UNORDERED_ACCESS = 0x08L,
+
+ SWAP_CHAIN_USAGE_LAST = SWAP_CHAIN_USAGE_UNORDERED_ACCESS,
};
DEFINE_FLAG_ENUM_OPERATORS(SWAP_CHAIN_USAGE_FLAGS)
@@ -2720,10 +2723,12 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32)
/// The resource is used for present
RESOURCE_STATE_PRESENT = 0x10000,
- RESOURCE_STATE_BUILD_AS = 0x20000,
- RESOURCE_STATE_RAY_TRACING = 0x40000,
+ /// AZ TODO
+ RESOURCE_STATE_BUILD_AS_READ = 0x20000,
+ RESOURCE_STATE_BUILD_AS_WRITE = 0x40000,
+ RESOURCE_STATE_RAY_TRACING = 0x80000,
- RESOURCE_STATE_MAX_BIT = 0x40000,
+ RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING,
RESOURCE_STATE_GENERIC_READ = RESOURCE_STATE_VERTEX_BUFFER |
RESOURCE_STATE_CONSTANT_BUFFER |
@@ -2753,105 +2758,4 @@ DILIGENT_TYPED_ENUM(STATE_TRANSITION_TYPE, Uint8)
STATE_TRANSITION_TYPE_END
};
-static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU;
-static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU;
-
-/// Resource state transition barrier description
-struct StateTransitionDesc
-{
- /// Texture to transition.
- /// \note Exactly one of pTexture or pBuffer must be non-null.
- struct ITexture* pTexture DEFAULT_INITIALIZER(nullptr);
-
- /// Buffer to transition.
- /// \note Exactly one of pTexture or pBuffer must be non-null.
- struct IBuffer* pBuffer DEFAULT_INITIALIZER(nullptr);
-
- /// When transitioning a texture, first mip level of the subresource range to transition.
- Uint32 FirstMipLevel DEFAULT_INITIALIZER(0);
-
- /// When transitioning a texture, number of mip levels of the subresource range to transition.
- Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS);
-
- /// When transitioning a texture, first array slice of the subresource range to transition.
- Uint32 FirstArraySlice DEFAULT_INITIALIZER(0);
-
- /// When transitioning a texture, number of array slices of the subresource range to transition.
- Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES);
-
- /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN,
- /// internal resource state will be used, which must be defined in this case.
- RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
-
- /// Resource state after transition.
- RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
-
- /// State transition type, see Diligent::STATE_TRANSITION_TYPE.
-
- /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS),
- /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE.
- STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE);
-
- /// If set to true, the internal resource state will be set to NewState and the engine
- /// will be able to take over the resource state management. In this case it is the
- /// responsibility of the application to make sure that all subresources are indeed in
- /// designated state.
- /// If set to false, internal resource state will be unchanged.
- /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false.
- bool UpdateResourceState DEFAULT_INITIALIZER(false);
-
-#if DILIGENT_CPP_INTERFACE
- StateTransitionDesc()noexcept{}
-
- StateTransitionDesc(ITexture* _pTexture,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- Uint32 _FirstMipLevel = 0,
- Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS,
- Uint32 _FirstArraySlice = 0,
- Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES,
- STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE,
- bool _UpdateState = false)noexcept :
- pTexture {_pTexture },
- FirstMipLevel {_FirstMipLevel },
- MipLevelsCount {_MipLevelsCount },
- FirstArraySlice {_FirstArraySlice},
- ArraySliceCount {_ArraySliceCount},
- OldState {_OldState },
- NewState {_NewState },
- TransitionType {_TransitionType },
- UpdateResourceState {_UpdateState }
- {}
-
- StateTransitionDesc(ITexture* _pTexture,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- bool _UpdateState)noexcept :
- StateTransitionDesc
- {
- _pTexture,
- _OldState,
- _NewState,
- 0,
- REMAINING_MIP_LEVELS,
- 0,
- REMAINING_ARRAY_SLICES,
- STATE_TRANSITION_TYPE_IMMEDIATE,
- _UpdateState
- }
- {}
-
- StateTransitionDesc(IBuffer* _pBuffer,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- bool _UpdateState)noexcept :
- pBuffer {_pBuffer },
- OldState {_OldState },
- NewState {_NewState },
- UpdateResourceState {_UpdateState}
- {}
-#endif
-};
-typedef struct StateTransitionDesc StateTransitionDesc;
-
DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h
index e45dc703..3afa83f2 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -223,6 +223,17 @@ struct RayTracingGeneralShaderGroup
/// AZ TODO
IShader* pShader DEFAULT_INITIALIZER(nullptr);
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingGeneralShaderGroup() noexcept
+ {}
+
+ RayTracingGeneralShaderGroup(const char* _Name,
+ IShader* _pShader) noexcept:
+ Name {_Name },
+ pShader{_pShader}
+ {}
+#endif
};
typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup;
@@ -237,6 +248,19 @@ struct RayTracingTriangleHitShaderGroup
/// AZ TODO
IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingTriangleHitShaderGroup() noexcept
+ {}
+
+ RayTracingTriangleHitShaderGroup(const char* _Name,
+ IShader* _pClosestHitShader,
+ IShader* _pAnyHitShader = nullptr) noexcept:
+ Name {_Name },
+ pClosestHitShader{_pClosestHitShader},
+ pAnyHitShader {_pAnyHitShader }
+ {}
+#endif
};
typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup;
@@ -254,6 +278,21 @@ struct RayTracingProceduralHitShaderGroup
/// AZ TODO
IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingProceduralHitShaderGroup() noexcept
+ {}
+
+ RayTracingProceduralHitShaderGroup(const char* _Name,
+ IShader* _pIntersectionShader,
+ IShader* _pClosestHitShader = nullptr,
+ IShader* _pAnyHitShader = nullptr) noexcept:
+ Name {_Name },
+ pIntersectionShader{_pIntersectionShader},
+ pClosestHitShader {_pClosestHitShader },
+ pAnyHitShader {_pAnyHitShader }
+ {}
+#endif
};
typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup;
diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
index 514f9b7c..71fa25e4 100644
--- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
+++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
@@ -157,10 +157,10 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject)
/// AZ TODO
VIRTUAL void METHOD(BindCallableShader)(THIS_
- Uint32 Index,
- const char* ShaderName,
- const void* Data DEFAULT_INITIALIZER(nullptr),
- Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE;
+ const char* ShaderGroupName,
+ Uint32 CallableIndex,
+ const void* Data DEFAULT_INITIALIZER(nullptr),
+ Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE;
/// AZ TODO
VIRTUAL void METHOD(BindAll)(THIS_
diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h
index 0e427864..630f8ddd 100644
--- a/Graphics/GraphicsEngine/interface/TopLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h
@@ -120,6 +120,25 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject)
/// AZ TODO
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
+
+ /// Returns native acceleration structure handle specific to the underlying graphics API
+
+ /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n
+ /// VkAccelerationStructureKHR handle, for Vulkan implementation
+ VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE;
+
+ /// Sets the acceleration structure usage state.
+
+ /// \note This method does not perform state transition, but
+ /// resets the internal acceleration structure state to the given value.
+ /// This method should be used after the application finished
+ /// manually managing the acceleration structure state and wants to hand over
+ /// state management back to the engine.
+ VIRTUAL void METHOD(SetState)(THIS_
+ RESOURCE_STATE State) PURE;
+
+ /// Returns the internal acceleration structure state
+ VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -129,7 +148,11 @@ DILIGENT_END_INTERFACE
// clang-format off
-# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__)
+# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__)
+# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This)
+# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This)
+# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__)
+# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This)
// clang-format on
diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp
index aab770fd..5b72389a 100644
--- a/Graphics/GraphicsEngine/src/BufferBase.cpp
+++ b/Graphics/GraphicsEngine/src/BufferBase.cpp
@@ -45,7 +45,7 @@ namespace Diligent
void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps)
{
- static_assert(BIND_FLAGS_LAST == 0x400L, "AZ TODO");
+ static_assert(BIND_FLAGS_LAST == 0x400L, "Please update this function to handle the new bind flags");
constexpr Uint32 AllowedBindFlags =
BIND_VERTEX_BUFFER |