summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-11-03 10:52:24 +0000
committerazhirnov <zh1dron@gmail.com>2020-11-03 11:16:11 +0000
commitefa43e2bd2475a4dec6771bf9759f6a99f7d77ed (patch)
treebbb257c3825ff07078626e3e137468f99d235a07 /Graphics/GraphicsEngine
parentFew improvements to ray tracing tests (diff)
downloadDiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.tar.gz
DiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.zip
fixed resource state transitions, some improvements for ray tracing
Diffstat (limited to 'Graphics/GraphicsEngine')
-rw-r--r--Graphics/GraphicsEngine/include/BottomLevelASBase.hpp16
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp98
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBase.hpp3
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp169
-rw-r--r--Graphics/GraphicsEngine/include/TopLevelASBase.hpp81
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h37
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h11
-rw-r--r--Graphics/GraphicsEngine/interface/ShaderBindingTable.h5
8 files changed, 338 insertions, 82 deletions
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
index 41f2fdf3..2bdd51dc 100644
--- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
@@ -184,6 +184,18 @@ public:
return (this->m_State & State) == State;
}
+#ifdef DILIGENT_DEVELOPMENT
+ void UpdateVersion()
+ {
+ m_Version.fetch_add(1);
+ }
+
+ Uint32 GetVersion() const
+ {
+ return m_Version.load();
+ }
+#endif
+
protected:
static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc)
{
@@ -215,6 +227,10 @@ protected:
std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
StringPool m_StringPool;
+
+#ifdef DILIGENT_DEVELOPMENT
+ std::atomic<Uint32> m_Version{0};
+#endif
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index 829416d2..ba586f4b 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -1855,13 +1855,23 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>::
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 if (RefCntAutoPtr<IBottomLevelAS> pBLAS{Barrier.pResource, IID_BottomLevelAS})
+ else if (RefCntAutoPtr<IBottomLevelAS> pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS})
{
- // AZ TODO
+ const auto& BLASDesc = pBottomLevelAS->GetDesc();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState();
+ DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
+ DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING,
+ "Invlaid new state specified for BLAS '", BLASDesc.Name, "'");
+ DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS");
}
- else if (RefCntAutoPtr<ITopLevelAS> pTLAS{Barrier.pResource, IID_TopLevelAS})
+ else if (RefCntAutoPtr<ITopLevelAS> pTopLevelAS{Barrier.pResource, IID_TopLevelAS})
{
- // AZ TODO
+ const auto& TLASDesc = pTopLevelAS->GetDesc();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState();
+ DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
+ DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING,
+ "Invlaid new state specified for TLAS '", TLASDesc.Name, "'");
+ DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for TLAS");
}
else
{
@@ -1943,6 +1953,12 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
template <typename BaseInterface, typename ImplementationTraits>
bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLASBuildAttribs& Attribs, int)
{
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("BuildBLAS command must be performed outside of render pass");
+ return false;
+ }
+
if (Attribs.pBLAS == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBLAS must not be null");
@@ -2090,6 +2106,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
}
+#endif // DILIGENT_DEVELOPMENT
const auto& BLASDesc = Attribs.pBLAS->GetDesc();
@@ -2113,7 +2130,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
- if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pBLAS->GetScratchBufferSizes().Build)
+ if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pBLAS->GetScratchBufferSizes().Build)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get required size for scratch buffer");
return false;
@@ -2124,7 +2141,6 @@ 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;
}
@@ -2132,6 +2148,12 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
template <typename BaseInterface, typename ImplementationTraits>
bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLASBuildAttribs& Attribs, int)
{
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("BuildTLAS command must be performed outside of render pass");
+ return false;
+ }
+
if (Attribs.pTLAS == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pTLAS must not be null");
@@ -2162,7 +2184,6 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
-#ifdef DILIGENT_DEVELOPMENT
const auto& TLASDesc = Attribs.pTLAS->GetDesc();
if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount)
@@ -2171,9 +2192,11 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
- const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE;
- Uint32 AutoOffsetCounter = 0;
+ const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
+ const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE;
+
+#ifdef DILIGENT_DEVELOPMENT
+ Uint32 AutoOffsetCounter = 0;
// calculate instance data size
for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
@@ -2203,6 +2226,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes)
{
@@ -2210,15 +2234,15 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset > InstDataSize)
+ if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset < InstDataSize)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ...");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer size is too small, ...");
return false;
}
if ((InstDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must be created with BIND_RAY_TRACING flag");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
@@ -2230,7 +2254,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pTLAS->GetScratchBufferSizes().Build)
+ if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pTLAS->GetScratchBufferSizes().Build)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get required size for scratch buffer");
return false;
@@ -2241,7 +2265,6 @@ 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;
}
@@ -2261,6 +2284,12 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
return false;
}
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("CopyBLAS command must be performed outside of render pass");
+ return false;
+ }
+
#ifdef DILIGENT_DEVELOPMENT
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
@@ -2338,7 +2367,19 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
return false;
}
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("CopyTLAS command must be performed outside of render pass");
+ return false;
+ }
+
#ifdef DILIGENT_DEVELOPMENT
+ if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->CheckBLASVersion())
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be rebuilded to apply BLAS changes before being copied to another TLAS");
+ return false;
+ }
+
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2370,6 +2411,33 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const Tra
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
+ if (!Attribs.pSBT->Verify())
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT content is not valid");
+ return false;
+ }
+#endif // DILIGENT_DEVELOPMENT
+
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound.");
+ return false;
+ }
+
+ if (!m_pPipelineState->GetDesc().IsRayTracingPipeline())
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline.");
+ return false;
+ }
+
+ if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name,
+ "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable");
+ return false;
+ }
+
if (Attribs.DimensionX == 0)
LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionX is zero.");
diff --git a/Graphics/GraphicsEngine/include/ShaderBase.hpp b/Graphics/GraphicsEngine/include/ShaderBase.hpp
index 24ad92ee..8b6e9efa 100644
--- a/Graphics/GraphicsEngine/include/ShaderBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBase.hpp
@@ -79,6 +79,9 @@ public:
if ((ShdrDesc.ShaderType == SHADER_TYPE_AMPLIFICATION || ShdrDesc.ShaderType == SHADER_TYPE_MESH) && !deviceFeatures.MeshShaders)
LOG_ERROR_AND_THROW("Mesh shaders are not supported by this device");
+
+ if ((ShdrDesc.ShaderType >= SHADER_TYPE_RAY_GEN && ShdrDesc.ShaderType <= SHADER_TYPE_CALLABLE) && !deviceFeatures.RayTracing)
+ LOG_ERROR_AND_THROW("Ray tracing shaders are not supported by this device");
}
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Shader, TDeviceObjectBase)
diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
index 35371958..b5642a75 100644
--- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
@@ -65,41 +65,78 @@ public:
TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
{
ValidateShaderBindingTableDesc(Desc);
+
+ this->m_pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
+ this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize;
+ this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize();
}
~ShaderBindingTableBase()
{
}
- void BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final
+ void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override final
{
- VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ this->m_RayGenShaderRecord.clear();
+ this->m_MissShadersRecord.clear();
+ this->m_CallableShadersRecord.clear();
+ this->m_HitGroupsRecord.clear();
+ this->m_Changed = true;
+ this->m_pPSO = nullptr;
+ this->m_Desc = {};
+
+ try
+ {
+ ValidateShaderBindingTableDesc(Desc);
+ }
+ catch (const std::runtime_error&)
+ {
+ return;
+ }
- this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride);
- ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride);
+ this->m_Desc = Desc;
+ this->m_pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
+ this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize;
+ this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize();
+ }
+
+ void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final
+ {
+ VERIFY_EXPR((Data == nullptr) == (DataSize == 0));
+ VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize));
+
+ this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, EmptyElem);
+ this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride);
+
+ const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize();
+ std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, Data, DataSize);
this->m_Changed = true;
}
- void BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final
+ void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final
{
- VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR((Data == nullptr) == (DataSize == 0));
+ VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize));
- const Uint32 Offset = MissIndex * this->m_ShaderRecordStride;
- this->m_MissShadersRecord.resize(std::max<size_t>(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+ const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize();
+ const Uint32 Offset = MissIndex * this->m_ShaderRecordStride;
+ this->m_MissShadersRecord.resize(std::max<size_t>(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem);
- ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, Data, DataSize);
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
+ void DILIGENT_CALL_TYPE 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((Data == nullptr) == (DataSize == 0));
+ VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize));
VERIFY_EXPR(pTLAS != nullptr);
VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY);
@@ -111,21 +148,23 @@ public:
const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName);
const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
const Uint32 Offset = Index * this->m_ShaderRecordStride;
+ const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize();
- this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride));
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem);
- ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, Data, DataSize);
this->m_Changed = true;
}
- void BindHitGroups(ITopLevelAS* pTLAS,
- const char* InstanceName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize) override final
+ void DILIGENT_CALL_TYPE 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((Data == nullptr) == (DataSize == 0));
VERIFY_EXPR(pTLAS != nullptr);
VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY ||
@@ -134,39 +173,64 @@ public:
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);
+ const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex;
+ const auto& GeometryDesc = Desc.pBLAS->GetDesc();
+ Uint32 GeometryCount = 0;
+
+ switch (pTLAS->GetDesc().BindingMode)
+ {
+ // clang-format off
+ case SHADER_BINDING_MODE_PER_GEOMETRY: GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount; break;
+ case SHADER_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break;
+ default: UNEXPECTED("unknown binding mode");
+ // clang-format on
+ }
+
+ VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize * GeometryCount));
- this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride));
+ const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize();
+ const auto* DataPtr = static_cast<const Uint8*>(Data);
+
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride), EmptyElem);
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_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+
+ std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, DataPtr, this->m_ShaderRecordSize);
+ DataPtr += this->m_ShaderRecordSize;
}
this->m_Changed = true;
}
- void BindCallableShader(const char* ShaderGroupName,
- Uint32 CallableIndex,
- const void* Data,
- Uint32 DataSize) override final
+ void DILIGENT_CALL_TYPE BindCallableShader(const char* ShaderGroupName,
+ Uint32 CallableIndex,
+ const void* Data,
+ Uint32 DataSize) override final
{
- VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR((Data == nullptr) == (DataSize == 0));
+ VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize));
- const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride;
- this->m_CallableShadersRecord.resize(std::max<size_t>(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+ const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize();
+ const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride;
+ this->m_CallableShadersRecord.resize(std::max<size_t>(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem);
- ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, Data, DataSize);
this->m_Changed = true;
}
+ Bool DILIGENT_CALL_TYPE Verify() const override final
+ {
+ // AZ TODO
+ return true;
+ }
+
protected:
- static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc)
+ void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const
{
#define LOG_SBT_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)
@@ -180,6 +244,20 @@ protected:
LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline");
}
+ const auto ShaderGroupHandleSize = this->m_pDevice->GetShaderGroupHandleSize();
+ const auto MaxShaderRecordStride = this->m_pDevice->GetMaxShaderRecordStride();
+ const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize;
+ const auto ShaderRecordStride = ShaderRecordSize + ShaderGroupHandleSize;
+
+ if (ShaderRecordStride > MaxShaderRecordStride)
+ {
+ LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", MaxShaderRecordStride - ShaderGroupHandleSize);
+ }
+
+ if (ShaderRecordStride % ShaderGroupHandleSize != 0)
+ {
+ LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") plus ShaderGroupHandleSize(", ShaderGroupHandleSize, ") must be multiple of ", ShaderGroupHandleSize);
+ }
#undef LOG_SBT_ERROR_AND_THROW
}
@@ -191,8 +269,13 @@ protected:
std::vector<Uint8> m_CallableShadersRecord;
std::vector<Uint8> m_HitGroupsRecord;
+ RefCntAutoPtr<PipelineStateImplType> m_pPSO;
+
+ Uint32 m_ShaderRecordSize = 0;
Uint32 m_ShaderRecordStride = 0;
bool m_Changed = true;
+
+ static const Uint8 EmptyElem = 0xA7;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
index ab56636f..b03d9e5c 100644
--- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
@@ -47,7 +47,7 @@ namespace Diligent
/// (Diligent::ITopLevelASD3D12 or Diligent::ITopLevelASVk).
/// \tparam RenderDeviceImplType - type of the render device implementation
/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl)
-template <class BaseInterface, class RenderDeviceImplType>
+template <class BaseInterface, class BottomLevelASType, class RenderDeviceImplType>
class TopLevelASBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, TopLevelASDesc>
{
public:
@@ -73,8 +73,9 @@ public:
void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance)
{
- m_Instances.clear();
- m_StringPool.Release();
+ this->m_Instances.clear();
+ this->m_StringPool.Release();
+ this->m_HitShadersPerInstance = HitShadersPerInstance;
size_t StringPoolSize = 0;
for (Uint32 i = 0; i < InstanceCount; ++i)
@@ -82,30 +83,61 @@ public:
StringPoolSize += strlen(pInstances[i].InstanceName) + 1;
}
- m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
+ this->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);
+ const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName);
InstanceDesc Desc = {};
Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex;
- Desc.pBLAS = inst.pBLAS;
+ Desc.pBLAS = ValidatedCast<BottomLevelASType>(inst.pBLAS);
+
+#ifdef DILIGENT_DEVELOPMENT
+ Desc.Version = Desc.pBLAS->GetVersion();
+#endif
if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
{
Desc.ContributionToHitGroupIndex = InstanceOffset;
auto& BLASDesc = Desc.pBLAS->GetDesc();
- InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance;
+ switch (this->m_Desc.BindingMode)
+ {
+ // clang-format off
+ case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break;
+ case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break;
+ case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break;
+ default: UNEXPECTED("unknown ray tracing shader binding mode");
+ // clang-format on
+ }
}
- bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second;
+ bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second;
if (!IsUniqueName)
LOG_ERROR_AND_THROW("Instance name must be unique!");
}
+
+ VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0);
+ }
+
+ void CopyInstancceData(const TopLevelASBase& Src)
+ {
+ this->m_Instances.clear();
+ this->m_StringPool.Release();
+ this->m_StringPool.Reserve(Src.m_StringPool.GetReservedSize(), GetRawAllocator());
+ this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance;
+ this->m_Desc.BindingMode = Src.m_Desc.BindingMode;
+
+ for (auto& SrcInst : Src.m_Instances)
+ {
+ const char* NameCopy = this->m_StringPool.CopyString(SrcInst.first.GetStr());
+ this->m_Instances.emplace(NameCopy, SrcInst.second);
+ }
+
+ VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0);
}
virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final
@@ -114,11 +146,11 @@ public:
TLASInstanceDesc Result = {};
- auto iter = m_Instances.find(Name);
- if (iter != m_Instances.end())
+ auto iter = this->m_Instances.find(Name);
+ if (iter != this->m_Instances.end())
{
Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex;
- Result.pBLAS = iter->second.pBLAS;
+ Result.pBLAS = iter->second.pBLAS.RawPtr<IBottomLevelAS>();
}
else
{
@@ -150,6 +182,22 @@ public:
return (this->m_State & State) == State;
}
+#ifdef DILIGENT_DEVELOPMENT
+ bool CheckBLASVersion() const
+ {
+ for (auto& NameAndInst : m_Instances)
+ {
+ auto& Inst = NameAndInst.second;
+ if (Inst.Version != Inst.pBLAS->GetVersion())
+ {
+ LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS that was changed after TLAS build, you must rebuild TLAS.");
+ return false;
+ }
+ }
+ return true;
+ }
+#endif
+
protected:
static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc)
{
@@ -172,14 +220,19 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase)
protected:
- RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+ RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+ Uint32 m_HitShadersPerInstance = 0;
StringPool m_StringPool;
struct InstanceDesc
{
- Uint32 ContributionToHitGroupIndex = 0;
- mutable RefCntAutoPtr<IBottomLevelAS> pBLAS;
+ Uint32 ContributionToHitGroupIndex = 0;
+ RefCntAutoPtr<BottomLevelASType> pBLAS;
+
+#ifdef DILIGENT_DEVELOPMENT
+ Uint32 Version = 0;
+#endif
};
std::unordered_map<HashMapStringKey, InstanceDesc, HashMapStringKey::Hasher> m_Instances;
};
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index 35e17e91..0cb7fe7d 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -741,7 +741,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8)
/// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag.
RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08,
- RAYTRACING_INSTANCE_FLAGS_LAST = 0x08
+ RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE
};
DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS)
@@ -757,7 +757,7 @@ DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8)
// after the build of the acceleration structure specified by src.
//COPY_AS_MODE_COMPACT,
- COPY_AS_MODE_LAST = 0,
+ COPY_AS_MODE_LAST = COPY_AS_MODE_CLONE,
};
/// Defines geometry flags for ray tracing.
@@ -775,7 +775,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8)
/// If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry.
RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02,
- RAYTRACING_GEOMETRY_FLAGS_LAST = 0x02
+ RAYTRACING_GEOMETRY_FLAGS_LAST = RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION
};
DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS)
@@ -910,6 +910,35 @@ static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u;
/// AZ TODO
static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64;
+/// AZ TODO
+struct InstanceMatrix
+{
+ /// rotation translation
+ /// (0 1 2) [ 3]
+ /// (4 5 6) [ 7]
+ /// (8 9 10) [11]
+ float data [3][4];
+
+#if DILIGENT_CPP_INTERFACE
+ /// AZ TODO
+ InstanceMatrix() noexcept :
+ data{{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f}}
+ {}
+
+ InstanceMatrix(const InstanceMatrix&) noexcept = default;
+
+ InstanceMatrix& SetTranslation(float x, float y, float z) noexcept
+ {
+ data[0][3] = x;
+ data[1][3] = y;
+ data[2][3] = z;
+ return *this;
+ }
+#endif
+};
+typedef struct InstanceMatrix InstanceMatrix;
/// AZ TODO
struct TLASBuildInstanceData
@@ -921,7 +950,7 @@ struct TLASBuildInstanceData
IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance
/// AZ TODO
- float Transform[3][4] DEFAULT_INITIALIZER({});
+ InstanceMatrix Transform;
/// AZ TODO
Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h
index 4115a9d1..ebec8344 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -299,8 +299,11 @@ typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderG
/// AZ TODO
struct RayTracingPipelineDesc
{
+ // Size of the additional data passed to the shader.
+ Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0);
+
/// AZ TODO
- Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits)
+ Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits)
};
typedef struct RayTracingPipelineDesc RayTracingPipelineDesc;
@@ -438,7 +441,7 @@ typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo;
struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo)
/// AZ TODO
- RayTracingPipelineDesc RayTracingPipeline;
+ RayTracingPipelineDesc RayTracingPipeline;
/// AZ TODO
const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr);
@@ -457,6 +460,10 @@ struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo
/// AZ TODO
Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0);
+
+ /// Direct3D12 only: set name of constant buffer that will be used by local root signature.
+ /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero.
+ const char* ShaderRecordName DEFAULT_INITIALIZER(nullptr);
};
typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo;
diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
index 2a5e587a..d6f0740f 100644
--- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
+++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
@@ -51,9 +51,6 @@ struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs)
/// AZ TODO
IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr);
-
- // Size of the additional data passed to the shader, maximum size is 4064 bytes.
- Uint32 ShaderRecordSize DEFAULT_INITIALIZER(0);
/// AZ TODO
Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
@@ -114,7 +111,7 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject)
#endif
/// AZ TODO
- VIRTUAL void METHOD(Verify)(THIS) CONST PURE;
+ VIRTUAL Bool METHOD(Verify)(THIS) CONST PURE;
/// AZ TODO
VIRTUAL void METHOD(Reset)(THIS_