diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-10-28 16:33:03 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-10-28 18:04:08 +0000 |
| commit | 135d5dc6743fc89d7a19c539fa06eca33506f51b (patch) | |
| tree | 9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics/GraphicsEngine | |
| parent | Fixed vexing gcc/clang liker error (diff) | |
| download | DiligentCore-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.hpp | 34 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/DeviceContextBase.hpp | 192 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp | 105 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 48 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/BottomLevelAS.h | 25 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/DeviceContext.h | 155 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/GraphicsTypes.h | 128 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/PipelineState.h | 39 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/ShaderBindingTable.h | 8 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/TopLevelAS.h | 25 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/src/BufferBase.cpp | 2 |
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 | |
