summaryrefslogtreecommitdiffstats
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
parentFew improvements to ray tracing tests (diff)
downloadDiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.tar.gz
DiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.zip
fixed resource state transitions, some improvements for ray tracing
-rw-r--r--Common/interface/StringPool.hpp4
-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
-rw-r--r--Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp7
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp6
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp7
-rw-r--r--Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp5
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h1
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp44
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp45
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp40
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp111
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp45
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp40
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp29
-rw-r--r--Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h120
-rw-r--r--Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h99
-rw-r--r--Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp155
-rw-r--r--Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp679
-rw-r--r--Tests/DiligentCoreAPITest/src/RayTracingTest.cpp333
-rw-r--r--Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp746
34 files changed, 2312 insertions, 657 deletions
diff --git a/Common/interface/StringPool.hpp b/Common/interface/StringPool.hpp
index 793668bf..b44711fe 100644
--- a/Common/interface/StringPool.hpp
+++ b/Common/interface/StringPool.hpp
@@ -161,6 +161,10 @@ public:
VERIFY(m_pCurrPtr <= m_pBuffer + m_ReservedSize, "Buffer overflow");
return m_pCurrPtr - m_pBuffer;
}
+ size_t GetReservedSize() const
+ {
+ return m_ReservedSize;
+ }
private:
Char* m_pBuffer = nullptr;
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_
diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
index 5e69da8e..5be505a1 100644
--- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
@@ -61,7 +61,7 @@ struct DeviceContextD3D11ImplTraits
using FramebufferType = FramebufferD3D11Impl;
using RenderPassType = RenderPassD3D11Impl;
using BottomLevelASType = BottomLevelASBase<IBottomLevelAS, RenderDeviceD3D11Impl>;
- using TopLevelASType = TopLevelASBase<ITopLevelAS, RenderDeviceD3D11Impl>;
+ using TopLevelASType = TopLevelASBase<ITopLevelAS, BottomLevelASType, RenderDeviceD3D11Impl>;
};
/// Device context implementation in Direct3D11 backend.
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
index 6a27a029..f336c6ff 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
@@ -144,8 +144,11 @@ private:
void Destruct();
- CComPtr<ID3D12DeviceChild> m_pd3d12PSO;
- RootSignature m_RootSig;
+ void CreateLocalRootSignature(const RayTracingPipelineDesc& Desc);
+
+ CComPtr<ID3D12DeviceChild> m_pd3d12PSO;
+ RootSignature m_RootSig;
+ CComPtr<ID3D12RootSignature> m_LocalRootSignature;
// Must be defined before default SRB
SRBMemoryAllocator m_SRBMemAllocator;
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
index ab72e22a..636175d5 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
@@ -178,10 +178,8 @@ public:
ShaderVersion GetMaxShaderModel() const;
D3D_FEATURE_LEVEL GetD3DFeatureLevel() const;
- static Uint32 GetShaderGroupHandleSize()
- {
- return D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
- }
+ static Uint32 GetShaderGroupHandleSize() { return D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; }
+ static Uint32 GetMaxShaderRecordStride() { return D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE; }
private:
template <typename PSOCreateInfoType>
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp
index e866c6f2..daf84d14 100644
--- a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp
@@ -54,10 +54,6 @@ public:
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
- virtual void DILIGENT_CALL_TYPE Verify() const override;
-
- virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override;
-
virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override;
virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override;
@@ -70,9 +66,6 @@ public:
D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& CallableShaderBindingTable) override;
private:
- void ValidateDesc(const ShaderBindingTableDesc& Desc) const;
-
-private:
RefCntAutoPtr<IBuffer> m_pBuffer;
};
diff --git a/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp
index 8eccf530..c61ab368 100644
--- a/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp
@@ -33,6 +33,7 @@
#include "TopLevelASD3D12.h"
#include "RenderDeviceD3D12.h"
#include "TopLevelASBase.hpp"
+#include "BottomLevelASD3D12Impl.hpp"
#include "D3D12ResourceBase.hpp"
#include "RenderDeviceD3D12Impl.hpp"
@@ -40,10 +41,10 @@ namespace Diligent
{
/// Top-level acceleration structure object implementation in Direct3D12 backend.
-class TopLevelASD3D12Impl final : public TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>, public D3D12ResourceBase
+class TopLevelASD3D12Impl final : public TopLevelASBase<ITopLevelASD3D12, BottomLevelASD3D12Impl, RenderDeviceD3D12Impl>, public D3D12ResourceBase
{
public:
- using TTopLevelASBase = TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>;
+ using TTopLevelASBase = TopLevelASBase<ITopLevelASD3D12, BottomLevelASD3D12Impl, RenderDeviceD3D12Impl>;
TopLevelASD3D12Impl(IReferenceCounters* pRefCounters,
class RenderDeviceD3D12Impl* pDeviceD3D12,
diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h
index 4b0835cd..aa50251a 100644
--- a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h
@@ -65,6 +65,7 @@ DILIGENT_END_INTERFACE
#if DILIGENT_C_INTERFACE
+# define IShaderBindingTableD3D12_GetD3D12AddressRangeAndStride(This, ...) CALL_IFACE_METHOD(ShaderBindingTableD3D12, GetD3D12AddressRangeAndStride, This, __VA_ARGS__)
#endif
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 3cd896ac..0adcaa59 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -2198,8 +2198,6 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext&
RESOURCE_STATE RequiredState,
const char* OperationName)
{
- // AZ TODO: transit BLAS state too?
-
if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState))
@@ -2210,6 +2208,11 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext&
{
DvpVerifyTLASState(TLAS, RequiredState, OperationName);
}
+
+ if (RequiredState & RESOURCE_STATE_RAY_TRACING)
+ {
+ TLAS.CheckBLASVersion();
+ }
#endif
}
@@ -2318,6 +2321,8 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs)
d3d12Tris.VertexBuffer.StartAddress = pVB->GetGPUAddress() + SrcTris.VertexOffset;
d3d12Tris.VertexBuffer.StrideInBytes = SrcTris.VertexStride;
+ TransitionOrVerifyBufferState(CmdCtx, *pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+
if (SrcTris.pIndexBuffer)
{
auto* const pIB = ValidatedCast<BufferD3D12Impl>(SrcTris.pIndexBuffer);
@@ -2389,6 +2394,10 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs)
CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr);
++m_State.NumCommands;
+
+#ifdef DILIGENT_DEVELOPMENT
+ pBLASD12->UpdateVersion();
+#endif
}
void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs)
@@ -2401,7 +2410,6 @@ void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs)
auto* pTLASD12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pTLAS);
auto* pScratchD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pScratchBuffer);
auto* pInstancesD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pInstanceBuffer);
- //auto& TLASDesc = pTLASD12->GetDesc();
auto& CmdCtx = GetCmdContext();
const char* OpName = "Build TopLevelAS (DeviceContextD3D12Impl::BuildTLAS)";
@@ -2423,7 +2431,7 @@ void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs)
auto* const pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(Inst.pBLAS);
static_assert(sizeof(d3d12Inst.Transform) == sizeof(Inst.Transform), "size mismatch");
- std::memcpy(&d3d12Inst.Transform, Inst.Transform, sizeof(d3d12Inst.Transform));
+ std::memcpy(&d3d12Inst.Transform, Inst.Transform.data, sizeof(d3d12Inst.Transform));
d3d12Inst.InstanceID = Inst.CustomId;
d3d12Inst.InstanceContributionToHitGroupIndex = pTLASD12->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize
@@ -2458,7 +2466,20 @@ void DeviceContextD3D12Impl::CopyBLAS(const CopyBLASAttribs& Attribs)
if (!TDeviceContextBase::CopyBLAS(Attribs, 0))
return;
- // AZ TODO
+ auto* pSrcD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pSrc);
+ auto* pDstD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pDst);
+ auto& CmdCtx = GetCmdContext();
+
+ const char* OpName = "Copy BottomLevelAS (DeviceContextD3D12Impl::CopyBLAS)";
+ TransitionOrVerifyBLASState(CmdCtx, *pSrcD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyBLASState(CmdCtx, *pDstD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
+ CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pSrcD3D12->GetGPUAddress(), pDstD3D12->GetGPUAddress(), D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE);
+ ++m_State.NumCommands;
+
+#ifdef DILIGENT_DEVELOPMENT
+ pDstD3D12->UpdateVersion();
+#endif
}
void DeviceContextD3D12Impl::CopyTLAS(const CopyTLASAttribs& Attribs)
@@ -2466,7 +2487,18 @@ void DeviceContextD3D12Impl::CopyTLAS(const CopyTLASAttribs& Attribs)
if (!TDeviceContextBase::CopyTLAS(Attribs, 0))
return;
- // AZ TODO
+ auto* pSrcD3D12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pSrc);
+ auto* pDstD3D12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pDst);
+ auto& CmdCtx = GetCmdContext();
+
+ pDstD3D12->CopyInstancceData(*pSrcD3D12);
+
+ const char* OpName = "Copy BottomLevelAS (DeviceContextD3D12Impl::CopyTLAS)";
+ TransitionOrVerifyTLASState(CmdCtx, *pSrcD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyTLASState(CmdCtx, *pDstD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
+ CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pSrcD3D12->GetGPUAddress(), pDstD3D12->GetGPUAddress(), D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE);
+ ++m_State.NumCommands;
}
void DeviceContextD3D12Impl::TraceRays(const TraceRaysAttribs& Attribs)
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
index 405f6d4b..b1fe19fe 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -224,7 +224,7 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateI
}
template <typename TNameToGroupIndexMap>
-void GetShaderIdentifiers(ID3D12StateObject* pSO,
+void GetShaderIdentifiers(ID3D12DeviceChild* pSO,
const RayTracingPipelineStateCreateInfo& CreateInfo,
const TNameToGroupIndexMap& NameToGroupIndex,
Uint8* ShaderData)
@@ -625,6 +625,8 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters*
{
try
{
+ CreateLocalRootSignature(CreateInfo.RayTracingPipeline);
+
TShaderStages ShaderStages;
std::vector<D3D12_STATE_SUBOBJECT> Subobjects;
DynamicLinearAllocator TempPool{GetRawAllocator(), 4 << 10};
@@ -640,21 +642,21 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters*
D3D12_GLOBAL_ROOT_SIGNATURE GlobalRoot = {m_RootSig.GetD3D12RootSignature()};
Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &GlobalRoot});
+ D3D12_LOCAL_ROOT_SIGNATURE LocalRoot = {m_LocalRootSignature};
+ if (m_LocalRootSignature)
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &LocalRoot});
+
D3D12_STATE_OBJECT_DESC RTPipelineDesc = {};
RTPipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
RTPipelineDesc.NumSubobjects = static_cast<UINT>(Subobjects.size());
RTPipelineDesc.pSubobjects = Subobjects.data();
- CComPtr<ID3D12StateObject> pSO;
-
auto pd3d12Device = pDeviceD3D12->GetD3D12Device5();
- HRESULT hr = pd3d12Device->CreateStateObject(&RTPipelineDesc, IID_PPV_ARGS(&pSO));
+ HRESULT hr = pd3d12Device->CreateStateObject(&RTPipelineDesc, IID_PPV_ARGS(&m_pd3d12PSO));
if (FAILED(hr))
LOG_ERROR_AND_THROW("Failed to create ray tracing state object");
- m_pd3d12PSO = pSO;
-
- GetShaderIdentifiers(pSO, CreateInfo, m_pRayTracingPipelineData->NameToGroupIndex, m_pRayTracingPipelineData->Shaders);
+ GetShaderIdentifiers(m_pd3d12PSO, CreateInfo, m_pRayTracingPipelineData->NameToGroupIndex, m_pRayTracingPipelineData->Shaders);
if (*m_Desc.Name != 0)
{
@@ -672,6 +674,35 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters*
}
}
+void PipelineStateD3D12Impl::CreateLocalRootSignature(const RayTracingPipelineDesc& Desc)
+{
+ // AZ TODO
+ /*if (Desc.ShaderRecordSize == 0)
+ return;
+
+ D3D12_ROOT_SIGNATURE_DESC d3d12RootSignatureDesc = {};
+ D3D12_ROOT_PARAMETER d3d12Params = {};
+
+ d3d12Params.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ d3d12Params.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ d3d12Params.Constants.Num32BitValues = Desc.ShaderRecordSize / 4;
+ d3d12Params.Constants.RegisterSpace = Desc.LocalRootRegisterSpace;
+ d3d12Params.Constants.ShaderRegister = 0;
+
+ d3d12RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
+ d3d12RootSignatureDesc.NumParameters = 1;
+ d3d12RootSignatureDesc.pParameters = &d3d12Params;
+
+ CComPtr<ID3DBlob> signature;
+ auto hr = D3D12SerializeRootSignature(&d3d12RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr);
+ CHECK_D3D_RESULT_THROW(hr, "Failed to serialize root signature");
+
+ auto pd3d12Device = GetDevice()->GetD3D12Device();
+
+ hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_LocalRootSignature));
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature");*/
+}
+
PipelineStateD3D12Impl::~PipelineStateD3D12Impl()
{
Destruct();
diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
index d0db2201..e6af12c8 100644
--- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
@@ -705,7 +705,7 @@ __forceinline void TransitionResource(CommandContext& Ctx,
{
VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
auto* pTLASD3D12 = Res.pObject.RawPtr<TopLevelASD3D12Impl>();
- if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING))
+ if (pTLASD3D12->IsInKnownState())
Ctx.TransitionResource(pTLASD3D12, RESOURCE_STATE_RAY_TRACING);
}
break;
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp
index d352caf0..d71d98b7 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp
@@ -44,9 +44,6 @@ ShaderBindingTableD3D12Impl::ShaderBindingTableD3D12Impl(IReferenceCounters*
bool bIsDeviceInternal) :
TShaderBindingTableBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal}
{
- ValidateDesc(Desc);
-
- m_ShaderRecordStride = m_Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
}
ShaderBindingTableD3D12Impl::~ShaderBindingTableD3D12Impl()
@@ -55,43 +52,6 @@ ShaderBindingTableD3D12Impl::~ShaderBindingTableD3D12Impl()
IMPLEMENT_QUERY_INTERFACE(ShaderBindingTableD3D12Impl, IID_ShaderBindingTableD3D12, TShaderBindingTableBase)
-void ShaderBindingTableD3D12Impl::ValidateDesc(const ShaderBindingTableDesc& Desc) const
-{
- if (Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES > D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE)
- {
- LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""),
- "' is invalid: ShaderRecordSize is too big, max size is: ", D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE - D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES);
- }
-}
-
-void ShaderBindingTableD3D12Impl::Verify() const
-{
- // AZ TODO
-}
-
-void ShaderBindingTableD3D12Impl::Reset(const ShaderBindingTableDesc& Desc)
-{
- m_RayGenShaderRecord.clear();
- m_MissShadersRecord.clear();
- m_CallableShadersRecord.clear();
- m_HitGroupsRecord.clear();
- m_Changed = true;
-
- try
- {
- ValidateShaderBindingTableDesc(Desc);
- ValidateDesc(Desc);
- }
- catch (const std::runtime_error&)
- {
- // AZ TODO
- return;
- }
-
- m_Desc = Desc;
- m_ShaderRecordStride = m_Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
-}
-
void ShaderBindingTableD3D12Impl::ResetHitGroups(Uint32 HitShadersPerInstance)
{
// AZ TODO
diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
index 0b2154e6..32055367 100644
--- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
@@ -56,7 +56,7 @@ struct DeviceContextGLImplTraits
using FramebufferType = FramebufferGLImpl;
using RenderPassType = RenderPassGLImpl;
using BottomLevelASType = BottomLevelASBase<IBottomLevelAS, RenderDeviceGLImpl>;
- using TopLevelASType = TopLevelASBase<ITopLevelAS, RenderDeviceGLImpl>;
+ using TopLevelASType = TopLevelASBase<ITopLevelAS, BottomLevelASType, RenderDeviceGLImpl>;
};
/// Device context implementation in OpenGL backend.
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index e13f1a76..5440a6c8 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -201,6 +201,10 @@ public:
{
return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize;
}
+ Uint32 GetMaxShaderRecordStride() const
+ {
+ return GetPhysicalDevice().GetExtProperties().RayTracing.maxShaderGroupStride;
+ }
private:
template <typename PSOCreateInfoType>
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
index 1b2db950..cef50a4e 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
@@ -51,10 +51,6 @@ public:
bool bIsDeviceInternal = false);
~ShaderBindingTableVkImpl();
- virtual void DILIGENT_CALL_TYPE Verify() const override;
-
- virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override;
-
virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override;
virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override;
@@ -68,9 +64,6 @@ public:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase);
private:
- void ValidateDesc(const ShaderBindingTableDesc& Desc) const;
-
-private:
RefCntAutoPtr<IBuffer> m_pBuffer;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
index b2801eca..0f8a94c8 100644
--- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
@@ -34,15 +34,16 @@
#include "RenderDeviceVkImpl.hpp"
#include "TopLevelASVk.h"
#include "TopLevelASBase.hpp"
+#include "BottomLevelASVkImpl.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
namespace Diligent
{
-class TopLevelASVkImpl final : public TopLevelASBase<ITopLevelASVk, RenderDeviceVkImpl>
+class TopLevelASVkImpl final : public TopLevelASBase<ITopLevelASVk, BottomLevelASVkImpl, RenderDeviceVkImpl>
{
public:
- using TTopLevelASBase = TopLevelASBase<ITopLevelASVk, RenderDeviceVkImpl>;
+ using TTopLevelASBase = TopLevelASBase<ITopLevelASVk, BottomLevelASVkImpl, RenderDeviceVkImpl>;
TopLevelASVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pRenderDeviceVk,
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 69a3a1ba..a77fb96d 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -2334,6 +2334,22 @@ void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayou
}
}
+namespace
+{
+NODISCARD inline bool ResourceStateHasWriteAccess(RESOURCE_STATE State)
+{
+ static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag");
+ constexpr RESOURCE_STATE WriteAccessStates =
+ RESOURCE_STATE_RENDER_TARGET |
+ RESOURCE_STATE_UNORDERED_ACCESS |
+ RESOURCE_STATE_COPY_DEST |
+ RESOURCE_STATE_RESOLVE_DEST |
+ RESOURCE_STATE_BUILD_AS_WRITE;
+
+ return State & WriteAccessStates;
+}
+} // namespace
+
void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& TextureVk,
RESOURCE_STATE OldState,
RESOURCE_STATE NewState,
@@ -2396,17 +2412,22 @@ void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& Textur
pSubresRange->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
- // Note that when both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
+ // Always add barrier after writes.
+ const bool AfterWrite = ResourceStateHasWriteAccess(OldState);
+
auto OldLayout = ResourceStateToVkImageLayout(OldState);
auto NewLayout = ResourceStateToVkImageLayout(NewState);
auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
- m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange, OldStages, NewStages);
- if (UpdateTextureState)
+
+ if (((OldState & NewState) != NewState) || OldLayout != NewLayout || AfterWrite)
{
- TextureVk.SetState(NewState);
- VERIFY_EXPR(TextureVk.GetLayout() == NewLayout);
+ m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange, OldStages, NewStages);
+ if (UpdateTextureState)
+ {
+ TextureVk.SetState(NewState);
+ VERIFY_EXPR(TextureVk.GetLayout() == NewLayout);
+ }
}
}
@@ -2421,10 +2442,7 @@ void DeviceContextVkImpl::TransitionOrVerifyTextureState(TextureVkImpl&
VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (Texture.IsInKnownState())
{
- if (!Texture.CheckState(RequiredState))
- {
- TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true);
VERIFY_EXPR(Texture.GetLayout() == ExpectedLayout);
}
}
@@ -2489,9 +2507,10 @@ void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE
}
}
- // When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
- if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS || NewState == RESOURCE_STATE_BUILD_AS_WRITE)
+ // Always add barrier after writes.
+ const bool AfterWrite = ResourceStateHasWriteAccess(OldState);
+
+ if (((OldState & NewState) != NewState) || AfterWrite)
{
DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
@@ -2521,10 +2540,7 @@ void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl&
VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (Buffer.IsInKnownState())
{
- if (!Buffer.CheckState(RequiredState))
- {
- TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true);
VERIFY_EXPR(Buffer.CheckAccessFlags(ExpectedAccessFlags));
}
}
@@ -2564,7 +2580,10 @@ void DeviceContextVkImpl::TransitionBLASState(BottomLevelASVkImpl& BLAS,
}
}
- if ((OldState & NewState) != NewState)
+ // Always add barrier after writes.
+ const bool AfterWrite = ResourceStateHasWriteAccess(OldState);
+
+ if ((OldState & NewState) != NewState || AfterWrite)
{
EnsureVkCmdBuffer();
auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
@@ -2584,8 +2603,6 @@ void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS,
RESOURCE_STATE NewState,
bool UpdateInternalState)
{
- // AZ TODO: transit BLAS state too?
-
VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (OldState == RESOURCE_STATE_UNKNOWN)
{
@@ -2609,7 +2626,10 @@ void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS,
}
}
- if ((OldState & NewState) != NewState)
+ // Always add barrier after writes.
+ const bool AfterWrite = ResourceStateHasWriteAccess(OldState);
+
+ if ((OldState & NewState) != NewState || AfterWrite)
{
EnsureVkCmdBuffer();
auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
@@ -2634,10 +2654,7 @@ void DeviceContextVkImpl::TransitionOrVerifyBLASState(BottomLevelASVkImpl&
VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (BLAS.IsInKnownState())
{
- if (!BLAS.CheckState(RequiredState))
- {
- TransitionBLASState(BLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ TransitionBLASState(BLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
}
#ifdef DILIGENT_DEVELOPMENT
@@ -2658,10 +2675,7 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl&
VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
if (TLAS.IsInKnownState())
{
- if (!TLAS.CheckState(RequiredState))
- {
- TransitionTLASState(TLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ TransitionTLASState(TLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
}
#ifdef DILIGENT_DEVELOPMENT
@@ -2669,6 +2683,11 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl&
{
DvpVerifyTLASState(TLAS, RequiredState, OperationName);
}
+
+ if (RequiredState & RESOURCE_STATE_RAY_TRACING)
+ {
+ TLAS.CheckBLASVersion();
+ }
#endif
}
@@ -2718,13 +2737,13 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra
{
TransitionBufferState(*pBuffer, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
}
- else if (RefCntAutoPtr<BottomLevelASVkImpl> pBLAS{Barrier.pResource, IID_BottomLevelAS})
+ else if (RefCntAutoPtr<BottomLevelASVkImpl> pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS})
{
- TransitionBLASState(*pBLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ TransitionBLASState(*pBottomLevelAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
}
- else if (RefCntAutoPtr<TopLevelASVkImpl> pTLAS{Barrier.pResource, IID_TopLevelAS})
+ else if (RefCntAutoPtr<TopLevelASVkImpl> pTopLevelAS{Barrier.pResource, IID_TopLevelAS})
{
- TransitionTLASState(*pTLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ TransitionTLASState(*pTopLevelAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
}
else
{
@@ -2808,7 +2827,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
const char* OpName = "Build BottomLevelAS (DeviceContextVkImpl::BuildBLAS)";
TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
- TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VkAccessFlagBits(0), OpName);
+ TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName);
VkAccelerationStructureBuildGeometryInfoKHR Info = {};
std::vector<VkAccelerationStructureBuildOffsetInfoKHR> Offsets;
@@ -2845,7 +2864,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
vkTris.vertexStride = SrcTris.VertexStride;
vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset;
- TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast<VkAccessFlagBits>(0), OpName);
+ TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName);
if (SrcTris.pIndexBuffer)
{
@@ -2854,7 +2873,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset;
off.primitiveCount = SrcTris.IndexCount / 3;
- TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast<VkAccessFlagBits>(0), OpName);
+ TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName);
}
else
{
@@ -2870,7 +2889,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
auto* const pTB = ValidatedCast<BufferVkImpl>(SrcTris.pTransformBuffer);
vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset;
- TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+ TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName);
}
else
{
@@ -2913,7 +2932,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
vkAABBs.stride = SrcBoxes.BoxStride;
vkAABBs.data.deviceAddress = pBB->GetVkDeviceAddress() + SrcBoxes.BoxOffset;
- TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+ TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName);
off.firstVertex = 0;
off.transformOffset = 0;
@@ -2939,6 +2958,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
EnsureVkCmdBuffer();
m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr);
++m_State.NumCommands;
+
+#ifdef DILIGENT_DEVELOPMENT
+ pBLASVk->UpdateVersion();
+#endif
}
void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
@@ -2964,7 +2987,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
const char* OpName = "Build TopLevelAS (DeviceContextVkImpl::BuildTLAS)";
TransitionOrVerifyTLASState(*pTLASVk, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
- TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VkAccessFlagBits(0), OpName);
+ TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName);
pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance);
@@ -2981,7 +3004,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
auto* const pBLASVk = ValidatedCast<BottomLevelASVkImpl>(Inst.pBLAS);
static_assert(sizeof(vkASInst.transform) == sizeof(Inst.Transform), "size mismatch");
- std::memcpy(&vkASInst.transform, Inst.Transform, sizeof(vkASInst.transform));
+ std::memcpy(&vkASInst.transform, Inst.Transform.data, sizeof(vkASInst.transform));
vkASInst.instanceCustomIndex = Inst.CustomId;
vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize
@@ -2994,7 +3017,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode);
}
- TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+ TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName);
VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {};
VkAccelerationStructureBuildOffsetInfoKHR vkASBuildOffset = {};
@@ -3060,6 +3083,10 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
m_CommandBuffer.CopyAccelerationStructure(Info);
++m_State.NumCommands;
+
+#ifdef DILIGENT_DEVELOPMENT
+ pDstVk->UpdateVersion();
+#endif
}
void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
@@ -3077,6 +3104,8 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
auto* pSrcVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pSrc);
auto* pDstVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pDst);
+ pDstVk->CopyInstancceData(*pSrcVk);
+
VkCopyAccelerationStructureInfoKHR Info = {};
Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR;
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 36ca3a42..1cac2b6f 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -758,10 +758,16 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters*
{
try
{
+ const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
+ const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize();
+
+ if (LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing == VK_FALSE)
+ LOG_ERROR_AND_THROW("Ray tracing is not supported by this device");
+
std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
-
std::vector<VkRayTracingShaderGroupCreateInfoKHR> ShaderGroups;
+
InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules,
[&](const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages& ShaderStages) //
{
@@ -773,9 +779,6 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters*
CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline);
- const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
- const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize();
-
auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast<uint32_t>(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]);
VERIFY(err == VK_SUCCESS, "Failed to get shader group handles");
(void)err;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
index 6f5091e0..3940769f 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
@@ -39,57 +39,12 @@ ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters*
bool bIsDeviceInternal) :
TShaderBindingTableBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}
{
- ValidateDesc(Desc);
-
- const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
- m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
}
ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl()
{
}
-void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const
-{
- const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
-
- if (Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize > RTLimits.maxShaderGroupStride)
- {
- LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""),
- "' is invalid: ShaderRecordSize is too big, max size is: ", RTLimits.maxShaderGroupStride - RTLimits.shaderGroupHandleSize);
- }
-}
-
-void ShaderBindingTableVkImpl::Verify() const
-{
- // AZ TODO
-}
-
-void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc)
-{
- m_RayGenShaderRecord.clear();
- m_MissShadersRecord.clear();
- m_CallableShadersRecord.clear();
- m_HitGroupsRecord.clear();
- m_Changed = true;
-
- try
- {
- ValidateShaderBindingTableDesc(Desc);
- ValidateDesc(Desc);
- }
- catch (const std::runtime_error&)
- {
- // AZ TODO
- return;
- }
-
- m_Desc = Desc;
-
- const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
- m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
-}
-
void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance)
{
// AZ TODO
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index 8101fefc..27e5ee72 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -166,10 +166,9 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
{
constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_CONSTANT_BUFFER;
VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & VK_ACCESS_UNIFORM_READ_BIT) == VK_ACCESS_UNIFORM_READ_BIT);
- const bool IsInRequiredState = pBufferVk->CheckState(RequiredState);
if (VerifyOnly)
{
- if (!IsInRequiredState)
+ if (!pBufferVk->CheckState(RequiredState))
{
LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ",
GetResourceStateString(RequiredState), ". Actual state: ",
@@ -181,10 +180,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
}
else
{
- if (!IsInRequiredState)
- {
- pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_UNIFORM_READ_BIT));
}
}
@@ -211,11 +207,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & RequiredAccessFlags) == RequiredAccessFlags);
#endif
- const bool IsInRequiredState = pBufferVk->CheckState(RequiredState);
if (VerifyOnly)
{
- if (!IsInRequiredState)
+ if (!pBufferVk->CheckState(RequiredState))
{
LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ",
GetResourceStateString(RequiredState), ". Actual state: ",
@@ -227,12 +222,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
}
else
{
- // When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
- if (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS)
- {
- pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
VERIFY_EXPR(pBufferVk->CheckAccessFlags(RequiredAccessFlags));
}
}
@@ -275,11 +265,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
VERIFY_EXPR(ResourceStateToVkImageLayout(RequiredState) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
}
- const bool IsInRequiredState = pTextureVk->CheckState(RequiredState);
if (VerifyOnly)
{
- if (!IsInRequiredState)
+ if (!pTextureVk->CheckState(RequiredState))
{
LOG_ERROR_MESSAGE("State of texture '", pTextureVk->GetDesc().Name, "' is incorrect. Required state: ",
GetResourceStateString(RequiredState), ". Actual state: ",
@@ -291,12 +280,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
}
else
{
- // When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
- if (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS)
- {
- pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
}
}
@@ -327,11 +311,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
auto* pTLASVk = Res.pObject.RawPtr<TopLevelASVkImpl>();
if (pTLASVk != nullptr && pTLASVk->IsInKnownState())
{
- constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING;
- const bool IsInRequiredState = pTLASVk->CheckState(RequiredState);
+ constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING;
if (VerifyOnly)
{
- if (!IsInRequiredState)
+ if (!pTLASVk->CheckState(RequiredState))
{
LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
GetResourceStateString(RequiredState), ". Actual state: ",
@@ -340,13 +323,12 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
"when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
"with IDeviceContext::TransitionResourceStates().");
}
+
+ pTLASVk->CheckBLASVersion();
}
else
{
- if (!IsInRequiredState)
- {
- pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
+ pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index 143042b8..e039311b 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1613,12 +1613,10 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF
"Please update the switch below to handle the new ray tracing build flag");
VkBuildAccelerationStructureFlagsKHR Result = 0;
- for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1)
+ while (Flags != RAYTRACING_BUILD_AS_NONE)
{
- if ((Flags & Bit) != Bit)
- continue;
-
- switch (static_cast<RAYTRACING_BUILD_AS_FLAGS>(Bit))
+ auto FlagBit = static_cast<RAYTRACING_BUILD_AS_FLAGS>(1 << PlatformMisc::GetLSB(Uint32{Flags}));
+ switch (FlagBit)
{
// clang-format off
case RAYTRACING_BUILD_AS_ALLOW_UPDATE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; break;
@@ -1629,6 +1627,7 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF
// clang-format on
default: UNEXPECTED("unknown build AS flag");
}
+ Flags = Flags & ~FlagBit;
}
return Result;
}
@@ -1639,12 +1638,10 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag
"Please update the switch below to handle the new ray tracing geometry flag");
VkGeometryFlagsKHR Result = 0;
- for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1)
+ while (Flags != RAYTRACING_GEOMETRY_NONE)
{
- if ((Flags & Bit) != Bit)
- continue;
-
- switch (static_cast<RAYTRACING_GEOMETRY_FLAGS>(Bit))
+ auto FlagBit = static_cast<RAYTRACING_GEOMETRY_FLAGS>(1 << PlatformMisc::GetLSB(Uint32{Flags}));
+ switch (FlagBit)
{
// clang-format off
case RAYTRACING_GEOMETRY_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break;
@@ -1652,6 +1649,7 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag
// clang-format on
default: UNEXPECTED("unknown geometry flag");
}
+ Flags = Flags & ~FlagBit;
}
return Result;
}
@@ -1662,12 +1660,10 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS
"Please update the switch below to handle the new ray tracing instance flag");
VkGeometryInstanceFlagsKHR Result = 0;
- for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1)
+ while (Flags != RAYTRACING_INSTANCE_NONE)
{
- if ((Flags & Bit) != Bit)
- continue;
-
- switch (static_cast<RAYTRACING_INSTANCE_FLAGS>(Bit))
+ auto FlagBit = static_cast<RAYTRACING_INSTANCE_FLAGS>(1 << PlatformMisc::GetLSB(Uint32{Flags}));
+ switch (FlagBit)
{
// clang-format off
case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: Result |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; break;
@@ -1677,6 +1673,7 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS
// clang-format on
default: UNEXPECTED("unknown instance flag");
}
+ Flags = Flags & ~FlagBit;
}
return Result;
}
@@ -1693,7 +1690,7 @@ VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(C
// clang-format on
default:
UNEXPECTED("unknown AS copy mode");
- return static_cast<VkCopyAccelerationStructureModeKHR>(0);
+ return VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR;
}
}
diff --git a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h
index fe761719..7567e526 100644
--- a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h
+++ b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h
@@ -55,7 +55,7 @@ void main()
gl_RayFlagsNoneEXT, // rayFlags
0xFF, // cullMask
0, // sbtRecordOffset
- 0, // sbtRecordStride
+ 1, // sbtRecordStride
0, // missIndex
origin, // ray origin
0.01, // ray min range
@@ -122,7 +122,7 @@ void main()
gl_RayFlagsSkipClosestHitShaderEXT,
0xFF, // cullMask
0, // sbtRecordOffset
- 0, // sbtRecordStride
+ 1, // sbtRecordStride
0, // missIndex
origin, // ray origin
0.01, // ray min range
@@ -207,7 +207,7 @@ void main()
gl_RayFlagsNoneEXT, // rayFlags
0xFF, // cullMask
0, // sbtRecordOffset
- 0, // sbtRecordStride
+ 1, // sbtRecordStride
0, // missIndex
origin, // ray origin
0.01, // ray min range
@@ -280,6 +280,120 @@ void main()
// clang-format on
+// clang-format off
+const std::string RayTracingTest4_RG{
+R"glsl(
+#version 460
+#extension GL_EXT_ray_tracing : require
+
+layout(set=0, binding=0) uniform accelerationStructureEXT g_TLAS;
+layout(set=0, binding=1, rgba8) uniform image2D g_ColorBuffer;
+
+layout(location=0) rayPayloadEXT vec4 payload;
+
+void main()
+{
+ const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1);
+ const vec3 origin = vec3(uv.x, 1.0 - uv.y, -1.0);
+ const vec3 direction = vec3(0.0, 0.0, 1.0);
+
+ payload = vec4(0.0);
+ traceRayEXT(g_TLAS, // acceleration structure
+ gl_RayFlagsNoneEXT, // rayFlags
+ 0xFF, // cullMask
+ 0, // sbtRecordOffset
+ 1, // sbtRecordStride
+ 0, // missIndex
+ origin, // ray origin
+ 0.01, // ray min range
+ direction, // ray direction
+ 10.0, // ray max range
+ 0); // payload location
+
+ imageStore(g_ColorBuffer, ivec2(gl_LaunchIDEXT), payload);
+}
+)glsl"
+};
+
+const std::string RayTracingTest4_RM{
+R"glsl(
+#version 460
+#extension GL_EXT_ray_tracing : require
+
+layout(location=0) rayPayloadInEXT vec4 payload;
+
+void main()
+{
+ payload = vec4(0.0, 0.0, 0.2, 1.0);
+}
+)glsl"
+};
+
+const std::string RayTracingTest4_Uniforms{
+R"glsl(
+#version 460
+#extension GL_EXT_ray_tracing : require
+
+layout(shaderRecordEXT) buffer ShaderRecord
+{
+ vec4 Weights;
+};
+
+layout(location=0) rayPayloadInEXT vec4 payload;
+hitAttributeEXT vec2 hitAttribs;
+
+layout(set=0, binding=2, std430) readonly buffer PerInstanceData {
+ uint PrimitiveOffsets[3];
+} g_PerInstance[2];
+
+layout(set=0, binding=3, std430) readonly buffer PrimitiveData {
+ uvec4 g_Primitives[9];
+};
+
+struct Vertex
+{
+ vec4 Pos;
+ vec4 Color1;
+ vec4 Color2;
+};
+layout(set=0, binding=4, std430) readonly buffer VertexData {
+ Vertex g_Vertices[16];
+};
+)glsl"
+};
+
+const std::string RayTracingTest4_RCH1 = RayTracingTest4_Uniforms +
+R"glsl(
+void main()
+{
+ vec3 barycentrics = vec3(1.0f - hitAttribs.x - hitAttribs.y, hitAttribs.x, hitAttribs.y);// * Weights.xyz;
+ uint primOffset = g_PerInstance[gl_InstanceID].PrimitiveOffsets[gl_GeometryIndexEXT];
+ uvec4 triFace = g_Primitives[primOffset + gl_PrimitiveID];
+ Vertex v0 = g_Vertices[triFace.x];
+ Vertex v1 = g_Vertices[triFace.y];
+ Vertex v2 = g_Vertices[triFace.z];
+ vec4 col = v0.Color2 * barycentrics.x + v1.Color2 * barycentrics.y + v2.Color2 * barycentrics.z;
+ payload = col;
+}
+)glsl";
+
+const std::string RayTracingTest4_RCH2 = RayTracingTest4_Uniforms +
+R"glsl(
+void main()
+{
+ vec3 barycentrics = vec3(1.0f - hitAttribs.x - hitAttribs.y, hitAttribs.x, hitAttribs.y);// * Weights.xyz;
+ uint primOffset = g_PerInstance[gl_InstanceID].PrimitiveOffsets[gl_GeometryIndexEXT];
+ uvec4 triFace = g_Primitives[primOffset + gl_PrimitiveID];
+ Vertex v0 = g_Vertices[triFace.x];
+ Vertex v1 = g_Vertices[triFace.y];
+ Vertex v2 = g_Vertices[triFace.z];
+ vec4 col = v0.Color1 * barycentrics.x + v1.Color1 * barycentrics.y + v2.Color1 * barycentrics.z;
+ payload = col;
+}
+)glsl";
+// clang-format on
+
+
} // namespace GLSL
} // namespace
diff --git a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h
index ed64b700..c6b97b6e 100644
--- a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h
+++ b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h
@@ -86,7 +86,7 @@ R"hlsl(
[shader("closesthit")]
void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr)
{
- float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
+ float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
payload.Color = float4(barycentrics, 1.0);
}
)hlsl";
@@ -147,7 +147,7 @@ R"hlsl(
[shader("anyhit")]
void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr)
{
- float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
+ float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
if (barycentrics.y > barycentrics.x)
IgnoreHit();
else
@@ -241,6 +241,101 @@ void main()
)hlsl";
// clang-format on
+
+// clang-format off
+const std::string RayTracingTest4_RG = RayTracingTest_Payload +
+R"hlsl(
+RaytracingAccelerationStructure g_TLAS : register(t0);
+RWTexture2D<float4> g_ColorBuffer : register(u0);
+
+[shader("raygeneration")]
+void main()
+{
+ const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
+
+ RayDesc ray;
+ ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
+ ray.Direction = float3(0.0, 0.0, 1.0);
+ ray.TMin = 0.01;
+ ray.TMax = 10.0;
+
+ RTPayload payload = {float4(0, 0, 0, 0)};
+ TraceRay(g_TLAS, // Acceleration Structure
+ RAY_FLAG_NONE, // Ray Flags
+ ~0, // Instance Inclusion Mask
+ 0, // Ray Contribution To Hit Group Index
+ 1, // Multiplier For Geometry Contribution To Hit Group Index
+ 0, // Miss Shader Index
+ ray,
+ payload);
+
+ g_ColorBuffer[DispatchRaysIndex().xy] = payload.Color;
+}
+)hlsl";
+
+const std::string RayTracingTest4_RM = RayTracingTest_Payload +
+R"hlsl(
+[shader("miss")]
+void main(inout RTPayload payload)
+{
+ payload.Color = float4(0.0, 0.0, 0.2, 1.0);
+}
+)hlsl";
+
+const std::string RayTracingTest4_Uniforms = RayTracingTest_Payload +
+R"hlsl(
+struct Vertex
+{
+ float4 Pos;
+ float4 Color1;
+ float4 Color2;
+};
+StructuredBuffer<Vertex> g_Vertices : register(t1); // array size = 16
+StructuredBuffer<uint> g_PerInstance[2] : register(t2); // array size = 3
+StructuredBuffer<uint4> g_Primitives : register(t4); // array size = 9
+
+// local root constants
+struct LocalRootConst
+{
+ float4 Weight;
+};
+//[[vk::shader_record_ext]]
+//ConstantBuffer<LocalRootConst> g_LocalRoot : register(b0);
+)hlsl";
+
+const std::string RayTracingTest4_RCH1 = RayTracingTest4_Uniforms +
+R"hlsl(
+[shader("closesthit")]
+void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr)
+{
+ float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);// * g_LocalRoot.Weight.xyz;
+ uint primOffset = g_PerInstance[InstanceIndex()][GeometryIndex()];
+ uint4 triFace = g_Primitives[primOffset + PrimitiveIndex()];
+ Vertex v0 = g_Vertices[triFace.x];
+ Vertex v1 = g_Vertices[triFace.y];
+ Vertex v2 = g_Vertices[triFace.z];
+ float4 col = v0.Color2 * barycentrics.x + v1.Color2 * barycentrics.y + v2.Color2 * barycentrics.z;
+ payload.Color = col;
+}
+)hlsl";
+
+const std::string RayTracingTest4_RCH2 = RayTracingTest4_Uniforms +
+R"hlsl(
+[shader("closesthit")]
+void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr)
+{
+ float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);// * g_LocalRoot.Weight.xyz;
+ uint primOffset = g_PerInstance[InstanceIndex()][GeometryIndex()];
+ uint4 triFace = g_Primitives[primOffset + PrimitiveIndex()];
+ Vertex v0 = g_Vertices[triFace.x];
+ Vertex v1 = g_Vertices[triFace.y];
+ Vertex v2 = g_Vertices[triFace.z];
+ float4 col = v0.Color1 * barycentrics.x + v1.Color1 * barycentrics.y + v2.Color1 * barycentrics.z;
+ payload.Color = col;
+}
+)hlsl";
+// clang-format on
+
} // namespace HLSL
} // namespace
diff --git a/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp b/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp
new file mode 100644
index 00000000..99ab4bf0
--- /dev/null
+++ b/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "BasicMath.hpp"
+
+namespace Diligent
+{
+
+namespace TestingConstants
+{
+// clang-format off
+
+ namespace TriangleClosestHit
+ {
+ static const float3 Vertices[] =
+ {
+ float3{0.25f, 0.25f, 0.0f},
+ float3{0.75f, 0.25f, 0.0f},
+ float3{0.50f, 0.75f, 0.0f}
+ };
+ } // namespace TriangleClosestHit
+
+ namespace TriangleAnyHit
+ {
+ static const float3 Vertices[] =
+ {
+ float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f},
+ float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f},
+ float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f}
+ };
+ } // namespace TriangleAnyHit
+
+ namespace ProceduralIntersection
+ {
+ static const float3 Boxes[] =
+ {
+ float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f},
+ float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f}
+ };
+ } // namespace ProceduralIntersection
+
+ namespace MultiGeometry
+ {
+ struct VertexType
+ {
+ float4 Pos;
+ float4 Color1;
+ float4 Color2;
+
+ VertexType(float2 _Pos, float3 _Color1, float3 _Color2) :
+ Pos {_Pos.x, _Pos.y, 2.0f, 1.0f},
+ Color1{_Color1.x, _Color1.y, _Color1.z, 1.0f},
+ Color2{_Color2.x, _Color2.y, _Color2.z, 1.0f}
+ {}
+ };
+
+ static const VertexType Vertices[] =
+ {
+ // geometry 1
+ VertexType{{0.10f, 0.10f}, {0.7f, 0.3f, 0.1f}, {0.2f, 0.9f, 0.4f}}, // 0
+ VertexType{{0.17f, 0.30f}, {0.6f, 0.0f, 0.4f}, {0.2f, 0.5f, 0.8f}}, // 1
+ VertexType{{0.10f, 0.31f}, {0.3f, 0.7f, 0.4f}, {0.9f, 0.2f, 0.6f}}, // 2
+ VertexType{{0.22f, 0.45f}, {0.2f, 0.9f, 0.7f}, {0.1f, 0.7f, 0.1f}}, // 3
+ // geometry 2
+ VertexType{{0.27f, 0.10f}, {0.5f, 0.1f, 0.6f}, {0.3f, 0.1f, 0.5f}}, // 4
+ VertexType{{0.40f, 0.30f}, {1.0f, 1.0f, 1.0f}, {0.3f, 1.0f, 0.7f}}, // 5
+ VertexType{{0.26f, 0.30f}, {0.3f, 0.3f, 0.9f}, {1.0f, 0.0f, 0.3f}}, // 6
+ VertexType{{0.40f, 0.47f}, {0.8f, 1.0f, 0.2f}, {1.0f, 0.7f, 0.0f}}, // 7
+ VertexType{{0.54f, 0.30f}, {0.1f, 1.0f, 0.9f}, {0.0f, 1.0f, 0.6f}}, // 8
+ VertexType{{0.53f, 0.10f}, {1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}}, // 9
+ // geometry 3
+ VertexType{{0.65f, 0.10f}, {0.3f, 0.6f, 0.8f}, {1.0f, 0.9f, 0.2f}}, // 10
+ VertexType{{0.63f, 0.25f}, {0.9f, 1.0f, 0.2f}, {0.1f, 0.2f, 0.3f}}, // 11
+ VertexType{{0.82f, 0.20f}, {0.4f, 0.5f, 0.0f}, {1.0f, 0.2f, 0.6f}}, // 12
+ VertexType{{0.76f, 0.30f}, {1.0f, 0.0f, 0.0f}, {0.4f, 0.7f, 0.2f}}, // 13
+ VertexType{{0.55f, 0.48f}, {0.5f, 0.1f, 0.2f}, {1.0f, 0.3f, 0.5f}}, // 14
+ VertexType{{0.90f, 0.40f}, {0.8f, 0.2f, 1.0f}, {0.3f, 0.6f, 0.4f}}, // 15
+ };
+ static const uint Indices[] =
+ {
+ 0, 1, 2, 2, 1, 3, // geometry 1
+ 4, 5, 6, 6, 7, 8, 8, 5, 9, // geometry 2
+ 10, 12, 11, 11, 12, 13, 11, 13, 14, 13, 12, 15, // geometry 3
+ };
+ static const uint4 Primitives[] =
+ {
+ // geometry 1
+ {Indices[ 0], Indices[ 1], Indices[ 2], 0}, // 0
+ {Indices[ 3], Indices[ 4], Indices[ 5], 0}, // 1
+ // geometry 2
+ {Indices[ 6], Indices[ 7], Indices[ 8], 0}, // 2
+ {Indices[ 9], Indices[10], Indices[11], 0}, // 3
+ {Indices[12], Indices[13], Indices[14], 0}, // 4
+ // geometry 3
+ {Indices[15], Indices[16], Indices[17], 0}, // 5
+ {Indices[18], Indices[19], Indices[20], 0}, // 6
+ {Indices[21], Indices[22], Indices[23], 0}, // 7
+ {Indices[24], Indices[25], Indices[26], 0} // 8
+ };
+ static const uint PrimitiveOffsets[] =
+ {
+ 0, 2, 5
+ };
+
+ struct ShaderRecord
+ {
+ float4 Weight;
+ float4 Padding;
+ };
+ static const ShaderRecord Weights[] =
+ {
+ ShaderRecord{{1.0f, 0.4f, 0.4f, 1.0f}, {}},
+ ShaderRecord{{0.4f, 1.0f, 0.4f, 1.0f}, {}},
+ ShaderRecord{{0.4f, 0.4f, 1.0f, 1.0f}, {}}
+ };
+ static constexpr Uint32 ShaderRecordSize = sizeof(Weights[0]);
+ static constexpr Uint32 InstanceCount = 2;
+
+ static_assert(_countof(Vertices) == 16, "Update array size in shaders");
+ static_assert(_countof(PrimitiveOffsets) == 3, "Update array size in shaders");
+ static_assert(_countof(Primitives) == 9, "Update array size in shaders");
+ static_assert(_countof(Indices) % 3 == 0, "Invalid index count");
+ static_assert(_countof(Indices) / 3 == _countof(Primitives), "Primitive count mismatch");
+
+ } // namespace MultiGeometry
+
+// clang-format on
+
+} // namespace TestingConstants
+
+} // namespace Diligent
diff --git a/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp b/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp
index 79eb6e96..cd709797 100644
--- a/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp
+++ b/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp
@@ -34,6 +34,7 @@
#include "BasicMath.hpp"
#include "InlineShaders/RayTracingTestHLSL.h"
+#include "RayTracingTestConstants.hpp"
namespace Diligent
{
@@ -46,17 +47,21 @@ namespace
struct RTContext
{
- ID3D12Device5* pDevice = nullptr;
+ struct AccelStruct
+ {
+ CComPtr<ID3D12Resource> pAS;
+ UINT64 BuildScratchSize = 0;
+ UINT64 UpdateScratchSize = 0;
+ };
+
+ CComPtr<ID3D12Device5> pDevice;
CComPtr<ID3D12GraphicsCommandList4> pCmdList;
CComPtr<ID3D12StateObject> pRayTracingSO;
CComPtr<ID3D12StateObjectProperties> pStateObjectProperties;
- CComPtr<ID3D12RootSignature> pRootSignature;
- CComPtr<ID3D12Resource> pBLAS;
- UINT64 BLASBuildScratchSize = 0;
- UINT64 BLASUpdateScratchSize = 0;
- CComPtr<ID3D12Resource> pTLAS;
- UINT64 TLASBuildScratchSize = 0;
- UINT64 TLASUpdateScratchSize = 0;
+ CComPtr<ID3D12RootSignature> pGlobalRootSignature;
+ CComPtr<ID3D12RootSignature> pLocalRootSignature;
+ AccelStruct BLAS;
+ AccelStruct TLAS;
CComPtr<ID3D12Resource> pScratchBuffer;
CComPtr<ID3D12Resource> pVertexBuffer;
CComPtr<ID3D12Resource> pIndexBuffer;
@@ -96,8 +101,8 @@ struct RTContext
static constexpr UINT DescriptorHeapSize = 16;
};
-template <typename PSOCtorType>
-void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& PSOCtor)
+template <typename PSOCtorType, typename RootSigCtorType>
+void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, Uint32 ShaderRecordSize, PSOCtorType&& PSOCtor, RootSigCtorType&& RootSigCtor)
{
auto* pEnv = TestingEnvironmentD3D12::GetInstance();
auto* pTestingSwapChainD3D12 = ValidatedCast<TestingSwapChainD3D12>(pSwapChain);
@@ -110,38 +115,90 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P
hr = pEnv->CreateGraphicsCommandList()->QueryInterface(IID_PPV_ARGS(&Ctx.pCmdList));
ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to get ID3D12GraphicsCommandList4";
- // create root signature
+ // create descriptor heap
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC Desc = {};
+
+ Desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ Desc.NumDescriptors = Ctx.DescriptorHeapSize;
+ Desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ Desc.NodeMask = 0;
+
+ hr = Ctx.pDevice->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Ctx.pDescHeap));
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create descriptor heap";
+
+ Ctx.DescHeapCount = 0;
+ Ctx.DescHandleSize = Ctx.pDevice->GetDescriptorHandleIncrementSize(Desc.Type);
+
+ D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};
+
+ UAVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
+
+ D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
+ ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
+ ASSERT_TRUE(Ctx.DescHeapCount == 0);
+ UAVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
+ Ctx.pDevice->CreateUnorderedAccessView(pTestingSwapChainD3D12->GetD3D12RenderTarget(), nullptr, &UAVDesc, UAVHandle);
+ }
+
+ // create global root signature
{
- D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {};
- D3D12_DESCRIPTOR_RANGE DescriptorRanges[2] = {};
- D3D12_ROOT_PARAMETER Params[1] = {};
-
- DescriptorRanges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
- DescriptorRanges[0].NumDescriptors = 1;
- DescriptorRanges[0].BaseShaderRegister = 0;
- DescriptorRanges[0].RegisterSpace = 0;
- DescriptorRanges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- DescriptorRanges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- DescriptorRanges[1].NumDescriptors = 1;
- DescriptorRanges[1].BaseShaderRegister = 0;
- DescriptorRanges[1].RegisterSpace = 0;
- DescriptorRanges[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- Params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- Params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- Params[0].DescriptorTable.NumDescriptorRanges = _countof(DescriptorRanges);
- Params[0].DescriptorTable.pDescriptorRanges = DescriptorRanges;
+ D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {};
+ D3D12_ROOT_PARAMETER Param = {};
+ D3D12_DESCRIPTOR_RANGE Range = {};
+ std::vector<D3D12_DESCRIPTOR_RANGE> DescriptorRanges;
+
+ RootSigCtor(DescriptorRanges);
+
+ Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ Range.NumDescriptors = 1;
+ Range.OffsetInDescriptorsFromTableStart = 0;
+ DescriptorRanges.push_back(Range); // g_TLAS
+
+ Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ Range.NumDescriptors = 1;
+ Range.OffsetInDescriptorsFromTableStart = 1;
+ DescriptorRanges.push_back(Range); // g_ColorBuffer
+
+ Param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ Param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ Param.DescriptorTable.NumDescriptorRanges = static_cast<Uint32>(DescriptorRanges.size());
+ Param.DescriptorTable.pDescriptorRanges = DescriptorRanges.data();
RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
- RootSignatureDesc.NumParameters = _countof(Params);
- RootSignatureDesc.pParameters = Params;
+ RootSignatureDesc.NumParameters = 1;
+ RootSignatureDesc.pParameters = &Param;
+
+ CComPtr<ID3DBlob> signature;
+ hr = D3D12SerializeRootSignature(&RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr);
+ ASSERT_HRESULT_SUCCEEDED(hr);
+
+ hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pGlobalRootSignature));
+ ASSERT_HRESULT_SUCCEEDED(hr);
+ }
+
+ // create local root signature
+ if (ShaderRecordSize > 0)
+ {
+ D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {};
+ D3D12_ROOT_PARAMETER Param = {};
+
+ Param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ Param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ Param.Constants.Num32BitValues = ShaderRecordSize / 4;
+ Param.Constants.RegisterSpace = 1;
+ Param.Constants.ShaderRegister = 0;
+
+ RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
+ RootSignatureDesc.NumParameters = 1;
+ RootSignatureDesc.pParameters = &Param;
CComPtr<ID3DBlob> signature;
hr = D3D12SerializeRootSignature(&RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr);
ASSERT_HRESULT_SUCCEEDED(hr);
- hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pRootSignature));
+ hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pLocalRootSignature));
ASSERT_HRESULT_SUCCEEDED(hr);
}
@@ -165,9 +222,14 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P
Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &ShaderConfig});
D3D12_GLOBAL_ROOT_SIGNATURE GlobalRoot;
- GlobalRoot.pGlobalRootSignature = Ctx.pRootSignature;
+ GlobalRoot.pGlobalRootSignature = Ctx.pGlobalRootSignature;
Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &GlobalRoot});
+ D3D12_LOCAL_ROOT_SIGNATURE LocalRoot;
+ LocalRoot.pLocalRootSignature = Ctx.pLocalRootSignature;
+ if (Ctx.pLocalRootSignature)
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &LocalRoot});
+
D3D12_STATE_OBJECT_DESC RTPipelineDesc;
RTPipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
RTPipelineDesc.NumSubobjects = static_cast<UINT>(Subobjects.size());
@@ -179,32 +241,12 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P
hr = Ctx.pRayTracingSO->QueryInterface(IID_PPV_ARGS(&Ctx.pStateObjectProperties));
ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to get state object properties";
}
+}
- // create descriptor heap
- {
- D3D12_DESCRIPTOR_HEAP_DESC Desc = {};
-
- Desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
- Desc.NumDescriptors = Ctx.DescriptorHeapSize;
- Desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
- Desc.NodeMask = 0;
-
- hr = Ctx.pDevice->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Ctx.pDescHeap));
- ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create descriptor heap";
-
- Ctx.DescHeapCount = 0;
- Ctx.DescHandleSize = Ctx.pDevice->GetDescriptorHandleIncrementSize(Desc.Type);
-
- D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};
-
- UAVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
-
- D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
- ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
- UAVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
- Ctx.pDevice->CreateUnorderedAccessView(pTestingSwapChainD3D12->GetD3D12RenderTarget(), nullptr, &UAVDesc, UAVHandle);
- }
+template <typename PSOCtorType>
+void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, Uint32 ShaderRecordSize, PSOCtorType&& PSOCtor)
+{
+ InitializeRTContext(Ctx, pSwapChain, ShaderRecordSize, PSOCtor, [](std::vector<D3D12_DESCRIPTOR_RANGE>&) {});
}
void CreateBLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& BottomLevelInputs)
@@ -240,11 +282,11 @@ void CreateBLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_IN
auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
&ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr,
- IID_PPV_ARGS(&Ctx.pBLAS));
+ IID_PPV_ARGS(&Ctx.BLAS.pAS));
ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create acceleration structure";
- Ctx.BLASBuildScratchSize = BottomLevelPrebuildInfo.ScratchDataSizeInBytes;
- Ctx.BLASUpdateScratchSize = BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes;
+ Ctx.BLAS.BuildScratchSize = BottomLevelPrebuildInfo.ScratchDataSizeInBytes;
+ Ctx.BLAS.UpdateScratchSize = BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes;
}
void CreateTLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs)
@@ -280,26 +322,27 @@ void CreateTLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_IN
auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
&ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr,
- IID_PPV_ARGS(&Ctx.pTLAS));
+ IID_PPV_ARGS(&Ctx.TLAS.pAS));
ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create acceleration structure";
- Ctx.TLASBuildScratchSize = TopLevelPrebuildInfo.ScratchDataSizeInBytes;
- Ctx.TLASUpdateScratchSize = TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes;
+ Ctx.TLAS.BuildScratchSize = TopLevelPrebuildInfo.ScratchDataSizeInBytes;
+ Ctx.TLAS.UpdateScratchSize = TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes;
D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};
SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE;
SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
SRVDesc.Format = DXGI_FORMAT_UNKNOWN;
- SRVDesc.RaytracingAccelerationStructure.Location = Ctx.pTLAS->GetGPUVirtualAddress();
+ SRVDesc.RaytracingAccelerationStructure.Location = Ctx.TLAS.pAS->GetGPUVirtualAddress();
D3D12_CPU_DESCRIPTOR_HANDLE DescHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
+ ASSERT_TRUE(Ctx.DescHeapCount == 1);
DescHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
Ctx.pDevice->CreateShaderResourceView(nullptr, &SRVDesc, DescHandle);
}
-void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders)
+void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, Uint32 ShaderRecordSize = 0, size_t UploadSize = 0)
{
D3D12_RESOURCE_DESC BuffDesc = {};
BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
@@ -320,17 +363,15 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
HeapProps.CreationNodeMask = 1;
HeapProps.VisibleNodeMask = 1;
- BuffDesc.Width = std::max(Ctx.BLASBuildScratchSize, Ctx.BLASUpdateScratchSize);
- BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLASBuildScratchSize);
- BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLASUpdateScratchSize);
+ BuffDesc.Width = std::max(Ctx.BLAS.BuildScratchSize, Ctx.BLAS.UpdateScratchSize);
+ BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLAS.BuildScratchSize);
+ BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLAS.UpdateScratchSize);
auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
&BuffDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr,
IID_PPV_ARGS(&Ctx.pScratchBuffer));
ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create buffer";
- size_t UploadSize = 0;
-
if (VBSize > 0)
{
BuffDesc.Width = VBSize;
@@ -366,12 +407,12 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
// SBT
{
- const UINT64 handleSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
+ const UINT64 RecordSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES + ShaderRecordSize;
const UINT64 align = D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT;
- BuffDesc.Width = Align(handleSize, align);
- BuffDesc.Width = Align(BuffDesc.Width + NumMissShaders * handleSize, align);
- BuffDesc.Width = Align(BuffDesc.Width + NumHitShaders * handleSize, align);
+ BuffDesc.Width = Align(RecordSize, align);
+ BuffDesc.Width = Align(BuffDesc.Width + NumMissShaders * RecordSize, align);
+ BuffDesc.Width = Align(BuffDesc.Width + NumHitShaders * RecordSize, align);
hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
&BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
@@ -420,7 +461,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
const auto& SCDesc = pSwapChain->GetDesc();
RTContext Ctx = {};
- InitializeRTContext(Ctx, pSwapChain,
+ InitializeRTContext(Ctx, pSwapChain, 0,
[pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) {
ShadersByteCode.resize(3);
ExportDescs.resize(ShadersByteCode.size());
@@ -487,12 +528,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs;
D3D12_RAYTRACING_INSTANCE_DESC Instance = {};
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f},
- float3{0.75f, 0.25f, 0.0f},
- float3{0.50f, 0.75f, 0.0f} //
- };
+ const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
@@ -518,7 +554,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
Instance.InstanceContributionToHitGroupIndex = 0;
Instance.InstanceMask = 0xFF;
Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
- Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress();
+ Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress();
Instance.Transform[0][0] = 1.0f;
Instance.Transform[1][1] = 1.0f;
Instance.Transform[2][2] = 1.0f;
@@ -557,7 +593,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
Geometry.Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
- BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress();
+ BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress();
BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
BLASDesc.SourceAccelerationStructureData = 0;
@@ -579,7 +615,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress();
- TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress();
+ TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress();
TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
TLASDesc.SourceAccelerationStructureData = 0;
@@ -598,7 +634,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain)
ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap};
Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO);
- Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature);
+ Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature);
Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]);
Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart());
@@ -657,7 +693,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
const auto& SCDesc = pSwapChain->GetDesc();
RTContext Ctx = {};
- InitializeRTContext(Ctx, pSwapChain,
+ InitializeRTContext(Ctx, pSwapChain, 0,
[pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) {
ShadersByteCode.resize(4);
ExportDescs.resize(ShadersByteCode.size());
@@ -738,12 +774,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs;
D3D12_RAYTRACING_INSTANCE_DESC Instance = {};
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f},
- float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f},
- float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} //
- };
+ const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices;
Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE;
@@ -769,7 +800,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
Instance.InstanceContributionToHitGroupIndex = 0;
Instance.InstanceMask = 0xFF;
Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
- Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress();
+ Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress();
Instance.Transform[0][0] = 1.0f;
Instance.Transform[1][1] = 1.0f;
Instance.Transform[2][2] = 1.0f;
@@ -808,7 +839,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
Geometry.Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
- BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress();
+ BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress();
BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
BLASDesc.SourceAccelerationStructureData = 0;
@@ -830,7 +861,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress();
- TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress();
+ TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress();
TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
TLASDesc.SourceAccelerationStructureData = 0;
@@ -849,7 +880,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain)
ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap};
Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO);
- Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature);
+ Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature);
Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]);
Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart());
@@ -908,7 +939,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
const auto& SCDesc = pSwapChain->GetDesc();
RTContext Ctx = {};
- InitializeRTContext(Ctx, pSwapChain,
+ InitializeRTContext(Ctx, pSwapChain, 0,
[pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) {
ShadersByteCode.resize(4);
ExportDescs.resize(ShadersByteCode.size());
@@ -989,11 +1020,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs;
D3D12_RAYTRACING_INSTANCE_DESC Instance = {};
- const float3 Boxes[] = //
- {
- float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f},
- float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f} //
- };
+ const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes;
Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS;
Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
@@ -1014,7 +1041,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
Instance.InstanceContributionToHitGroupIndex = 0;
Instance.InstanceMask = 0xFF;
Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
- Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress();
+ Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress();
Instance.Transform[0][0] = 1.0f;
Instance.Transform[1][1] = 1.0f;
Instance.Transform[2][2] = 1.0f;
@@ -1053,7 +1080,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
Geometry.AABBs.AABBs.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
- BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress();
+ BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress();
BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
BLASDesc.SourceAccelerationStructureData = 0;
@@ -1075,7 +1102,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress();
- TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress();
+ TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress();
TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
TLASDesc.SourceAccelerationStructureData = 0;
@@ -1094,7 +1121,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap};
Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO);
- Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature);
+ Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature);
Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]);
Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart());
@@ -1144,6 +1171,440 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain)
pEnv->ExecuteCommandList(Ctx.pCmdList, true);
}
+
+void RayTracingMultiGeometryReferenceD3D12(ISwapChain* pSwapChain)
+{
+ static constexpr Uint32 InstanceCount = TestingConstants::MultiGeometry::InstanceCount;
+ static constexpr Uint32 GeometryCount = 3;
+ static constexpr Uint32 HitGroupCount = InstanceCount * GeometryCount;
+
+ auto* pEnv = TestingEnvironmentD3D12::GetInstance();
+ auto* pTestingSwapChainD3D12 = ValidatedCast<TestingSwapChainD3D12>(pSwapChain);
+
+ const auto& SCDesc = pSwapChain->GetDesc();
+
+ RTContext Ctx = {};
+ InitializeRTContext(
+ Ctx, pSwapChain,
+ TestingConstants::MultiGeometry::ShaderRecordSize,
+ [pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) {
+ ShadersByteCode.resize(4);
+ ExportDescs.resize(ShadersByteCode.size());
+ LibDescs.resize(ShadersByteCode.size());
+ HitGroups.resize(2);
+
+ auto hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RG, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[0]);
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray gen shader";
+
+ hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RM, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[1]);
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray miss shader";
+
+ hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RCH1, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[2]);
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray closest hit shader";
+
+ hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RCH2, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[3]);
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray closest hit shader";
+
+ D3D12_EXPORT_DESC& RGExportDesc = ExportDescs[0];
+ D3D12_DXIL_LIBRARY_DESC& RGLibDesc = LibDescs[0];
+ RGExportDesc.Flags = D3D12_EXPORT_FLAG_NONE;
+ RGExportDesc.ExportToRename = L"main"; // shader entry name
+ RGExportDesc.Name = L"Main";
+ RGLibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[0]->GetBufferSize();
+ RGLibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[0]->GetBufferPointer();
+ RGLibDesc.NumExports = 1;
+ RGLibDesc.pExports = &RGExportDesc;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RGLibDesc});
+
+ D3D12_EXPORT_DESC& RMExportDesc = ExportDescs[1];
+ D3D12_DXIL_LIBRARY_DESC& RMLibDesc = LibDescs[1];
+ RMExportDesc.Flags = D3D12_EXPORT_FLAG_NONE;
+ RMExportDesc.ExportToRename = L"main"; // shader entry name
+ RMExportDesc.Name = L"Miss";
+ RMLibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[1]->GetBufferSize();
+ RMLibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[1]->GetBufferPointer();
+ RMLibDesc.NumExports = 1;
+ RMLibDesc.pExports = &RMExportDesc;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RMLibDesc});
+
+ D3D12_EXPORT_DESC& RCH1ExportDesc = ExportDescs[2];
+ D3D12_DXIL_LIBRARY_DESC& RCH1LibDesc = LibDescs[2];
+ RCH1ExportDesc.Flags = D3D12_EXPORT_FLAG_NONE;
+ RCH1ExportDesc.ExportToRename = L"main"; // shader entry name
+ RCH1ExportDesc.Name = L"ClosestHitShader1";
+ RCH1LibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[2]->GetBufferSize();
+ RCH1LibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[2]->GetBufferPointer();
+ RCH1LibDesc.NumExports = 1;
+ RCH1LibDesc.pExports = &RCH1ExportDesc;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RCH1LibDesc});
+
+ D3D12_EXPORT_DESC& RCH2ExportDesc = ExportDescs[3];
+ D3D12_DXIL_LIBRARY_DESC& RCH2LibDesc = LibDescs[3];
+ RCH2ExportDesc.Flags = D3D12_EXPORT_FLAG_NONE;
+ RCH2ExportDesc.ExportToRename = L"main"; // shader entry name
+ RCH2ExportDesc.Name = L"ClosestHitShader2";
+ RCH2LibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[3]->GetBufferSize();
+ RCH2LibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[3]->GetBufferPointer();
+ RCH2LibDesc.NumExports = 1;
+ RCH2LibDesc.pExports = &RCH2ExportDesc;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RCH2LibDesc});
+
+ D3D12_HIT_GROUP_DESC& HitGroup1Desc = HitGroups[0];
+ HitGroup1Desc.HitGroupExport = L"HitGroup1";
+ HitGroup1Desc.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
+ HitGroup1Desc.ClosestHitShaderImport = L"ClosestHitShader1";
+ HitGroup1Desc.AnyHitShaderImport = nullptr;
+ HitGroup1Desc.IntersectionShaderImport = nullptr;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroup1Desc});
+
+ D3D12_HIT_GROUP_DESC& HitGroup2Desc = HitGroups[1];
+ HitGroup2Desc.HitGroupExport = L"HitGroup2";
+ HitGroup2Desc.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
+ HitGroup2Desc.ClosestHitShaderImport = L"ClosestHitShader2";
+ HitGroup2Desc.AnyHitShaderImport = nullptr;
+ HitGroup2Desc.IntersectionShaderImport = nullptr;
+ Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroup2Desc});
+ },
+ [](std::vector<D3D12_DESCRIPTOR_RANGE>& DescriptorRanges) {
+ D3D12_DESCRIPTOR_RANGE Range = {};
+ Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ Range.NumDescriptors = 1;
+
+ Range.BaseShaderRegister = 1;
+ Range.OffsetInDescriptorsFromTableStart = 2;
+ DescriptorRanges.push_back(Range); // g_Vertices
+
+ Range.BaseShaderRegister = 4;
+ Range.OffsetInDescriptorsFromTableStart = 3;
+ DescriptorRanges.push_back(Range); // g_Primitives
+
+ Range.BaseShaderRegister = 2;
+ Range.NumDescriptors = 2;
+ Range.OffsetInDescriptorsFromTableStart = 4;
+ DescriptorRanges.push_back(Range); // g_PerInstance[2]
+ });
+
+ const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets;
+ const auto& Primitives = TestingConstants::MultiGeometry::Primitives;
+ const auto& Vertices = TestingConstants::MultiGeometry::Vertices;
+
+ // create acceleration structurea
+ {
+ const auto& Indices = TestingConstants::MultiGeometry::Indices;
+
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC BLASDesc = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& BottomLevelInputs = BLASDesc.Inputs;
+ D3D12_RAYTRACING_GEOMETRY_DESC Geometries[3] = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC TLASDesc = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs;
+ D3D12_RAYTRACING_INSTANCE_DESC Instances[2] = {};
+
+ static_assert(GeometryCount == _countof(Geometries), "size mismatch");
+ static_assert(InstanceCount == _countof(Instances), "size mismatch");
+
+ Geometries[0].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
+ Geometries[0].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
+ Geometries[0].Triangles.VertexBuffer.StartAddress = 0;
+ Geometries[0].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]);
+ Geometries[0].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
+ Geometries[0].Triangles.VertexCount = _countof(Vertices);
+ Geometries[0].Triangles.IndexCount = PrimitiveOffsets[1] * 3;
+ Geometries[0].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT;
+ Geometries[0].Triangles.IndexBuffer = 0;
+ Geometries[0].Triangles.Transform3x4 = 0;
+
+ Geometries[1].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
+ Geometries[1].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
+ Geometries[1].Triangles.VertexBuffer.StartAddress = 0;
+ Geometries[1].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]);
+ Geometries[1].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
+ Geometries[1].Triangles.VertexCount = _countof(Vertices);
+ Geometries[1].Triangles.IndexCount = (PrimitiveOffsets[2] - PrimitiveOffsets[1]) * 3;
+ Geometries[1].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT;
+ Geometries[1].Triangles.IndexBuffer = 0;
+ Geometries[1].Triangles.Transform3x4 = 0;
+
+ Geometries[2].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
+ Geometries[2].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
+ Geometries[2].Triangles.VertexBuffer.StartAddress = 0;
+ Geometries[2].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]);
+ Geometries[2].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
+ Geometries[2].Triangles.VertexCount = _countof(Vertices);
+ Geometries[2].Triangles.IndexCount = (_countof(Primitives) - PrimitiveOffsets[2]) * 3;
+ Geometries[2].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT;
+ Geometries[2].Triangles.IndexBuffer = 0;
+ Geometries[2].Triangles.Transform3x4 = 0;
+
+ BottomLevelInputs.pGeometryDescs = Geometries;
+ BottomLevelInputs.NumDescs = _countof(Geometries);
+
+ TopLevelInputs.NumDescs = _countof(Instances);
+
+ CreateBLAS(Ctx, BottomLevelInputs);
+ CreateTLAS(Ctx, TopLevelInputs);
+ CreateRTBuffers(Ctx, sizeof(Vertices), sizeof(Indices), InstanceCount, 1, HitGroupCount,
+ TestingConstants::MultiGeometry::ShaderRecordSize,
+ sizeof(PrimitiveOffsets) + sizeof(Primitives));
+
+ Instances[0].InstanceID = 0;
+ Instances[0].InstanceContributionToHitGroupIndex = 0;
+ Instances[0].InstanceMask = 0xFF;
+ Instances[0].Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
+ Instances[0].AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress();
+ Instances[0].Transform[0][0] = 1.0f;
+ Instances[0].Transform[1][1] = 1.0f;
+ Instances[0].Transform[2][2] = 1.0f;
+
+ Instances[1].InstanceID = 0;
+ Instances[1].InstanceContributionToHitGroupIndex = HitGroupCount / 2;
+ Instances[1].InstanceMask = 0xFF;
+ Instances[1].Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
+ Instances[1].AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress();
+ Instances[1].Transform[0][0] = 1.0f;
+ Instances[1].Transform[1][1] = 1.0f;
+ Instances[1].Transform[2][2] = 1.0f;
+ Instances[1].Transform[0][3] = 0.1f;
+ Instances[1].Transform[1][3] = 0.5f;
+ Instances[1].Transform[2][3] = 0.0f;
+
+ UpdateBuffer(Ctx, Ctx.pVertexBuffer, 0, Vertices, sizeof(Vertices));
+ UpdateBuffer(Ctx, Ctx.pIndexBuffer, 0, Indices, sizeof(Indices));
+ UpdateBuffer(Ctx, Ctx.pInstanceBuffer, 0, Instances, sizeof(Instances));
+
+ // vertex & instance buffer barrier
+ {
+ std::vector<D3D12_RESOURCE_BARRIER> Barriers;
+ D3D12_RESOURCE_BARRIER Barrier;
+
+ Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+
+ if (Ctx.pVertexBuffer)
+ {
+ Barrier.Transition.pResource = Ctx.pVertexBuffer;
+ Barriers.push_back(Barrier);
+ }
+ if (Ctx.pIndexBuffer)
+ {
+ Barrier.Transition.pResource = Ctx.pIndexBuffer;
+ Barriers.push_back(Barrier);
+ }
+ if (Ctx.pInstanceBuffer)
+ {
+ Barrier.Transition.pResource = Ctx.pInstanceBuffer;
+ Barriers.push_back(Barrier);
+ }
+ Ctx.pCmdList->ResourceBarrier(static_cast<UINT>(Barriers.size()), Barriers.data());
+ }
+
+ Geometries[0].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
+ Geometries[1].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
+ Geometries[2].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress();
+
+ Geometries[0].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[0] * sizeof(uint) * 3;
+ Geometries[1].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[1] * sizeof(uint) * 3;
+ Geometries[2].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[2] * sizeof(uint) * 3;
+
+ BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress();
+ BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
+ BLASDesc.SourceAccelerationStructureData = 0;
+
+ ASSERT_TRUE(BLASDesc.DestAccelerationStructureData != 0);
+ ASSERT_TRUE(BLASDesc.ScratchAccelerationStructureData != 0);
+
+ Ctx.pCmdList->BuildRaytracingAccelerationStructure(&BLASDesc, 0, nullptr);
+
+ // UAV barrier for scratch buffer
+ {
+ D3D12_RESOURCE_BARRIER Barrier;
+ Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+ Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ Barrier.UAV.pResource = Ctx.pScratchBuffer;
+
+ Ctx.pCmdList->ResourceBarrier(1, &Barrier);
+ }
+
+ TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress();
+
+ TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress();
+ TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress();
+ TLASDesc.SourceAccelerationStructureData = 0;
+
+ ASSERT_TRUE(TLASDesc.DestAccelerationStructureData != 0);
+ ASSERT_TRUE(TLASDesc.ScratchAccelerationStructureData != 0);
+
+ Ctx.pCmdList->BuildRaytracingAccelerationStructure(&TLASDesc, 0, nullptr);
+ }
+
+ // update descriptors
+ CComPtr<ID3D12Resource> pPerInstanceBuffer;
+ CComPtr<ID3D12Resource> pPrimitiveBuffer;
+ {
+ D3D12_RESOURCE_DESC BuffDesc = {};
+ BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ BuffDesc.Alignment = 0;
+ BuffDesc.Width = sizeof(PrimitiveOffsets);
+ BuffDesc.Height = 1;
+ BuffDesc.DepthOrArraySize = 1;
+ BuffDesc.MipLevels = 1;
+ BuffDesc.Format = DXGI_FORMAT_UNKNOWN;
+ BuffDesc.SampleDesc.Count = 1;
+ BuffDesc.SampleDesc.Quality = 0;
+ BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ D3D12_HEAP_PROPERTIES HeapProps;
+ HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ HeapProps.CreationNodeMask = 1;
+ HeapProps.VisibleNodeMask = 1;
+
+ auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
+ &BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
+ IID_PPV_ARGS(&pPerInstanceBuffer));
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create per instance buffer";
+
+ BuffDesc.Width = sizeof(Primitives);
+
+ hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
+ &BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
+ IID_PPV_ARGS(&pPrimitiveBuffer));
+ ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create per instance buffer";
+
+ UpdateBuffer(Ctx, pPrimitiveBuffer, 0, Primitives, sizeof(Primitives));
+ UpdateBuffer(Ctx, pPerInstanceBuffer, 0, PrimitiveOffsets, sizeof(PrimitiveOffsets));
+
+ // buffer barrier
+ {
+ D3D12_RESOURCE_BARRIER Barrier = {};
+ Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ Barrier.Transition.pResource = pPerInstanceBuffer;
+ Ctx.pCmdList->ResourceBarrier(1, &Barrier);
+
+ Barrier.Transition.pResource = pPrimitiveBuffer;
+ Ctx.pCmdList->ResourceBarrier(1, &Barrier);
+ }
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};
+ D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle;
+
+ SRVDesc.Format = DXGI_FORMAT_UNKNOWN;
+ SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
+ SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ SRVDesc.Buffer.NumElements = _countof(Vertices);
+ SRVDesc.Buffer.StructureByteStride = sizeof(Vertices[0]);
+
+ ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
+ ASSERT_TRUE(Ctx.DescHeapCount == 2);
+ SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
+ SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
+ Ctx.pDevice->CreateShaderResourceView(Ctx.pVertexBuffer, &SRVDesc, SRVHandle); // g_Vertices
+
+ SRVDesc.Buffer.NumElements = _countof(Primitives);
+ SRVDesc.Buffer.StructureByteStride = sizeof(Primitives[0]);
+ ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
+ ASSERT_TRUE(Ctx.DescHeapCount == 3);
+ SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
+ SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
+ Ctx.pDevice->CreateShaderResourceView(pPrimitiveBuffer, &SRVDesc, SRVHandle); // g_Primitives
+
+ SRVDesc.Buffer.NumElements = _countof(PrimitiveOffsets);
+ SRVDesc.Buffer.StructureByteStride = sizeof(PrimitiveOffsets[0]);
+ ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize);
+ ASSERT_TRUE(Ctx.DescHeapCount == 4);
+ SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
+ SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
+ Ctx.pDevice->CreateShaderResourceView(pPerInstanceBuffer, &SRVDesc, SRVHandle); // g_PerInstance[0]
+
+ ASSERT_TRUE(Ctx.DescHeapCount == 5);
+ SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart();
+ SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++;
+ Ctx.pDevice->CreateShaderResourceView(pPerInstanceBuffer, &SRVDesc, SRVHandle); // g_PerInstance[1]
+ }
+
+ Ctx.ClearRenderTarget(pTestingSwapChainD3D12);
+
+ // trace rays
+ {
+ pTestingSwapChainD3D12->TransitionRenderTarget(Ctx.pCmdList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+
+ ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap};
+
+ Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO);
+ Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature);
+
+ Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]);
+ Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart());
+
+ D3D12_DISPATCH_RAYS_DESC Desc = {};
+
+ Desc.Width = SCDesc.Width;
+ Desc.Height = SCDesc.Height;
+ Desc.Depth = 1;
+
+ const UINT64 handleSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
+ const UINT64 align = D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT;
+ const UINT64 ShaderRecordSize = handleSize + TestingConstants::MultiGeometry::ShaderRecordSize;
+ const size_t RayGenOffset = 0;
+ const size_t RayMissOffset = Align(RayGenOffset + handleSize, align);
+ const size_t HitGroupOffset = Align(RayMissOffset + handleSize, align);
+ const auto& Weights = TestingConstants::MultiGeometry::Weights;
+
+ Desc.RayGenerationShaderRecord.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + RayGenOffset;
+ Desc.RayGenerationShaderRecord.SizeInBytes = ShaderRecordSize;
+ Desc.MissShaderTable.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + RayMissOffset;
+ Desc.MissShaderTable.SizeInBytes = ShaderRecordSize;
+ Desc.MissShaderTable.StrideInBytes = ShaderRecordSize;
+ Desc.HitGroupTable.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + HitGroupOffset;
+ Desc.HitGroupTable.SizeInBytes = ShaderRecordSize * HitGroupCount;
+ Desc.HitGroupTable.StrideInBytes = ShaderRecordSize;
+
+ UpdateBuffer(Ctx, Ctx.pSBTBuffer, RayGenOffset, Ctx.pStateObjectProperties->GetShaderIdentifier(L"Main"), handleSize);
+ UpdateBuffer(Ctx, Ctx.pSBTBuffer, RayMissOffset, Ctx.pStateObjectProperties->GetShaderIdentifier(L"Miss"), handleSize);
+
+ const auto SetHitGroup = [&](Uint32 Index, const wchar_t* GroupName, const void* ShaderRecord) {
+ VERIFY_EXPR(Index < HitGroupCount);
+ UINT64 Offset = HitGroupOffset + Index * ShaderRecordSize;
+ UpdateBuffer(Ctx, Ctx.pSBTBuffer, Offset, Ctx.pStateObjectProperties->GetShaderIdentifier(GroupName), handleSize);
+ UpdateBuffer(Ctx, Ctx.pSBTBuffer, Offset + handleSize, ShaderRecord, sizeof(Weights[0]));
+ };
+ // instance 1
+ SetHitGroup(0, L"HitGroup1", &Weights[2]); // geometry 1
+ SetHitGroup(1, L"HitGroup1", &Weights[0]); // geometry 2
+ SetHitGroup(2, L"HitGroup1", &Weights[1]); // geometry 3
+ // instance 2
+ SetHitGroup(3, L"HitGroup2", &Weights[2]); // geometry 1
+ SetHitGroup(4, L"HitGroup2", &Weights[1]); // geometry 2
+ SetHitGroup(5, L"HitGroup2", &Weights[0]); // geometry 3
+
+ // SBT buffer barrier
+ {
+ D3D12_RESOURCE_BARRIER Barrier;
+ Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ Barrier.Transition.pResource = Ctx.pSBTBuffer;
+ Ctx.pCmdList->ResourceBarrier(1, &Barrier);
+ }
+
+ Ctx.pCmdList->DispatchRays(&Desc);
+ }
+
+ Ctx.pCmdList->Close();
+
+ pEnv->ExecuteCommandList(Ctx.pCmdList, true);
+}
+
} // namespace Testing
} // namespace Diligent
diff --git a/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp b/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp
index bd6b2223..fa71c6a7 100644
--- a/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp
+++ b/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp
@@ -34,6 +34,7 @@
#include "gtest/gtest.h"
#include "InlineShaders/RayTracingTestHLSL.h"
+#include "RayTracingTestConstants.hpp"
namespace Diligent
{
@@ -45,12 +46,14 @@ namespace Testing
void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain);
void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain);
void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain);
+void RayTracingMultiGeometryReferenceD3D12(ISwapChain* pSwapChain);
#endif
#if VULKAN_SUPPORTED
void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain);
void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain);
void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain);
+void RayTracingMultiGeometryReferenceVk(ISwapChain* pSwapChain);
#endif
} // namespace Testing
@@ -83,6 +86,7 @@ void CreateBLAS(IRenderDevice* pDevice, IDeviceContext* pContext, const BLASBuil
BottomLevelASDesc ASDesc;
ASDesc.Name = "Triangle BLAS";
+ ASDesc.Flags = RAYTRACING_BUILD_AS_NONE;
ASDesc.pTriangles = TriangleInfos.data();
ASDesc.TriangleCount = TriangleCount;
@@ -130,6 +134,7 @@ void CreateBLAS(IRenderDevice* pDevice, IDeviceContext* pContext, const BLASBuil
BottomLevelASDesc ASDesc;
ASDesc.Name = "Boxes BLAS";
+ ASDesc.Flags = RAYTRACING_BUILD_AS_NONE;
ASDesc.pBoxes = BoxInfos.data();
ASDesc.BoxCount = BoxCount;
@@ -262,12 +267,12 @@ TEST(RayTracingTest, TriangleClosestHitShader)
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
+ ShaderCI.EntryPoint = "main";
// Create ray generation shader.
RefCntAutoPtr<IShader> pRG;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray tracing RG";
ShaderCI.Source = HLSL::RayTracingTest1_RG.c_str();
pDevice->CreateShader(ShaderCI, &pRG);
@@ -278,7 +283,6 @@ TEST(RayTracingTest, TriangleClosestHitShader)
RefCntAutoPtr<IShader> pRMiss;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Miss shader";
ShaderCI.Source = HLSL::RayTracingTest1_RM.c_str();
pDevice->CreateShader(ShaderCI, &pRMiss);
@@ -289,7 +293,6 @@ TEST(RayTracingTest, TriangleClosestHitShader)
RefCntAutoPtr<IShader> pClosestHit;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray closest hit shader";
ShaderCI.Source = HLSL::RayTracingTest1_RCH.c_str();
pDevice->CreateShader(ShaderCI, &pClosestHit);
@@ -315,12 +318,7 @@ TEST(RayTracingTest, TriangleClosestHitShader)
pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
VERIFY_EXPR(pRayTracingSRB != nullptr);
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f},
- float3{0.75f, 0.25f, 0.0f},
- float3{0.50f, 0.75f, 0.0f} //
- };
+ const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
RefCntAutoPtr<IBuffer> pVertexBuffer;
{
@@ -351,15 +349,9 @@ TEST(RayTracingTest, TriangleClosestHitShader)
CreateBLAS(pDevice, pContext, &Triangle, 1, pBLAS);
TLASBuildInstanceData Instance;
- Instance.InstanceName = "Instance";
- Instance.pBLAS = pBLAS;
- Instance.CustomId = 0;
- Instance.Flags = RAYTRACING_INSTANCE_NONE;
- Instance.Mask = 0xFF;
- Instance.ContributionToHitGroupIndex = 0;
- Instance.Transform[0][0] = 1.0f;
- Instance.Transform[1][1] = 1.0f;
- Instance.Transform[2][2] = 1.0f;
+ Instance.InstanceName = "Instance";
+ Instance.pBLAS = pBLAS;
+ Instance.Flags = RAYTRACING_INSTANCE_NONE;
RefCntAutoPtr<ITopLevelAS> pTLAS;
CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS);
@@ -367,7 +359,6 @@ TEST(RayTracingTest, TriangleClosestHitShader)
ShaderBindingTableDesc SBTDesc;
SBTDesc.Name = "SBT";
SBTDesc.pPSO = pRayTracingPSO;
- SBTDesc.ShaderRecordSize = 0;
SBTDesc.HitShadersPerInstance = 1;
RefCntAutoPtr<IShaderBindingTable> pSBT;
@@ -447,12 +438,12 @@ TEST(RayTracingTest, TriangleAnyHitShader)
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
+ ShaderCI.EntryPoint = "main";
// Create ray generation shader.
RefCntAutoPtr<IShader> pRG;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray tracing RG";
ShaderCI.Source = HLSL::RayTracingTest2_RG.c_str();
pDevice->CreateShader(ShaderCI, &pRG);
@@ -463,7 +454,6 @@ TEST(RayTracingTest, TriangleAnyHitShader)
RefCntAutoPtr<IShader> pRMiss;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Miss shader";
ShaderCI.Source = HLSL::RayTracingTest2_RM.c_str();
pDevice->CreateShader(ShaderCI, &pRMiss);
@@ -474,7 +464,6 @@ TEST(RayTracingTest, TriangleAnyHitShader)
RefCntAutoPtr<IShader> pClosestHit;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray closest hit shader";
ShaderCI.Source = HLSL::RayTracingTest2_RCH.c_str();
pDevice->CreateShader(ShaderCI, &pClosestHit);
@@ -485,7 +474,6 @@ TEST(RayTracingTest, TriangleAnyHitShader)
RefCntAutoPtr<IShader> pAnyHit;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_ANY_HIT;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray any hit shader";
ShaderCI.Source = HLSL::RayTracingTest2_RAH.c_str();
pDevice->CreateShader(ShaderCI, &pAnyHit);
@@ -511,12 +499,7 @@ TEST(RayTracingTest, TriangleAnyHitShader)
pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
VERIFY_EXPR(pRayTracingSRB != nullptr);
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f},
- float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f},
- float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} //
- };
+ const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices;
RefCntAutoPtr<IBuffer> pVertexBuffer;
{
@@ -547,15 +530,9 @@ TEST(RayTracingTest, TriangleAnyHitShader)
CreateBLAS(pDevice, pContext, &Triangle, 1, pBLAS);
TLASBuildInstanceData Instance;
- Instance.InstanceName = "Instance";
- Instance.pBLAS = pBLAS;
- Instance.CustomId = 0;
- Instance.Flags = RAYTRACING_INSTANCE_NONE;
- Instance.Mask = 0xFF;
- Instance.ContributionToHitGroupIndex = 0;
- Instance.Transform[0][0] = 1.0f;
- Instance.Transform[1][1] = 1.0f;
- Instance.Transform[2][2] = 1.0f;
+ Instance.InstanceName = "Instance";
+ Instance.pBLAS = pBLAS;
+ Instance.Flags = RAYTRACING_INSTANCE_NONE;
RefCntAutoPtr<ITopLevelAS> pTLAS;
CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS);
@@ -563,7 +540,6 @@ TEST(RayTracingTest, TriangleAnyHitShader)
ShaderBindingTableDesc SBTDesc;
SBTDesc.Name = "SBT";
SBTDesc.pPSO = pRayTracingPSO;
- SBTDesc.ShaderRecordSize = 0;
SBTDesc.HitShadersPerInstance = 1;
RefCntAutoPtr<IShaderBindingTable> pSBT;
@@ -643,12 +619,12 @@ TEST(RayTracingTest, ProceduralIntersection)
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
+ ShaderCI.EntryPoint = "main";
// Create ray generation shader.
RefCntAutoPtr<IShader> pRG;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray tracing RG";
ShaderCI.Source = HLSL::RayTracingTest3_RG.c_str();
pDevice->CreateShader(ShaderCI, &pRG);
@@ -659,7 +635,6 @@ TEST(RayTracingTest, ProceduralIntersection)
RefCntAutoPtr<IShader> pRMiss;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Miss shader";
ShaderCI.Source = HLSL::RayTracingTest3_RM.c_str();
pDevice->CreateShader(ShaderCI, &pRMiss);
@@ -670,7 +645,6 @@ TEST(RayTracingTest, ProceduralIntersection)
RefCntAutoPtr<IShader> pClosestHit;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray closest hit shader";
ShaderCI.Source = HLSL::RayTracingTest3_RCH.c_str();
pDevice->CreateShader(ShaderCI, &pClosestHit);
@@ -681,7 +655,6 @@ TEST(RayTracingTest, ProceduralIntersection)
RefCntAutoPtr<IShader> pIntersection;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_INTERSECTION;
- ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Ray intersection shader";
ShaderCI.Source = HLSL::RayTracingTest3_RI.c_str();
pDevice->CreateShader(ShaderCI, &pIntersection);
@@ -707,9 +680,7 @@ TEST(RayTracingTest, ProceduralIntersection)
pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
VERIFY_EXPR(pRayTracingSRB != nullptr);
- const float3 Boxes[] = {
- float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f},
- float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f}};
+ const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes;
RefCntAutoPtr<IBuffer> pBoxBuffer;
{
@@ -738,15 +709,9 @@ TEST(RayTracingTest, ProceduralIntersection)
CreateBLAS(pDevice, pContext, &Box, 1, pBLAS);
TLASBuildInstanceData Instance;
- Instance.InstanceName = "Instance";
- Instance.pBLAS = pBLAS;
- Instance.CustomId = 0;
- Instance.Flags = RAYTRACING_INSTANCE_NONE;
- Instance.Mask = 0xFF;
- Instance.ContributionToHitGroupIndex = 0;
- Instance.Transform[0][0] = 1.0f;
- Instance.Transform[1][1] = 1.0f;
- Instance.Transform[2][2] = 1.0f;
+ Instance.InstanceName = "Instance";
+ Instance.pBLAS = pBLAS;
+ Instance.Flags = RAYTRACING_INSTANCE_NONE;
RefCntAutoPtr<ITopLevelAS> pTLAS;
CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS);
@@ -754,7 +719,6 @@ TEST(RayTracingTest, ProceduralIntersection)
ShaderBindingTableDesc SBTDesc;
SBTDesc.Name = "SBT";
SBTDesc.pPSO = pRayTracingPSO;
- SBTDesc.ShaderRecordSize = 0;
SBTDesc.HitShadersPerInstance = 1;
RefCntAutoPtr<IShaderBindingTable> pSBT;
@@ -784,4 +748,261 @@ TEST(RayTracingTest, ProceduralIntersection)
pSwapChain->Present();
}
+
+TEST(RayTracingTest, MultiGeometry)
+{
+ auto* pEnv = TestingEnvironment::GetInstance();
+ auto* pDevice = pEnv->GetDevice();
+ if (!pDevice->GetDeviceCaps().Features.RayTracing)
+ {
+ GTEST_SKIP() << "Ray tracing is not supported by this device";
+ }
+
+ auto* pSwapChain = pEnv->GetSwapChain();
+ auto* pContext = pEnv->GetDeviceContext();
+
+ RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
+ if (pTestingSwapChain)
+ {
+ pContext->Flush();
+ pContext->InvalidateState();
+
+ auto deviceType = pDevice->GetDeviceCaps().DevType;
+ switch (deviceType)
+ {
+#if D3D12_SUPPORTED
+ case RENDER_DEVICE_TYPE_D3D12:
+ RayTracingMultiGeometryReferenceD3D12(pSwapChain);
+ break;
+#endif
+
+#if VULKAN_SUPPORTED
+ case RENDER_DEVICE_TYPE_VULKAN:
+ RayTracingMultiGeometryReferenceVk(pSwapChain);
+ break;
+#endif
+
+ default:
+ LOG_ERROR_AND_THROW("Unsupported device type");
+ }
+
+ pTestingSwapChain->TakeSnapshot();
+ }
+ TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset;
+
+ RayTracingPipelineStateCreateInfo PSOCreateInfo;
+
+ PSOCreateInfo.PSODesc.Name = "Ray tracing PSO";
+ PSOCreateInfo.PSODesc.PipelineType = PIPELINE_TYPE_RAY_TRACING;
+
+ ShaderCreateInfo ShaderCI;
+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+ ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
+ ShaderCI.EntryPoint = "main";
+
+ // Create ray generation shader.
+ RefCntAutoPtr<IShader> pRG;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
+ ShaderCI.Desc.Name = "Ray tracing RG";
+ ShaderCI.Source = HLSL::RayTracingTest4_RG.c_str();
+ pDevice->CreateShader(ShaderCI, &pRG);
+ VERIFY_EXPR(pRG != nullptr);
+ }
+
+ // Create ray miss shader.
+ RefCntAutoPtr<IShader> pRMiss;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS;
+ ShaderCI.Desc.Name = "Miss shader";
+ ShaderCI.Source = HLSL::RayTracingTest4_RM.c_str();
+ pDevice->CreateShader(ShaderCI, &pRMiss);
+ VERIFY_EXPR(pRMiss != nullptr);
+ }
+
+ // Create ray closest hit shader.
+ RefCntAutoPtr<IShader> pClosestHit1;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
+ ShaderCI.Desc.Name = "Ray closest hit shader 1";
+ ShaderCI.Source = HLSL::RayTracingTest4_RCH1.c_str();
+ pDevice->CreateShader(ShaderCI, &pClosestHit1);
+ VERIFY_EXPR(pClosestHit1 != nullptr);
+ }
+
+ RefCntAutoPtr<IShader> pClosestHit2;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
+ ShaderCI.Desc.Name = "Ray closest hit shader 2";
+ ShaderCI.Source = HLSL::RayTracingTest4_RCH2.c_str();
+ pDevice->CreateShader(ShaderCI, &pClosestHit2);
+ VERIFY_EXPR(pClosestHit2 != nullptr);
+ }
+
+ const RayTracingGeneralShaderGroup GeneralShaders[] = {{"Main", pRG}, {"Miss", pRMiss}};
+ const RayTracingTriangleHitShaderGroup TriangleHitShaders[] = {{"HitGroup1", pClosestHit1}, {"HitGroup2", pClosestHit2}};
+
+ PSOCreateInfo.pGeneralShaders = GeneralShaders;
+ PSOCreateInfo.GeneralShaderCount = _countof(GeneralShaders);
+ PSOCreateInfo.pTriangleHitShaders = TriangleHitShaders;
+ PSOCreateInfo.TriangleHitShaderCount = _countof(TriangleHitShaders);
+
+ PSOCreateInfo.RayTracingPipeline.MaxRecursionDepth = 0;
+
+ PSOCreateInfo.RayTracingPipeline.ShaderRecordSize = TestingConstants::MultiGeometry::ShaderRecordSize;
+ PSOCreateInfo.ShaderRecordName = "g_LocalRoot";
+
+ PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
+
+ RefCntAutoPtr<IPipelineState> pRayTracingPSO;
+ pDevice->CreateRayTracingPipelineState(PSOCreateInfo, &pRayTracingPSO);
+ VERIFY_EXPR(pRayTracingPSO != nullptr);
+
+ RefCntAutoPtr<IShaderResourceBinding> pRayTracingSRB;
+ pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
+ VERIFY_EXPR(pRayTracingSRB != nullptr);
+
+ const auto& Vertices = TestingConstants::MultiGeometry::Vertices;
+ const auto& Indices = TestingConstants::MultiGeometry::Indices;
+ const auto& Weights = TestingConstants::MultiGeometry::Weights;
+ const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets;
+ const auto& Primitives = TestingConstants::MultiGeometry::Primitives;
+
+ RefCntAutoPtr<IBuffer> pVertexBuffer;
+ RefCntAutoPtr<IBuffer> pIndexBuffer;
+ RefCntAutoPtr<IBuffer> pPerInstanceBuffer;
+ RefCntAutoPtr<IBuffer> pPrimitiveBuffer;
+ {
+ BufferDesc BuffDesc;
+ BuffDesc.Name = "Indices";
+ BuffDesc.Usage = USAGE_IMMUTABLE;
+ BuffDesc.BindFlags = BIND_RAY_TRACING;
+ BuffDesc.uiSizeInBytes = sizeof(Indices);
+ BufferData BufData = {Indices, sizeof(Indices)};
+ pDevice->CreateBuffer(BuffDesc, &BufData, &pIndexBuffer);
+ VERIFY_EXPR(pIndexBuffer != nullptr);
+
+ BuffDesc.Name = "Vertices";
+ BuffDesc.Mode = BUFFER_MODE_STRUCTURED;
+ BuffDesc.BindFlags = BIND_RAY_TRACING | BIND_SHADER_RESOURCE;
+ BuffDesc.uiSizeInBytes = sizeof(Vertices);
+ BuffDesc.ElementByteStride = sizeof(Vertices[0]);
+ BufData = {Vertices, sizeof(Vertices)};
+ pDevice->CreateBuffer(BuffDesc, &BufData, &pVertexBuffer);
+ VERIFY_EXPR(pVertexBuffer != nullptr);
+
+ BuffDesc.Name = "PerInstanceData";
+ BuffDesc.BindFlags = BIND_SHADER_RESOURCE;
+ BuffDesc.uiSizeInBytes = sizeof(PrimitiveOffsets);
+ BuffDesc.ElementByteStride = sizeof(PrimitiveOffsets[0]);
+ BufData = {PrimitiveOffsets, sizeof(PrimitiveOffsets)};
+ pDevice->CreateBuffer(BuffDesc, &BufData, &pPerInstanceBuffer);
+ VERIFY_EXPR(pPerInstanceBuffer != nullptr);
+
+ BuffDesc.Name = "PrimitiveData";
+ BuffDesc.uiSizeInBytes = sizeof(Primitives);
+ BuffDesc.ElementByteStride = sizeof(Primitives[0]);
+ BufData = {Primitives, sizeof(Primitives)};
+ pDevice->CreateBuffer(BuffDesc, &BufData, &pPrimitiveBuffer);
+ VERIFY_EXPR(pPrimitiveBuffer != nullptr);
+ }
+
+ BLASBuildTriangleData Triangles[3] = {};
+ Triangles[0].GeometryName = "Geom 1";
+ Triangles[0].pVertexBuffer = pVertexBuffer;
+ Triangles[0].VertexStride = sizeof(Vertices[0]);
+ Triangles[0].VertexCount = _countof(Vertices);
+ Triangles[0].VertexValueType = VT_FLOAT32;
+ Triangles[0].VertexComponentCount = 3;
+ Triangles[0].pIndexBuffer = pIndexBuffer;
+ Triangles[0].IndexType = VT_UINT32;
+ Triangles[0].IndexCount = (PrimitiveOffsets[1] - PrimitiveOffsets[0]) * 3;
+ Triangles[0].IndexOffset = PrimitiveOffsets[0] * sizeof(uint) * 3;
+ Triangles[0].Flags = RAYTRACING_GEOMETRY_OPAQUE;
+
+ Triangles[1].GeometryName = "Geom 2";
+ Triangles[1].pVertexBuffer = pVertexBuffer;
+ Triangles[1].VertexStride = sizeof(Vertices[0]);
+ Triangles[1].VertexCount = _countof(Vertices);
+ Triangles[1].VertexValueType = VT_FLOAT32;
+ Triangles[1].VertexComponentCount = 3;
+ Triangles[1].pIndexBuffer = pIndexBuffer;
+ Triangles[1].IndexType = VT_UINT32;
+ Triangles[1].IndexCount = (PrimitiveOffsets[2] - PrimitiveOffsets[1]) * 3;
+ Triangles[1].IndexOffset = PrimitiveOffsets[1] * sizeof(uint) * 3;
+ Triangles[1].Flags = RAYTRACING_GEOMETRY_OPAQUE;
+
+ Triangles[2].GeometryName = "Geom 3";
+ Triangles[2].pVertexBuffer = pVertexBuffer;
+ Triangles[2].VertexStride = sizeof(Vertices[0]);
+ Triangles[2].VertexCount = _countof(Vertices);
+ Triangles[2].VertexValueType = VT_FLOAT32;
+ Triangles[2].VertexComponentCount = 3;
+ Triangles[2].pIndexBuffer = pIndexBuffer;
+ Triangles[2].IndexType = VT_UINT32;
+ Triangles[2].IndexCount = (_countof(Primitives) - PrimitiveOffsets[2]) * 3;
+ Triangles[2].IndexOffset = PrimitiveOffsets[2] * sizeof(uint) * 3;
+ Triangles[2].Flags = RAYTRACING_GEOMETRY_OPAQUE;
+
+ RefCntAutoPtr<IBottomLevelAS> pBLAS;
+ CreateBLAS(pDevice, pContext, Triangles, _countof(Triangles), pBLAS);
+
+ TLASBuildInstanceData Instances[2] = {};
+
+ Instances[0].InstanceName = "Instance 1";
+ Instances[0].pBLAS = pBLAS;
+ Instances[0].Flags = RAYTRACING_INSTANCE_NONE;
+
+ Instances[1].InstanceName = "Instance 2";
+ Instances[1].pBLAS = pBLAS;
+ Instances[1].Flags = RAYTRACING_INSTANCE_NONE;
+ Instances[1].Transform.SetTranslation(0.1f, 0.5f, 0.0f);
+
+ RefCntAutoPtr<ITopLevelAS> pTLAS;
+ CreateTLAS(pDevice, pContext, Instances, _countof(Instances), pTLAS);
+
+ ShaderBindingTableDesc SBTDesc;
+ SBTDesc.Name = "SBT";
+ SBTDesc.pPSO = pRayTracingPSO;
+ SBTDesc.HitShadersPerInstance = 1;
+
+ RefCntAutoPtr<IShaderBindingTable> pSBT;
+ pDevice->CreateSBT(SBTDesc, &pSBT);
+ VERIFY_EXPR(pSBT != nullptr);
+
+ pSBT->BindRayGenShader("Main");
+ pSBT->BindMissShader("Miss", 0);
+ pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 1", 0, "HitGroup1", &Weights[2], sizeof(Weights[0]));
+ pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 2", 0, "HitGroup1", &Weights[0], sizeof(Weights[0]));
+ pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 3", 0, "HitGroup1", &Weights[1], sizeof(Weights[0]));
+ pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 1", 0, "HitGroup2", &Weights[2], sizeof(Weights[0]));
+ pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 2", 0, "HitGroup2", &Weights[1], sizeof(Weights[0]));
+ pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 3", 0, "HitGroup2", &Weights[0], sizeof(Weights[0]));
+
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_TLAS")->Set(pTLAS);
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_ColorBuffer")->Set(pTestingSwapChain->GetCurrentBackBufferUAV());
+
+ IDeviceObject* pObject = pPerInstanceBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE);
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_PerInstance")->SetArray(&pObject, 0, 1);
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_PerInstance")->SetArray(&pObject, 1, 1);
+
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_Primitives")->Set(pPrimitiveBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE));
+ pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_Vertices")->Set(pVertexBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE));
+
+ pContext->SetPipelineState(pRayTracingPSO);
+ pContext->CommitShaderResources(pRayTracingSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+
+ const auto& SCDesc = pSwapChain->GetDesc();
+
+ TraceRaysAttribs Attribs;
+ Attribs.DimensionX = SCDesc.Width;
+ Attribs.DimensionY = SCDesc.Height;
+ Attribs.pSBT = pSBT;
+ Attribs.TransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
+
+ pContext->TraceRays(Attribs);
+
+ pSwapChain->Present();
+}
+
} // namespace
diff --git a/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp b/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp
index 20788602..6c98a047 100644
--- a/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp
+++ b/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp
@@ -37,6 +37,7 @@
#include "volk/volk.h"
#include "InlineShaders/RayTracingTestGLSL.h"
+#include "RayTracingTestConstants.hpp"
namespace Diligent
{
@@ -49,20 +50,36 @@ namespace
struct RTContext
{
- VkDevice vkDevice = VK_NULL_HANDLE;
- VkCommandBuffer vkCmdBuffer = VK_NULL_HANDLE;
- VkImage vkRenderTarget = VK_NULL_HANDLE;
- VkImageView vkRenderTargetView = VK_NULL_HANDLE;
- VkPipelineLayout vkLayout = VK_NULL_HANDLE;
- VkPipeline vkPipeline = VK_NULL_HANDLE;
- VkDescriptorSetLayout vkSetLayout = VK_NULL_HANDLE;
- VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE;
- VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE;
- VkDeviceMemory vkBLASMemory = VK_NULL_HANDLE;
- VkAccelerationStructureKHR vkBLAS = VK_NULL_HANDLE;
- VkDeviceAddress vkBLASAddress = 0;
- VkDeviceMemory vkTLASMemory = VK_NULL_HANDLE;
- VkAccelerationStructureKHR vkTLAS = VK_NULL_HANDLE;
+ struct AccelStruct
+ {
+ VkDevice vkDevice = VK_NULL_HANDLE;
+ VkDeviceMemory vkMemory = VK_NULL_HANDLE;
+ VkAccelerationStructureKHR vkAS = VK_NULL_HANDLE;
+ VkDeviceAddress vkAddress = 0;
+
+ AccelStruct()
+ {}
+
+ ~AccelStruct()
+ {
+ if (vkAS)
+ vkDestroyAccelerationStructureKHR(vkDevice, vkAS, nullptr);
+ if (vkMemory)
+ vkFreeMemory(vkDevice, vkMemory, nullptr);
+ }
+ };
+
+ VkDevice vkDevice = VK_NULL_HANDLE;
+ VkCommandBuffer vkCmdBuffer = VK_NULL_HANDLE;
+ VkImage vkRenderTarget = VK_NULL_HANDLE;
+ VkImageView vkRenderTargetView = VK_NULL_HANDLE;
+ VkPipelineLayout vkLayout = VK_NULL_HANDLE;
+ VkPipeline vkPipeline = VK_NULL_HANDLE;
+ VkDescriptorSetLayout vkSetLayout = VK_NULL_HANDLE;
+ VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE;
+ VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE;
+ AccelStruct BLAS;
+ AccelStruct TLAS;
VkBuffer vkSBTBuffer = VK_NULL_HANDLE;
VkBuffer vkScratchBuffer = VK_NULL_HANDLE;
VkBuffer vkInstanceBuffer = VK_NULL_HANDLE;
@@ -73,7 +90,6 @@ struct RTContext
VkDeviceAddress vkVertexBufferAddress = 0;
VkDeviceAddress vkIndexBufferAddress = 0;
VkDeviceMemory vkBufferMemory = VK_NULL_HANDLE;
- VkPhysicalDeviceMemoryProperties MemoryProperties = {};
VkPhysicalDeviceLimits DeviceLimits = {};
VkPhysicalDeviceRayTracingPropertiesKHR RayTracingProps = {};
@@ -88,16 +104,8 @@ struct RTContext
vkDestroyPipelineLayout(vkDevice, vkLayout, nullptr);
if (vkSetLayout)
vkDestroyDescriptorSetLayout(vkDevice, vkSetLayout, nullptr);
- if (vkBLAS)
- vkDestroyAccelerationStructureKHR(vkDevice, vkBLAS, nullptr);
- if (vkTLAS)
- vkDestroyAccelerationStructureKHR(vkDevice, vkTLAS, nullptr);
if (vkDescriptorPool)
vkDestroyDescriptorPool(vkDevice, vkDescriptorPool, nullptr);
- if (vkBLASMemory)
- vkFreeMemory(vkDevice, vkBLASMemory, nullptr);
- if (vkTLASMemory)
- vkFreeMemory(vkDevice, vkTLASMemory, nullptr);
if (vkBufferMemory)
vkFreeMemory(vkDevice, vkBufferMemory, nullptr);
if (vkSBTBuffer)
@@ -136,8 +144,6 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P
Ctx.vkRenderTarget = pTestingSwapChainVk->GetVkRenderTargetImage();
Ctx.vkRenderTargetView = pTestingSwapChainVk->GetVkRenderTargetImageView();
- vkGetPhysicalDeviceMemoryProperties(pEnv->GetVkPhysicalDevice(), &Ctx.MemoryProperties);
-
VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
Props2.pNext = &Ctx.RayTracingProps;
Ctx.RayTracingProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR;
@@ -225,7 +231,7 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P
PoolSizes[0].descriptorCount = MaxDescriptorsInPool;
PoolSizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
PoolSizes[1].descriptorCount = MaxDescriptorsInPool;
- PoolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ PoolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
PoolSizes[2].descriptorCount = MaxDescriptorsInPool;
res = vkCreateDescriptorPool(Ctx.vkDevice, &DescriptorPoolCI, nullptr, &Ctx.vkDescriptorPool);
@@ -269,14 +275,16 @@ void UpdateDescriptorSet(RTContext& Ctx)
TLASInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
TLASInfo.accelerationStructureCount = 1;
- TLASInfo.pAccelerationStructures = &Ctx.vkTLAS;
+ TLASInfo.pAccelerationStructures = &Ctx.TLAS.vkAS;
DescriptorWrite[1].pNext = &TLASInfo;
vkUpdateDescriptorSets(Ctx.vkDevice, _countof(DescriptorWrite), DescriptorWrite, 0, nullptr);
}
-void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometries, Uint32 GeometryCount)
+void CreateBLAS(const RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometries, Uint32 GeometryCount, RTContext::AccelStruct& BLAS)
{
+ BLAS.vkDevice = Ctx.vkDevice;
+
VkResult res = VK_SUCCESS;
VkAccelerationStructureCreateInfoKHR BLASCI = {};
@@ -290,12 +298,12 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI
BLASCI.compactedSize = 0;
BLASCI.pGeometryInfos = pGeometries;
- res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &BLASCI, nullptr, &Ctx.vkBLAS);
+ res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &BLASCI, nullptr, &BLAS.vkAS);
ASSERT_GE(res, VK_SUCCESS);
- ASSERT_TRUE(Ctx.vkBLAS != VK_NULL_HANDLE);
+ ASSERT_TRUE(BLAS.vkAS != VK_NULL_HANDLE);
MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
- MemInfo.accelerationStructure = Ctx.vkBLAS;
+ MemInfo.accelerationStructure = BLAS.vkAS;
MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
@@ -307,32 +315,21 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = MemReqs.memoryRequirements.size;
- MemAlloc.memoryTypeIndex = ~0u;
-
- for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i)
- {
- const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags;
-
- if (!!(MemReqs.memoryRequirements.memoryTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
- {
- MemAlloc.memoryTypeIndex = i;
- break;
- }
- }
+ MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u);
- res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkBLASMemory);
+ res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &BLAS.vkMemory);
ASSERT_GE(res, VK_SUCCESS);
- ASSERT_TRUE(Ctx.vkBLASMemory != VK_NULL_HANDLE);
+ ASSERT_TRUE(BLAS.vkMemory != VK_NULL_HANDLE);
VkBindAccelerationStructureMemoryInfoKHR BindInfo = {};
BindInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
- BindInfo.memory = Ctx.vkBLASMemory;
+ BindInfo.memory = BLAS.vkMemory;
BindInfo.memoryOffset = 0;
BindInfo.deviceIndexCount = 0;
BindInfo.pDeviceIndices = nullptr;
- BindInfo.accelerationStructure = Ctx.vkBLAS;
+ BindInfo.accelerationStructure = BLAS.vkAS;
res = vkBindAccelerationStructureMemoryKHR(Ctx.vkDevice, 1, &BindInfo);
ASSERT_GE(res, VK_SUCCESS);
@@ -340,13 +337,15 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI
VkAccelerationStructureDeviceAddressInfoKHR AddressInfo = {};
AddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
- AddressInfo.accelerationStructure = Ctx.vkBLAS;
+ AddressInfo.accelerationStructure = BLAS.vkAS;
- Ctx.vkBLASAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo);
+ BLAS.vkAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo);
}
-void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount)
+void CreateTLAS(const RTContext& Ctx, Uint32 InstanceCount, RTContext::AccelStruct& TLAS)
{
+ TLAS.vkDevice = Ctx.vkDevice;
+
VkResult res = VK_SUCCESS;
VkAccelerationStructureCreateInfoKHR TLASCI = {};
@@ -365,12 +364,12 @@ void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount)
TLASCI.maxGeometryCount = 1;
TLASCI.pGeometryInfos = &Instances;
- res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &TLASCI, nullptr, &Ctx.vkTLAS);
+ res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &TLASCI, nullptr, &TLAS.vkAS);
ASSERT_GE(res, VK_SUCCESS);
- ASSERT_TRUE(Ctx.vkTLAS != VK_NULL_HANDLE);
+ ASSERT_TRUE(TLAS.vkAS != VK_NULL_HANDLE);
MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
- MemInfo.accelerationStructure = Ctx.vkTLAS;
+ MemInfo.accelerationStructure = TLAS.vkAS;
MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
@@ -382,39 +381,34 @@ void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount)
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = MemReqs.memoryRequirements.size;
- MemAlloc.memoryTypeIndex = ~0u;
-
- for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i)
- {
- const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags;
-
- if (!!(MemReqs.memoryRequirements.memoryTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
- {
- MemAlloc.memoryTypeIndex = i;
- break;
- }
- }
+ MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u);
- res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkTLASMemory);
+ res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &TLAS.vkMemory);
ASSERT_GE(res, VK_SUCCESS);
- ASSERT_TRUE(Ctx.vkTLASMemory != VK_NULL_HANDLE);
+ ASSERT_TRUE(TLAS.vkMemory != VK_NULL_HANDLE);
VkBindAccelerationStructureMemoryInfoKHR BindInfo = {};
BindInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
- BindInfo.memory = Ctx.vkTLASMemory;
+ BindInfo.memory = TLAS.vkMemory;
BindInfo.memoryOffset = 0;
BindInfo.deviceIndexCount = 0;
BindInfo.pDeviceIndices = nullptr;
- BindInfo.accelerationStructure = Ctx.vkTLAS;
+ BindInfo.accelerationStructure = TLAS.vkAS;
res = vkBindAccelerationStructureMemoryKHR(Ctx.vkDevice, 1, &BindInfo);
ASSERT_GE(res, VK_SUCCESS);
+
+ VkAccelerationStructureDeviceAddressInfoKHR AddressInfo = {};
+
+ AddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
+ AddressInfo.accelerationStructure = TLAS.vkAS;
+
+ TLAS.vkAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo);
}
-template <typename TCreateBufferFn>
-void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, TCreateBufferFn&& CreateBufferFn)
+void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, Uint32 ShaderRecordSize = 0)
{
VkResult res = VK_SUCCESS;
@@ -431,9 +425,9 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
- if (Ctx.vkBLAS)
+ if (Ctx.BLAS.vkAS)
{
- MemInfo.accelerationStructure = Ctx.vkBLAS;
+ MemInfo.accelerationStructure = Ctx.BLAS.vkAS;
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
vkGetAccelerationStructureMemoryRequirementsKHR(Ctx.vkDevice, &MemInfo, &MemReqs);
@@ -444,9 +438,9 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
ScratchSize = std::max(ScratchSize, MemReqs.memoryRequirements.size);
}
- if (Ctx.vkTLAS)
+ if (Ctx.TLAS.vkAS)
{
- MemInfo.accelerationStructure = Ctx.vkTLAS;
+ MemInfo.accelerationStructure = Ctx.TLAS.vkAS;
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
vkGetAccelerationStructureMemoryRequirementsKHR(Ctx.vkDevice, &MemInfo, &MemReqs);
@@ -466,7 +460,7 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR;
BuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- BuffCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ BuffCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
MemInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
std::vector<std::function<void(VkDeviceMemory Mem, VkDeviceSize & Offset)>> BindMem;
@@ -569,9 +563,11 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
// SBT
{
- BuffCI.size = Align(Ctx.RayTracingProps.shaderGroupBaseAlignment, Ctx.RayTracingProps.shaderGroupHandleSize);
- BuffCI.size = Align(BuffCI.size + Ctx.RayTracingProps.shaderGroupHandleSize * NumMissShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- BuffCI.size = Align(BuffCI.size + Ctx.RayTracingProps.shaderGroupHandleSize * NumHitShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment);
+ const Uint32 GroupSize = Ctx.RayTracingProps.shaderGroupHandleSize + ShaderRecordSize;
+
+ BuffCI.size = Align(GroupSize, Ctx.RayTracingProps.shaderGroupBaseAlignment);
+ BuffCI.size = Align(BuffCI.size + GroupSize * NumMissShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment);
+ BuffCI.size = Align(BuffCI.size + GroupSize * NumHitShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment);
res = vkCreateBuffer(Ctx.vkDevice, &BuffCI, nullptr, &Ctx.vkSBTBuffer);
ASSERT_GE(res, VK_SUCCESS);
@@ -591,31 +587,18 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
});
}
- CreateBufferFn(MemSize, MemTypeBits, BindMem);
-
VkMemoryAllocateInfo MemAlloc = {};
VkMemoryAllocateFlagsInfo MemFlagInfo = {};
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = MemSize;
- MemAlloc.memoryTypeIndex = ~0u;
+ MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u);
MemAlloc.pNext = &MemFlagInfo;
MemFlagInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
MemFlagInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
- for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i)
- {
- const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags;
-
- if (!!(MemTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
- {
- MemAlloc.memoryTypeIndex = i;
- break;
- }
- }
- ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u);
-
res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkBufferMemory);
ASSERT_GE(res, VK_SUCCESS);
ASSERT_TRUE(Ctx.vkBufferMemory != VK_NULL_HANDLE);
@@ -628,9 +611,15 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan
ASSERT_GE(MemSize, Offset);
}
-void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders)
+void ClearRenderTarget(RTContext& Ctx, TestingSwapChainVk* pTestingSwapChainVk)
{
- return CreateRTBuffers(Ctx, VBSize, IBSize, InstanceCount, NumMissShaders, NumHitShaders, [](auto& MemSize, auto& MemTypeBits, auto& BindMem) {});
+ pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0);
+
+ VkImageSubresourceRange Range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
+ VkClearColorValue ClearValue = {};
+ vkCmdClearColorImage(Ctx.vkCmdBuffer, Ctx.vkRenderTarget, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &ClearValue, 1, &Range);
+
+ pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_GENERAL, 0);
}
} // namespace
@@ -709,12 +698,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
VkMemoryBarrier Barrier = {};
Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f},
- float3{0.75f, 0.25f, 0.0f},
- float3{0.50f, 0.75f, 0.0f} //
- };
+ const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {};
@@ -726,11 +710,11 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
GeometryCI.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
GeometryCI.allowsTransforms = VK_FALSE;
- CreateBLAS(Ctx, &GeometryCI, 1);
- CreateTLAS(Ctx, 1);
+ CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS);
+ CreateTLAS(Ctx, 1, Ctx.TLAS);
CreateRTBuffers(Ctx, sizeof(Vertices), 0, 1, 1, 1);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), &Vertices);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices);
// barrier for vertex & index buffers
Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -746,16 +730,14 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
VkAccelerationStructureGeometryKHR const* GeometryPtr = &Geometry;
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = &Offset;
- Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
- Geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
- Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
- Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
- Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat;
- Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]);
- Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
- Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
- Geometry.geometry.triangles.indexData.deviceAddress = 0;
- Geometry.geometry.triangles.transformData.deviceAddress = 0;
+ Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
+ Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
+ Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat;
+ Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]);
+ Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
+ Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
Offset.primitiveCount = GeometryCI.maxPrimitiveCount;
Offset.firstVertex = 0;
@@ -767,7 +749,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -780,7 +762,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
InstanceData.instanceShaderBindingTableRecordOffset = 0;
InstanceData.mask = 0xFF;
InstanceData.flags = 0;
- InstanceData.accelerationStructureReference = Ctx.vkBLASAddress;
+ InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress;
InstanceData.transform.matrix[0][0] = 1.0f;
InstanceData.transform.matrix[1][1] = 1.0f;
InstanceData.transform.matrix[2][2] = 1.0f;
@@ -812,7 +794,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -831,33 +813,34 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain)
VkStridedBufferRegionKHR MissShaderBindingTable = {};
VkStridedBufferRegionKHR HitShaderBindingTable = {};
VkStridedBufferRegionKHR CallableShaderBindingTable = {};
+ const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize;
RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer;
RaygenShaderBindingTable.offset = 0;
- RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ RaygenShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
MissShaderBindingTable.buffer = Ctx.vkSBTBuffer;
MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ MissShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
HitShaderBindingTable.buffer = Ctx.vkSBTBuffer;
HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ HitShaderBindingTable.size = ShaderGroupHandleSize;
+ HitShaderBindingTable.stride = ShaderGroupHandleSize;
char ShaderHandle[64] = {};
- ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize);
+ ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
// Barriers for TLAS & SBT
VkMemoryBarrier Barrier = {};
@@ -965,12 +948,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
VkMemoryBarrier Barrier = {};
Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- const float3 Vertices[] = //
- {
- float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f},
- float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f},
- float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} //
- };
+ const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices;
VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {};
@@ -982,11 +960,11 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
GeometryCI.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
GeometryCI.allowsTransforms = VK_FALSE;
- CreateBLAS(Ctx, &GeometryCI, 1);
- CreateTLAS(Ctx, 1);
+ CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS);
+ CreateTLAS(Ctx, 1, Ctx.TLAS);
CreateRTBuffers(Ctx, sizeof(Vertices), 0, 1, 1, 1);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), &Vertices);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices);
// barrier for vertex & index buffers
Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -1002,16 +980,14 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
VkAccelerationStructureGeometryKHR const* GeometryPtr = &Geometry;
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = &Offset;
- Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
- Geometry.flags = 0;
- Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
- Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
- Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat;
- Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]);
- Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
- Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
- Geometry.geometry.triangles.indexData.deviceAddress = 0;
- Geometry.geometry.triangles.transformData.deviceAddress = 0;
+ Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometry.flags = 0;
+ Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
+ Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat;
+ Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]);
+ Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
+ Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
Offset.primitiveCount = GeometryCI.maxPrimitiveCount;
Offset.firstVertex = 0;
@@ -1023,7 +999,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -1036,7 +1012,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
InstanceData.instanceShaderBindingTableRecordOffset = 0;
InstanceData.mask = 0xFF;
InstanceData.flags = 0;
- InstanceData.accelerationStructureReference = Ctx.vkBLASAddress;
+ InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress;
InstanceData.transform.matrix[0][0] = 1.0f;
InstanceData.transform.matrix[1][1] = 1.0f;
InstanceData.transform.matrix[2][2] = 1.0f;
@@ -1068,7 +1044,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -1087,33 +1063,34 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain)
VkStridedBufferRegionKHR MissShaderBindingTable = {};
VkStridedBufferRegionKHR HitShaderBindingTable = {};
VkStridedBufferRegionKHR CallableShaderBindingTable = {};
+ const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize;
RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer;
RaygenShaderBindingTable.offset = 0;
- RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ RaygenShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
MissShaderBindingTable.buffer = Ctx.vkSBTBuffer;
MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ MissShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
HitShaderBindingTable.buffer = Ctx.vkSBTBuffer;
HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ HitShaderBindingTable.size = ShaderGroupHandleSize;
+ HitShaderBindingTable.stride = ShaderGroupHandleSize;
char ShaderHandle[64] = {};
- ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize);
+ ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
// Barriers for TLAS & SBT
VkMemoryBarrier Barrier = {};
@@ -1221,11 +1198,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
VkMemoryBarrier Barrier = {};
Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- const float3 Boxes[] = //
- {
- float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f},
- float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f} //
- };
+ const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes;
VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {};
@@ -1234,11 +1207,11 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
GeometryCI.maxPrimitiveCount = 1;
GeometryCI.indexType = VK_INDEX_TYPE_NONE_KHR;
- CreateBLAS(Ctx, &GeometryCI, 1);
- CreateTLAS(Ctx, 1);
+ CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS);
+ CreateTLAS(Ctx, 1, Ctx.TLAS);
CreateRTBuffers(Ctx, sizeof(Boxes), 0, 1, 1, 1);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Boxes), &Boxes);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Boxes), Boxes);
// barrier for vertex & index buffers
Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -1272,7 +1245,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -1285,7 +1258,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
InstanceData.instanceShaderBindingTableRecordOffset = 0;
InstanceData.mask = 0xFF;
InstanceData.flags = 0;
- InstanceData.accelerationStructureReference = Ctx.vkBLASAddress;
+ InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress;
InstanceData.transform.matrix[0][0] = 1.0f;
InstanceData.transform.matrix[1][1] = 1.0f;
InstanceData.transform.matrix[2][2] = 1.0f;
@@ -1317,7 +1290,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
ASBuildInfo.flags = 0;
ASBuildInfo.update = VK_FALSE;
ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
- ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS;
+ ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS;
ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
ASBuildInfo.geometryCount = 1;
ASBuildInfo.ppGeometries = &GeometryPtr;
@@ -1336,33 +1309,34 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
VkStridedBufferRegionKHR MissShaderBindingTable = {};
VkStridedBufferRegionKHR HitShaderBindingTable = {};
VkStridedBufferRegionKHR CallableShaderBindingTable = {};
+ const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize;
RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer;
RaygenShaderBindingTable.offset = 0;
- RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ RaygenShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
MissShaderBindingTable.buffer = Ctx.vkSBTBuffer;
MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ MissShaderBindingTable.size = ShaderGroupHandleSize;
+ MissShaderBindingTable.stride = ShaderGroupHandleSize;
HitShaderBindingTable.buffer = Ctx.vkSBTBuffer;
HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
- HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize;
- HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize;
+ HitShaderBindingTable.size = ShaderGroupHandleSize;
+ HitShaderBindingTable.stride = ShaderGroupHandleSize;
char ShaderHandle[64] = {};
- ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize);
+ ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
- vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
- vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle);
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
// barrier for TLAS & SBT
VkMemoryBarrier Barrier = {};
@@ -1388,6 +1362,398 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain)
pEnv->SubmitCommandBuffer(Ctx.vkCmdBuffer, true);
}
+
+void RayTracingMultiGeometryReferenceVk(ISwapChain* pSwapChain)
+{
+ static constexpr Uint32 InstanceCount = TestingConstants::MultiGeometry::InstanceCount;
+ static constexpr Uint32 GeometryCount = 3;
+ static constexpr Uint32 HitGroupCount = InstanceCount * GeometryCount;
+
+ enum
+ {
+ RAYGEN_SHADER,
+ MISS_SHADER,
+ HIT_SHADER_1,
+ HIT_SHADER_2,
+ NUM_SHADERS
+ };
+ enum
+ {
+ RAYGEN_GROUP,
+ MISS_GROUP,
+ HIT_GROUP_1,
+ HIT_GROUP_2,
+ NUM_GROUPS
+ };
+
+ auto* pEnv = TestingEnvironmentVk::GetInstance();
+ auto* pTestingSwapChainVk = ValidatedCast<TestingSwapChainVk>(pSwapChain);
+
+ const auto& SCDesc = pSwapChain->GetDesc();
+
+ RTContext Ctx = {};
+ InitializeRTContext(Ctx, pSwapChain,
+ [pEnv](auto& Bindings, auto& Modules, auto& Stages, auto& Groups) {
+ Bindings.resize(3);
+ Bindings[0] = {2u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, InstanceCount, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr};
+ Bindings[1] = {3u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr};
+ Bindings[2] = {4u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr};
+
+ Modules.resize(NUM_SHADERS);
+ Stages.resize(NUM_SHADERS);
+ Groups.resize(NUM_GROUPS);
+
+ Modules[RAYGEN_SHADER] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_GEN, GLSL::RayTracingTest4_RG);
+ Stages[RAYGEN_SHADER].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ Stages[RAYGEN_SHADER].stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
+ Stages[RAYGEN_SHADER].module = Modules[RAYGEN_SHADER];
+ Stages[RAYGEN_SHADER].pName = "main";
+
+ Modules[MISS_SHADER] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_MISS, GLSL::RayTracingTest4_RM);
+ Stages[MISS_SHADER].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ Stages[MISS_SHADER].stage = VK_SHADER_STAGE_MISS_BIT_KHR;
+ Stages[MISS_SHADER].module = Modules[MISS_SHADER];
+ Stages[MISS_SHADER].pName = "main";
+
+ Modules[HIT_SHADER_1] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_CLOSEST_HIT, GLSL::RayTracingTest4_RCH1);
+ Stages[HIT_SHADER_1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ Stages[HIT_SHADER_1].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
+ Stages[HIT_SHADER_1].module = Modules[HIT_SHADER_1];
+ Stages[HIT_SHADER_1].pName = "main";
+
+ Modules[HIT_SHADER_2] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_CLOSEST_HIT, GLSL::RayTracingTest4_RCH2);
+ Stages[HIT_SHADER_2].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ Stages[HIT_SHADER_2].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
+ Stages[HIT_SHADER_2].module = Modules[HIT_SHADER_2];
+ Stages[HIT_SHADER_2].pName = "main";
+
+ Groups[RAYGEN_GROUP].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Groups[RAYGEN_GROUP].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
+ Groups[RAYGEN_GROUP].generalShader = RAYGEN_SHADER;
+ Groups[RAYGEN_GROUP].closestHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[RAYGEN_GROUP].anyHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[RAYGEN_GROUP].intersectionShader = VK_SHADER_UNUSED_KHR;
+
+ Groups[HIT_GROUP_1].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Groups[HIT_GROUP_1].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
+ Groups[HIT_GROUP_1].generalShader = VK_SHADER_UNUSED_KHR;
+ Groups[HIT_GROUP_1].closestHitShader = HIT_SHADER_1;
+ Groups[HIT_GROUP_1].anyHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[HIT_GROUP_1].intersectionShader = VK_SHADER_UNUSED_KHR;
+
+ Groups[HIT_GROUP_2].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Groups[HIT_GROUP_2].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
+ Groups[HIT_GROUP_2].generalShader = VK_SHADER_UNUSED_KHR;
+ Groups[HIT_GROUP_2].closestHitShader = HIT_SHADER_2;
+ Groups[HIT_GROUP_2].anyHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[HIT_GROUP_2].intersectionShader = VK_SHADER_UNUSED_KHR;
+
+ Groups[MISS_GROUP].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Groups[MISS_GROUP].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
+ Groups[MISS_GROUP].generalShader = MISS_SHADER;
+ Groups[MISS_GROUP].closestHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[MISS_GROUP].anyHitShader = VK_SHADER_UNUSED_KHR;
+ Groups[MISS_GROUP].intersectionShader = VK_SHADER_UNUSED_KHR;
+ });
+
+ const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets;
+ const auto& Primitives = TestingConstants::MultiGeometry::Primitives;
+
+ // create acceleration structurea
+ {
+ VkMemoryBarrier Barrier = {};
+ Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+
+ const auto& Vertices = TestingConstants::MultiGeometry::Vertices;
+ const auto& Indices = TestingConstants::MultiGeometry::Indices;
+
+ VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI[3] = {};
+
+ GeometryCI[0].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
+ GeometryCI[0].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ GeometryCI[0].maxPrimitiveCount = PrimitiveOffsets[1];
+ GeometryCI[0].indexType = VK_INDEX_TYPE_UINT32;
+ GeometryCI[0].maxVertexCount = _countof(Vertices);
+ GeometryCI[0].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
+ GeometryCI[0].allowsTransforms = VK_FALSE;
+
+ GeometryCI[1].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
+ GeometryCI[1].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ GeometryCI[1].maxPrimitiveCount = PrimitiveOffsets[2] - PrimitiveOffsets[1];
+ GeometryCI[1].indexType = VK_INDEX_TYPE_UINT32;
+ GeometryCI[1].maxVertexCount = _countof(Vertices);
+ GeometryCI[1].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
+ GeometryCI[1].allowsTransforms = VK_FALSE;
+
+ GeometryCI[2].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
+ GeometryCI[2].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ GeometryCI[2].maxPrimitiveCount = _countof(Primitives) - PrimitiveOffsets[2];
+ GeometryCI[2].indexType = VK_INDEX_TYPE_UINT32;
+ GeometryCI[2].maxVertexCount = _countof(Vertices);
+ GeometryCI[2].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
+ GeometryCI[2].allowsTransforms = VK_FALSE;
+
+ CreateBLAS(Ctx, GeometryCI, _countof(GeometryCI), Ctx.BLAS);
+ CreateTLAS(Ctx, 1, Ctx.TLAS);
+ CreateRTBuffers(Ctx, sizeof(Vertices), sizeof(Indices), InstanceCount, 1, HitGroupCount, TestingConstants::MultiGeometry::ShaderRecordSize);
+
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkIndexBuffer, 0, sizeof(Indices), Indices);
+
+ // barrier for vertex & index buffers
+ Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
+ vkCmdPipelineBarrier(Ctx.vkCmdBuffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
+ 0, 1, &Barrier, 0, nullptr, 0, nullptr);
+
+ VkAccelerationStructureBuildGeometryInfoKHR ASBuildInfo = {};
+ VkAccelerationStructureBuildOffsetInfoKHR Offsets[3] = {};
+ VkAccelerationStructureGeometryKHR Geometries[3] = {};
+ VkAccelerationStructureGeometryKHR const* GeometriyPtr = Geometries;
+ VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = Offsets;
+ static_assert(_countof(Offsets) == _countof(Geometries), "size mismatch");
+ static_assert(_countof(GeometryCI) == _countof(Geometries), "size mismatch");
+ static_assert(GeometryCount == _countof(Geometries), "size mismatch");
+
+ Geometries[0].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometries[0].flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
+ Geometries[0].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ Geometries[0].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
+ Geometries[0].geometry.triangles.vertexFormat = GeometryCI[0].vertexFormat;
+ Geometries[0].geometry.triangles.vertexStride = sizeof(Vertices[0]);
+ Geometries[0].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
+ Geometries[0].geometry.triangles.indexType = GeometryCI[0].indexType;
+ Geometries[0].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[0] * sizeof(uint) * 3;
+
+ Geometries[1].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometries[1].flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
+ Geometries[1].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ Geometries[1].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
+ Geometries[1].geometry.triangles.vertexFormat = GeometryCI[1].vertexFormat;
+ Geometries[1].geometry.triangles.vertexStride = sizeof(Vertices[0]);
+ Geometries[1].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
+ Geometries[1].geometry.triangles.indexType = GeometryCI[1].indexType;
+ Geometries[1].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[1] * sizeof(uint) * 3;
+
+ Geometries[2].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometries[2].flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
+ Geometries[2].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
+ Geometries[2].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
+ Geometries[2].geometry.triangles.vertexFormat = GeometryCI[2].vertexFormat;
+ Geometries[2].geometry.triangles.vertexStride = sizeof(Vertices[0]);
+ Geometries[2].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress;
+ Geometries[2].geometry.triangles.indexType = GeometryCI[2].indexType;
+ Geometries[2].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[2] * sizeof(uint) * 3;
+
+ Offsets[0].primitiveCount = GeometryCI[0].maxPrimitiveCount;
+ Offsets[1].primitiveCount = GeometryCI[1].maxPrimitiveCount;
+ Offsets[2].primitiveCount = GeometryCI[2].maxPrimitiveCount;
+
+ ASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
+ ASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
+ ASBuildInfo.flags = 0;
+ ASBuildInfo.update = VK_FALSE;
+ ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
+ ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS;
+ ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
+ ASBuildInfo.geometryCount = _countof(Geometries);
+ ASBuildInfo.ppGeometries = &GeometriyPtr;
+ ASBuildInfo.scratchData.deviceAddress = Ctx.vkScratchBufferAddress;
+
+ vkCmdBuildAccelerationStructureKHR(Ctx.vkCmdBuffer, 1, &ASBuildInfo, &OffsetPtr);
+
+ VkAccelerationStructureInstanceKHR InstanceData[2] = {};
+
+ InstanceData[0].instanceCustomIndex = 0;
+ InstanceData[0].instanceShaderBindingTableRecordOffset = 0;
+ InstanceData[0].mask = 0xFF;
+ InstanceData[0].flags = 0;
+ InstanceData[0].accelerationStructureReference = Ctx.BLAS.vkAddress;
+ InstanceData[0].transform.matrix[0][0] = 1.0f;
+ InstanceData[0].transform.matrix[1][1] = 1.0f;
+ InstanceData[0].transform.matrix[2][2] = 1.0f;
+
+ InstanceData[1].instanceCustomIndex = 2;
+ InstanceData[1].instanceShaderBindingTableRecordOffset = HitGroupCount / 2;
+ InstanceData[1].mask = 0xFF;
+ InstanceData[1].flags = 0;
+ InstanceData[1].accelerationStructureReference = Ctx.BLAS.vkAddress;
+ InstanceData[1].transform.matrix[0][0] = 1.0f;
+ InstanceData[1].transform.matrix[1][1] = 1.0f;
+ InstanceData[1].transform.matrix[2][2] = 1.0f;
+ InstanceData[1].transform.matrix[0][3] = 0.1f;
+ InstanceData[1].transform.matrix[1][3] = 0.5f;
+ InstanceData[1].transform.matrix[2][3] = 0.0f;
+
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkInstanceBuffer, 0, sizeof(InstanceData), InstanceData);
+
+ // barrier for BLAS, scratch buffer, instance buffer
+ Barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT;
+ Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
+ vkCmdPipelineBarrier(Ctx.vkCmdBuffer,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
+ 0, 1, &Barrier, 0, nullptr, 0, nullptr);
+
+ VkAccelerationStructureBuildOffsetInfoKHR InstOffsets = {};
+ VkAccelerationStructureGeometryKHR Instances[2] = {};
+ static_assert(_countof(InstanceData) == _countof(Instances), "size mismatch");
+ static_assert(InstanceCount == _countof(Instances), "size mismatch");
+
+ GeometriyPtr = Instances;
+ OffsetPtr = &InstOffsets;
+ InstOffsets.primitiveCount = _countof(Instances);
+
+ Instances[0].flags = 0;
+ Instances[0].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Instances[0].geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
+ Instances[0].geometry.instances.pNext = nullptr;
+ Instances[0].geometry.instances.arrayOfPointers = VK_FALSE;
+ Instances[0].geometry.instances.data.deviceAddress = Ctx.vkInstanceBufferAddress;
+
+ Instances[1].flags = 0;
+ Instances[1].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Instances[1].geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
+ Instances[1].geometry.instances.pNext = nullptr;
+ Instances[1].geometry.instances.arrayOfPointers = VK_FALSE;
+ Instances[1].geometry.instances.data.deviceAddress = Ctx.vkInstanceBufferAddress + sizeof(VkAccelerationStructureInstanceKHR);
+
+ ASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
+ ASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
+ ASBuildInfo.flags = 0;
+ ASBuildInfo.update = VK_FALSE;
+ ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
+ ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS;
+ ASBuildInfo.geometryArrayOfPointers = VK_FALSE;
+ ASBuildInfo.geometryCount = 1;
+ ASBuildInfo.ppGeometries = &GeometriyPtr;
+ ASBuildInfo.scratchData.deviceAddress = Ctx.vkScratchBufferAddress;
+
+ vkCmdBuildAccelerationStructureKHR(Ctx.vkCmdBuffer, 1, &ASBuildInfo, &OffsetPtr);
+ }
+
+ ClearRenderTarget(Ctx, pTestingSwapChainVk);
+ UpdateDescriptorSet(Ctx);
+
+ VkBuffer vkPerInstanceBuffer = VK_NULL_HANDLE;
+ VkDeviceMemory vkPerInstanceBufferMemory = VK_NULL_HANDLE;
+ VkBuffer vkPrimitiveBuffer = VK_NULL_HANDLE;
+ VkDeviceMemory vkPrimitiveBufferMemory = VK_NULL_HANDLE;
+ {
+ pEnv->CreateBuffer(sizeof(PrimitiveOffsets), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vkPerInstanceBufferMemory, vkPerInstanceBuffer);
+ pEnv->CreateBuffer(sizeof(Primitives), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vkPrimitiveBufferMemory, vkPrimitiveBuffer);
+
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, vkPerInstanceBuffer, 0, sizeof(PrimitiveOffsets), PrimitiveOffsets);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, vkPrimitiveBuffer, 0, sizeof(Primitives), Primitives);
+
+ VkWriteDescriptorSet DescriptorWrite = {};
+ VkDescriptorBufferInfo BufInfo = {};
+
+ DescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ DescriptorWrite.dstSet = Ctx.vkDescriptorSet;
+ DescriptorWrite.dstBinding = 4;
+ DescriptorWrite.dstArrayElement = 0;
+ DescriptorWrite.descriptorCount = 1;
+ DescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ DescriptorWrite.pBufferInfo = &BufInfo;
+ BufInfo.buffer = Ctx.vkVertexBuffer;
+ BufInfo.range = VK_WHOLE_SIZE;
+ vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr);
+
+ DescriptorWrite.dstBinding = 3;
+ BufInfo.buffer = vkPrimitiveBuffer;
+ vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr);
+
+ DescriptorWrite.dstBinding = 2;
+ BufInfo.buffer = vkPerInstanceBuffer;
+ vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr);
+
+ DescriptorWrite.dstArrayElement = 1;
+ vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr);
+ }
+
+ // trace rays
+ {
+ VkStridedBufferRegionKHR RaygenShaderBindingTable = {};
+ VkStridedBufferRegionKHR MissShaderBindingTable = {};
+ VkStridedBufferRegionKHR HitShaderBindingTable = {};
+ VkStridedBufferRegionKHR CallableShaderBindingTable = {};
+ const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize;
+ const Uint32 ShaderRecordSize = ShaderGroupHandleSize + TestingConstants::MultiGeometry::ShaderRecordSize;
+ const auto& Weights = TestingConstants::MultiGeometry::Weights;
+
+ RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer;
+ RaygenShaderBindingTable.offset = 0;
+ RaygenShaderBindingTable.size = ShaderRecordSize;
+ MissShaderBindingTable.stride = ShaderRecordSize;
+
+ MissShaderBindingTable.buffer = Ctx.vkSBTBuffer;
+ MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
+ MissShaderBindingTable.size = ShaderRecordSize;
+ MissShaderBindingTable.stride = ShaderRecordSize;
+
+ HitShaderBindingTable.buffer = Ctx.vkSBTBuffer;
+ HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment);
+ HitShaderBindingTable.size = ShaderRecordSize * HitGroupCount;
+ HitShaderBindingTable.stride = ShaderRecordSize;
+
+ char ShaderHandle[64] = {};
+ ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize);
+
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
+
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle);
+
+ const auto SetHitGroup = [&](Uint32 Index, Uint32 ShaderIndex, const void* ShaderRecord) {
+ VERIFY_EXPR(Index < HitGroupCount);
+ VkDeviceSize Offset = HitShaderBindingTable.offset + Index * ShaderRecordSize;
+ vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, ShaderIndex, 1, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, Offset, ShaderGroupHandleSize, ShaderHandle);
+ vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, Offset + ShaderGroupHandleSize, sizeof(Weights[0]), ShaderRecord);
+ };
+ // instance 1
+ SetHitGroup(0, HIT_GROUP_1, &Weights[2]); // geometry 1
+ SetHitGroup(1, HIT_GROUP_1, &Weights[0]); // geometry 2
+ SetHitGroup(2, HIT_GROUP_1, &Weights[1]); // geometry 3
+ // instance 2
+ SetHitGroup(3, HIT_GROUP_2, &Weights[2]); // geometry 1
+ SetHitGroup(4, HIT_GROUP_2, &Weights[1]); // geometry 2
+ SetHitGroup(5, HIT_GROUP_2, &Weights[0]); // geometry 3
+
+ // barrier for TLAS & SBT
+ VkMemoryBarrier Barrier = {};
+ Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ Barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT;
+ Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
+ vkCmdPipelineBarrier(Ctx.vkCmdBuffer,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
+ 0, 1, &Barrier, 0, nullptr, 0, nullptr);
+
+ vkCmdBindPipeline(Ctx.vkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, Ctx.vkPipeline);
+ vkCmdBindDescriptorSets(Ctx.vkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, Ctx.vkLayout, 0, 1, &Ctx.vkDescriptorSet, 0, nullptr);
+
+ vkCmdTraceRaysKHR(Ctx.vkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, SCDesc.Width, SCDesc.Height, 1);
+
+ pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0);
+ }
+
+ auto res = vkEndCommandBuffer(Ctx.vkCmdBuffer);
+ VERIFY(res >= 0, "Failed to end command buffer");
+
+ pEnv->SubmitCommandBuffer(Ctx.vkCmdBuffer, true);
+
+ vkDestroyBuffer(Ctx.vkDevice, vkPerInstanceBuffer, nullptr);
+ vkDestroyBuffer(Ctx.vkDevice, vkPrimitiveBuffer, nullptr);
+ vkFreeMemory(Ctx.vkDevice, vkPerInstanceBufferMemory, nullptr);
+ vkFreeMemory(Ctx.vkDevice, vkPrimitiveBufferMemory, nullptr);
+}
+
+
} // namespace Testing
} // namespace Diligent