summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-28 16:33:03 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-28 18:04:08 +0000
commit135d5dc6743fc89d7a19c539fa06eca33506f51b (patch)
tree9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics
parentFixed vexing gcc/clang liker error (diff)
downloadDiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.tar.gz
DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.zip
added ray tracing implementation for dx12 and vulkan
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp6
-rw-r--r--Graphics/GraphicsEngine/include/BottomLevelASBase.hpp34
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp192
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp105
-rw-r--r--Graphics/GraphicsEngine/include/TopLevelASBase.hpp48
-rw-r--r--Graphics/GraphicsEngine/interface/BottomLevelAS.h25
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h155
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h128
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h39
-rw-r--r--Graphics/GraphicsEngine/interface/ShaderBindingTable.h8
-rw-r--r--Graphics/GraphicsEngine/interface/TopLevelAS.h25
-rw-r--r--Graphics/GraphicsEngine/src/BufferBase.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp4
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp61
-rw-r--r--Graphics/GraphicsEngineD3D12/CMakeLists.txt9
-rw-r--r--Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp74
-rw-r--r--Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp6
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandContext.hpp157
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp21
-rw-r--r--Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp79
-rw-r--r--Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp83
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h70
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h71
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h77
-rw-r--r--Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp152
-rw-r--r--Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandContext.cpp99
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp70
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp274
-rw-r--r--Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp8
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp33
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp15
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp202
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp30
-rw-r--r--Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp115
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp18
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp29
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp53
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp67
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h11
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp10
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp14
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp309
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp20
-rw-r--r--Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp187
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp63
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp16
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp65
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp87
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp30
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp123
74 files changed, 3033 insertions, 786 deletions
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
index 918b81ae..0617ca59 100644
--- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
+++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
@@ -1055,7 +1055,8 @@ const Char* GetResourceStateFlagString(RESOURCE_STATE State)
case RESOURCE_STATE_RESOLVE_SOURCE: return "RESOLVE_SOURCE";
case RESOURCE_STATE_INPUT_ATTACHMENT: return "INPUT_ATTACHMENT";
case RESOURCE_STATE_PRESENT: return "PRESENT";
- case RESOURCE_STATE_BUILD_AS: return "BUILD_AS";
+ case RESOURCE_STATE_BUILD_AS_READ: return "BUILD_AS_READ";
+ case RESOURCE_STATE_BUILD_AS_WRITE: return "BUILD_AS_WRITE";
case RESOURCE_STATE_RAY_TRACING: return "RAY_TRACING";
// clang-format on
default:
@@ -1204,7 +1205,8 @@ if ( (State & ExclusiveState) != 0 && (State & ~ExclusiveState) != 0 )\
VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_COPY_DEST);
VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_RESOLVE_DEST);
VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_PRESENT);
- VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_BUILD_AS);
+ VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_BUILD_AS_READ);
+ VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_BUILD_AS_WRITE);
VERIFY_EXCLUSIVE_STATE(RESOURCE_STATE_RAY_TRACING);
#undef VERIFY_EXCLUSIVE_STATE
// clang-format on
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
index 879d73ab..9f37fb3f 100644
--- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
@@ -106,7 +106,7 @@ public:
else if (Desc.pBoxes != nullptr)
{
size_t StringPoolSize = 0;
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
+ for (Uint32 i = 0; i < Desc.BoxCount; ++i)
{
if (Desc.pBoxes[i].GeometryName == nullptr)
LOG_ERROR_AND_THROW("Geometry name can not be null!");
@@ -124,7 +124,7 @@ public:
this->m_Desc.pTriangles = nullptr;
// copy strings
- for (Uint32 i = 0; i < Desc.TriangleCount; ++i)
+ for (Uint32 i = 0; i < Desc.BoxCount; ++i)
{
pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName);
bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second;
@@ -147,7 +147,9 @@ public:
}
}
- virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override
+ static constexpr Uint32 InvalidGeometryIndex = ~0u;
+
+ virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final
{
VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
@@ -156,7 +158,29 @@ public:
return iter->second;
UNEXPECTED("Can't find geometry with specified name");
- return ~0u; // AZ TODO
+ return InvalidGeometryIndex;
+ }
+
+ virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
+ {
+ this->m_State = State;
+ }
+
+ virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final
+ {
+ return this->m_State;
+ }
+
+ bool IsInKnownState() const
+ {
+ return this->m_State != RESOURCE_STATE_UNKNOWN;
+ }
+
+ bool CheckState(RESOURCE_STATE State) const
+ {
+ VERIFY((State & (State - 1)) == 0, "Single state is expected");
+ VERIFY(IsInKnownState(), "BLAS state is unknown");
+ return (this->m_State & State) == State;
}
protected:
@@ -185,6 +209,8 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase)
protected:
+ RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+
std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
StringPool m_StringPool;
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index c16219da..0d98bae3 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -78,6 +78,8 @@ public:
using QueryImplType = typename ImplementationTraits::QueryType;
using FramebufferImplType = typename ImplementationTraits::FramebufferType;
using RenderPassImplType = typename ImplementationTraits::RenderPassType;
+ using BottomLevelASType = typename ImplementationTraits::BottomLevelASType;
+ using TopLevelASType = typename ImplementationTraits::TopLevelASType;
/// \param pRefCounters - reference counters object that controls the lifetime of this device context.
/// \param pRenderDevice - render device.
@@ -253,8 +255,10 @@ protected:
void DvpVerifyRenderTargets()const;
void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const;
- bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const;
- bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
#else
bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
@@ -268,8 +272,10 @@ protected:
void DvpVerifyRenderTargets()const {}
void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {}
- bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
- bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
+ bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;}
// clang-format on
#endif
@@ -279,8 +285,6 @@ protected:
bool CopyTLAS(const CopyTLASAttribs& Attribs, int);
bool TraceRays(const TraceRaysAttribs& Attribs, int);
- static const Uint32 TLASInstanceDataSize = 64; // bytes
-
/// Strong reference to the device.
RefCntAutoPtr<DeviceImplType> m_pDevice;
@@ -1803,15 +1807,19 @@ template <typename BaseInterface, typename ImplementationTraits>
void DeviceContextBase<BaseInterface, ImplementationTraits>::
DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
{
- DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null");
+ DEV_CHECK_ERR(Barrier.pResource != nullptr, "pResource must not be null");
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
- if (Barrier.pTexture)
+
+ RefCntAutoPtr<ITexture> pTexture{Barrier.pResource, IID_Texture};
+ RefCntAutoPtr<IBuffer> pBuffer{Barrier.pResource, IID_Buffer};
+
+ if (pTexture)
{
- const auto& TexDesc = Barrier.pTexture->GetDesc();
+ const auto& TexDesc = pTexture->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'");
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN,
"The state of texture '", TexDesc.Name,
"' is unknown to the engine and is not explicitly specified in the barrier");
@@ -1842,17 +1850,17 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>::
"Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
}
}
- else if (Barrier.pBuffer)
+ else if (pBuffer)
{
- const auto& BuffDesc = Barrier.pBuffer->GetDesc();
+ const auto& BuffDesc = pBuffer->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'");
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'");
}
else
{
- // AZ TODO: global barrier
+ UNEXPECTED("unsupported resource type");
}
if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
@@ -1896,6 +1904,35 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return true;
}
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyBLASState(const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+{
+ if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState))
+ {
+ LOG_ERROR_MESSAGE(OperationName, " requires BLAS '", BLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
+ " state. Actual BLAS state: ", GetResourceStateString(BLAS.GetState()),
+ ". Use appropriate state transiton flags or explicitly transition the BLAS using IDeviceContext::TransitionResourceStates() method.");
+ return false;
+ }
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyTLASState(const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+{
+ if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState))
+ {
+ LOG_ERROR_MESSAGE(OperationName, " requires TLAS '", TLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState),
+ " state. Actual TLAS state: ", GetResourceStateString(TLAS.GetState()),
+ ". Use appropriate state transiton flags or explicitly transition the TLAS using IDeviceContext::TransitionResourceStates() method.");
+ return false;
+ }
+
+ return true;
+}
#endif // DILIGENT_DEVELOPMENT
template <typename BaseInterface, typename ImplementationTraits>
@@ -1913,7 +1950,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
- if ((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr))
+ if (!((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)))
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined");
return false;
@@ -1931,39 +1968,93 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
{
- if (Attribs.pTriangleData[i].pVertexBuffer == nullptr)
+ const auto& tri = Attribs.pTriangleData[i];
+ const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount;
+ const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount;
+
+ if (tri.VertexValueType >= VT_NUM_TYPES)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type");
+ return false;
+ }
+
+ if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3");
+ return false;
+ }
+
+ if (tri.VertexStride < VertexSize)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexStride must be at least ", VertexSize, " bytes");
+ return false;
+ }
+
+ if (tri.pVertexBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must not be null");
return false;
}
- if ((Attribs.pTriangleData[i].pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
- if (Attribs.pTriangleData[i].IndexType != VT_UNDEFINED)
+ if (tri.VertexOffset + VertexDataSize > tri.pVertexBuffer->GetDesc().uiSizeInBytes)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer is too small for specified VertexStride and VertexCount");
+ return false;
+ }
+
+ if (tri.IndexType != VT_UNDEFINED)
{
- if (Attribs.pTriangleData[i].pIndexBuffer == nullptr)
+ if (tri.IndexType != VT_UINT16 && tri.IndexType != VT_UINT32)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must not be VT_UNDEFINED, VT_UINT16 or VT_UINT32");
+ return false;
+ }
+
+ if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0))
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid");
+ return false;
+ }
+
+ if (tri.pIndexBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null");
return false;
}
- if ((Attribs.pTriangleData[i].pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+
+ const Uint32 IndexDataSize = tri.IndexCount * GetValueSize(tri.IndexType);
+ if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount");
+ return false;
+ }
+ }
+ else
+ {
+ VERIFY(tri.pIndexBuffer == nullptr,
+ "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED");
+ VERIFY(tri.IndexCount == 0,
+ "IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be zero if IndexType is VT_UNDEFINED");
}
- // AZ TODO: check AllosTransforms flags in create info
- if (Attribs.pTriangleData[i].pTransformBuffer != nullptr)
+ if (tri.pTransformBuffer != nullptr)
{
- if ((Attribs.pTriangleData[i].pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag");
return false;
@@ -1973,13 +2064,22 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
{
- if (Attribs.pBoxData[i].pBoxBuffer == nullptr)
+ const auto& box = Attribs.pBoxData[i];
+ const Uint32 BoxSize = sizeof(float) * 6;
+
+ if (box.BoxStride < BoxSize)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxStride must be at least ", BoxSize, " bytes");
+ return false;
+ }
+
+ if (box.pBoxBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must not be null");
return false;
}
- if ((Attribs.pBoxData[i].pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
+ if ((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must be created with BIND_RAY_TRACING flag");
return false;
@@ -2019,6 +2119,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
return true;
}
@@ -2044,18 +2145,19 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- if (Attribs.pInstancesBuffer == nullptr)
+ if (Attribs.pInstanceBuffer == nullptr)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must not be null");
return false;
}
- if (Attribs.HitShadersPerInstance > 0)
+ if (Attribs.HitShadersPerInstance == 0)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0");
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
const auto& TLASDesc = Attribs.pTLAS->GetDesc();
if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount)
@@ -2064,14 +2166,16 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
return false;
}
- const auto& InstDesc = Attribs.pInstancesBuffer->GetDesc();
- const size_t InstDataSize = Attribs.InstanceCount * TLASInstanceDataSize;
+ const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
+ const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE;
+ Uint32 AutoOffsetCounter = 0;
// calculate instance data size
for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
{
- VERIFY_EXPR((Attribs.pInstances[i].customId & 0x00FFFFFF) == 0);
- VERIFY_EXPR((Attribs.pInstances[i].contributionToHitGroupIndex & 0x00FFFFFF) == 0);
+ VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0);
+ VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
+ (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0);
if (Attribs.pInstances[i].InstanceName == nullptr)
{
@@ -2084,15 +2188,24 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null");
return false;
}
+
+ if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+ ++AutoOffsetCounter;
+ }
+
+ if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not");
+ return false;
}
- if (Attribs.InstancesBufferOffset > InstDesc.uiSizeInBytes)
+ if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes)
{
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstancesBufferOffset is greater than buffer size");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceBufferOffset is greater than buffer size");
return false;
}
- if (InstDesc.uiSizeInBytes - Attribs.InstancesBufferOffset > InstDataSize)
+ if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset > InstDataSize)
{
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ...");
return false;
@@ -2123,6 +2236,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA
LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
return true;
}
@@ -2142,6 +2256,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2192,13 +2307,15 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy
return false;
}
}
- return true;
}
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
+
+ return true;
}
template <typename BaseInterface, typename ImplementationTraits>
@@ -2216,6 +2333,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
if (Attribs.Mode == COPY_AS_MODE_CLONE)
{
auto& SrcDesc = Attribs.pSrc->GetDesc();
@@ -2227,13 +2345,15 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc");
return false;
}
- return true;
}
else
{
LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode");
return false;
}
+#endif // DILIGENT_DEVELOPMENT
+
+ return true;
}
template <typename BaseInterface, typename ImplementationTraits>
diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
index cce40b11..155ecb66 100644
--- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp
@@ -47,7 +47,7 @@ namespace Diligent
/// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk).
/// \tparam RenderDeviceImplType - type of the render device implementation
/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl)
-template <class BaseInterface, class RenderDeviceImplType>
+template <class BaseInterface, class PipelineStateImplType, class RenderDeviceImplType>
class ShaderBindingTableBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, ShaderBindingTableDesc>
{
public:
@@ -71,6 +71,100 @@ public:
{
}
+ void BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride);
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ const Uint32 Offset = MissIndex * this->m_ShaderRecordStride;
+ this->m_MissShadersRecord.resize(std::max<size_t>(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindHitGroup(ITopLevelAS* pTLAS,
+ const char* InstanceName,
+ const char* GeometryName,
+ Uint32 RayOffsetInHitGroupIndex,
+ const char* ShaderGroupName,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR(pTLAS != nullptr);
+ VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
+ VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY);
+
+ const auto Desc = pTLAS->GetInstanceDesc(InstanceName);
+ VERIFY_EXPR(Desc.pBLAS != nullptr);
+
+ const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex;
+ const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName);
+ const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 Offset = Index * this->m_ShaderRecordStride;
+
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
+ void BindHitGroups(ITopLevelAS* pTLAS,
+ const char* InstanceName,
+ Uint32 RayOffsetInHitGroupIndex,
+ const char* ShaderGroupName,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+ VERIFY_EXPR(pTLAS != nullptr);
+ VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance);
+ VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY ||
+ pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_INSTANCE);
+
+ const auto Desc = pTLAS->GetInstanceDesc(InstanceName);
+ VERIFY_EXPR(Desc.pBLAS != nullptr);
+
+ const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex;
+ const auto& GeometryDesc = Desc.pBLAS->GetDesc();
+ const Uint32 GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount;
+ const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex;
+ PipelineStateImplType* pPSO = ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO);
+
+ this->m_HitGroupsRecord.resize(std::max<size_t>(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride));
+
+ for (Uint32 i = 0; i < GeometryCount; ++i)
+ {
+ Uint32 Offset = (BeginIndex + i) * this->m_ShaderRecordStride;
+ pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride);
+ }
+ this->m_Changed = true;
+ }
+
+ void BindCallableShader(const char* ShaderGroupName,
+ Uint32 CallableIndex,
+ const void* Data,
+ Uint32 DataSize) override final
+ {
+ VERIFY(Data == nullptr && DataSize == 0, "not supported yet");
+
+ const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride;
+ this->m_CallableShadersRecord.resize(std::max<size_t>(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride));
+
+ ValidatedCast<PipelineStateImplType>(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride);
+ this->m_Changed = true;
+ }
+
protected:
static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc)
{
@@ -92,10 +186,13 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase)
protected:
- StringPool m_StringPool;
+ std::vector<Uint8> m_RayGenShaderRecord;
+ std::vector<Uint8> m_MissShadersRecord;
+ std::vector<Uint8> m_CallableShadersRecord;
+ std::vector<Uint8> m_HitGroupsRecord;
- std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex;
- std::unordered_map<HashMapStringKey, TLASInstanceDesc, HashMapStringKey::Hasher> m_Instances;
+ Uint32 m_ShaderRecordStride = 0;
+ bool m_Changed = true;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
index 2d2049af..ab56636f 100644
--- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp
@@ -71,7 +71,7 @@ public:
{
}
- void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount)
+ void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance)
{
m_Instances.clear();
m_StringPool.Release();
@@ -84,22 +84,31 @@ public:
m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
+ Uint32 InstanceOffset = 0;
+
for (Uint32 i = 0; i < InstanceCount; ++i)
{
auto& inst = pInstances[i];
const char* NameCopy = m_StringPool.CopyString(inst.InstanceName);
InstanceDesc Desc = {};
- Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex;
+ Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex;
Desc.pBLAS = inst.pBLAS;
+ if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+ {
+ Desc.ContributionToHitGroupIndex = InstanceOffset;
+ auto& BLASDesc = Desc.pBLAS->GetDesc();
+ InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance;
+ }
+
bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second;
if (!IsUniqueName)
LOG_ERROR_AND_THROW("Instance name must be unique!");
}
}
- virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override
+ virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final
{
VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
@@ -108,7 +117,7 @@ public:
auto iter = m_Instances.find(Name);
if (iter != m_Instances.end())
{
- Result.ContributionToHitGroupIndex = iter->second.contributionToHitGroupIndex;
+ Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex;
Result.pBLAS = iter->second.pBLAS;
}
else
@@ -119,6 +128,28 @@ public:
return Result;
}
+ virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final
+ {
+ this->m_State = State;
+ }
+
+ virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final
+ {
+ return this->m_State;
+ }
+
+ bool IsInKnownState() const
+ {
+ return this->m_State != RESOURCE_STATE_UNKNOWN;
+ }
+
+ bool CheckState(RESOURCE_STATE State) const
+ {
+ VERIFY((State & (State - 1)) == 0, "Single state is expected");
+ VERIFY(IsInKnownState(), "TLAS state is unknown");
+ return (this->m_State & State) == State;
+ }
+
protected:
static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc)
{
@@ -141,14 +172,15 @@ protected:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase)
protected:
+ RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
+
+ StringPool m_StringPool;
+
struct InstanceDesc
{
- Uint32 contributionToHitGroupIndex = 0;
+ Uint32 ContributionToHitGroupIndex = 0;
mutable RefCntAutoPtr<IBottomLevelAS> pBLAS;
};
-
- StringPool m_StringPool;
-
std::unordered_map<HashMapStringKey, InstanceDesc, HashMapStringKey::Hasher> m_Instances;
};
diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
index cc8c4aec..264720ff 100644
--- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
@@ -200,6 +200,25 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject)
/// AZ TODO
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
+
+ /// Returns native acceleration structure handle specific to the underlying graphics API
+
+ /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n
+ /// VkAccelerationStructureKHR handle, for Vulkan implementation
+ VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE;
+
+ /// Sets the acceleration structure usage state.
+
+ /// \note This method does not perform state transition, but
+ /// resets the internal acceleration structure state to the given value.
+ /// This method should be used after the application finished
+ /// manually managing the acceleration structure state and wants to hand over
+ /// state management back to the engine.
+ VIRTUAL void METHOD(SetState)(THIS_
+ RESOURCE_STATE State) PURE;
+
+ /// Returns the internal acceleration structure state
+ VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -209,7 +228,11 @@ DILIGENT_END_INTERFACE
// clang-format off
-# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__)
+# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__)
+# define IBottomLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(BottomLevelAS, GetScratchBufferSizes, This)
+# define IBottomLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(BottomLevelAS, GetNativeHandle, This)
+# define IBottomLevelAS_SetState(This, ...) CALL_IFACE_METHOD(BottomLevelAS, SetState, This, __VA_ARGS__)
+# define IBottomLevelAS_GetState(This) CALL_IFACE_METHOD(BottomLevelAS, GetState, This)
// clang-format on
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index a294b066..04ff3030 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -809,7 +809,7 @@ struct BLASBuildTriangleData
Uint32 IndexOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- Uint32 IndexCount DEFAULT_INITIALIZER(0);
+ Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ?
/// AZ TODO
VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration
@@ -872,6 +872,9 @@ struct BLASBuildAttribs
RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
+ RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// AZ TODO
BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
@@ -903,6 +906,9 @@ typedef struct BLASBuildAttribs BLASBuildAttribs;
/// AZ TODO
static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u;
+/// AZ TODO
+static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64;
+
/// AZ TODO
struct TLASBuildInstanceData
@@ -917,7 +923,7 @@ struct TLASBuildInstanceData
float Transform[3][4] DEFAULT_INITIALIZER({});
/// AZ TODO
- Uint32 customId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
+ Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL
/// AZ TODO
RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE);
@@ -926,7 +932,7 @@ struct TLASBuildInstanceData
Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0
/// AZ TODO
- Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll()
+ Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll()
#if DILIGENT_CPP_INTERFACE
/// AZ TODO
@@ -940,37 +946,40 @@ typedef struct TLASBuildInstanceData TLASBuildInstanceData;
struct TLASBuildAttribs
{
/// AZ TODO
- ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
+ ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
- TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr);
+ RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// AZ TODO
+ TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 InstanceCount DEFAULT_INITIALIZER(0);
+ Uint32 InstanceCount DEFAULT_INITIALIZER(0);
/// AZ TODO
- IBuffer* pInstancesBuffer DEFAULT_INITIALIZER(nullptr);
+ IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 InstancesBufferOffset DEFAULT_INITIALIZER(0);
+ Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
/// AZ TODO
- Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
+ Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1);
/// AZ TODO
- IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
+ IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr);
/// AZ TODO
- Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
+ Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0);
/// AZ TODO
- RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+ RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
#if DILIGENT_CPP_INTERFACE
/// AZ TODO
@@ -1048,6 +1057,124 @@ struct TraceRaysAttribs
typedef struct TraceRaysAttribs TraceRaysAttribs;
+static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU;
+static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU;
+
+/// Resource state transition barrier description
+struct StateTransitionDesc
+{
+ /// Resource to transition.
+ /// Can be ITexture, IBuffer, IBottomLevelAS, ITopLevelAS.
+ struct IDeviceObject* pResource DEFAULT_INITIALIZER(nullptr);
+
+ /// When transitioning a texture, first mip level of the subresource range to transition.
+ Uint32 FirstMipLevel DEFAULT_INITIALIZER(0);
+
+ /// When transitioning a texture, number of mip levels of the subresource range to transition.
+ Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS);
+
+ /// When transitioning a texture, first array slice of the subresource range to transition.
+ Uint32 FirstArraySlice DEFAULT_INITIALIZER(0);
+
+ /// When transitioning a texture, number of array slices of the subresource range to transition.
+ Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES);
+
+ /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN,
+ /// internal resource state will be used, which must be defined in this case.
+ RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
+
+ /// Resource state after transition.
+ RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
+
+ /// State transition type, see Diligent::STATE_TRANSITION_TYPE.
+
+ /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS),
+ /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE.
+ STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE);
+
+ /// If set to true, the internal resource state will be set to NewState and the engine
+ /// will be able to take over the resource state management. In this case it is the
+ /// responsibility of the application to make sure that all subresources are indeed in
+ /// designated state.
+ /// If set to false, internal resource state will be unchanged.
+ /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false.
+ bool UpdateResourceState DEFAULT_INITIALIZER(false);
+
+#if DILIGENT_CPP_INTERFACE
+ StateTransitionDesc()noexcept{}
+
+ StateTransitionDesc(ITexture* _pTexture,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ Uint32 _FirstMipLevel = 0,
+ Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS,
+ Uint32 _FirstArraySlice = 0,
+ Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES,
+ STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE,
+ bool _UpdateState = false)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pTexture)},
+ FirstMipLevel {_FirstMipLevel },
+ MipLevelsCount {_MipLevelsCount },
+ FirstArraySlice {_FirstArraySlice},
+ ArraySliceCount {_ArraySliceCount},
+ OldState {_OldState },
+ NewState {_NewState },
+ TransitionType {_TransitionType },
+ UpdateResourceState {_UpdateState }
+ {}
+
+ StateTransitionDesc(ITexture* _pTexture,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ StateTransitionDesc
+ {
+ _pTexture,
+ _OldState,
+ _NewState,
+ 0,
+ REMAINING_MIP_LEVELS,
+ 0,
+ REMAINING_ARRAY_SLICES,
+ STATE_TRANSITION_TYPE_IMMEDIATE,
+ _UpdateState
+ }
+ {}
+
+ StateTransitionDesc(IBuffer* _pBuffer,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pBuffer)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+
+ StateTransitionDesc(IBottomLevelAS* _pBLAS,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pBLAS)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+
+ StateTransitionDesc(ITopLevelAS* _pTLAS,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ bool _UpdateState)noexcept :
+ pResource {static_cast<IDeviceObject*>(_pTLAS)},
+ OldState {_OldState },
+ NewState {_NewState },
+ UpdateResourceState {_UpdateState}
+ {}
+#endif
+};
+typedef struct StateTransitionDesc StateTransitionDesc;
+
+
#define DILIGENT_INTERFACE_NAME IDeviceContext
#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 10a84f1d..093039bd 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -41,9 +41,6 @@
/// Graphics engine namespace
DILIGENT_BEGIN_NAMESPACE(Diligent)
-struct ITexture;
-struct IBuffer;
-
/// Value type
/// This enumeration describes value type. It is used by
@@ -86,7 +83,7 @@ DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32)
BIND_UNORDERED_ACCESS = 0x80L, ///< A buffer or a texture can be bound as an unordered access view
BIND_INDIRECT_DRAW_ARGS = 0x100L, ///< A buffer can be bound as the source buffer for indirect draw commands
BIND_INPUT_ATTACHMENT = 0x200L, ///< A texture can be used as render pass input attachment
- BIND_RAY_TRACING = 0x400L, ///< AZ TODO
+ BIND_RAY_TRACING = 0x400L, ///< A buffer can be used as scratch buffer for acceleration structure building.
BIND_FLAGS_LAST = 0x400L
};
DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS)
@@ -1253,16 +1250,22 @@ typedef struct DisplayModeAttribs DisplayModeAttribs;
DILIGENT_TYPED_ENUM(SWAP_CHAIN_USAGE_FLAGS, Uint32)
{
/// No allowed usage
- SWAP_CHAIN_USAGE_NONE = 0x00L,
+ SWAP_CHAIN_USAGE_NONE = 0x00L,
/// Swap chain can be used as render target ouput
- SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L,
+ SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L,
/// Swap chain images can be used as shader inputs
- SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L,
+ SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L,
/// Swap chain images can be used as source of copy operation
- SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L
+ SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L,
+
+ /// Swap chain images will define an unordered access view that will be used
+ /// for unordered read/write operations from the shaders
+ SWAP_CHAIN_USAGE_UNORDERED_ACCESS = 0x08L,
+
+ SWAP_CHAIN_USAGE_LAST = SWAP_CHAIN_USAGE_UNORDERED_ACCESS,
};
DEFINE_FLAG_ENUM_OPERATORS(SWAP_CHAIN_USAGE_FLAGS)
@@ -2720,10 +2723,12 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32)
/// The resource is used for present
RESOURCE_STATE_PRESENT = 0x10000,
- RESOURCE_STATE_BUILD_AS = 0x20000,
- RESOURCE_STATE_RAY_TRACING = 0x40000,
+ /// AZ TODO
+ RESOURCE_STATE_BUILD_AS_READ = 0x20000,
+ RESOURCE_STATE_BUILD_AS_WRITE = 0x40000,
+ RESOURCE_STATE_RAY_TRACING = 0x80000,
- RESOURCE_STATE_MAX_BIT = 0x40000,
+ RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING,
RESOURCE_STATE_GENERIC_READ = RESOURCE_STATE_VERTEX_BUFFER |
RESOURCE_STATE_CONSTANT_BUFFER |
@@ -2753,105 +2758,4 @@ DILIGENT_TYPED_ENUM(STATE_TRANSITION_TYPE, Uint8)
STATE_TRANSITION_TYPE_END
};
-static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU;
-static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU;
-
-/// Resource state transition barrier description
-struct StateTransitionDesc
-{
- /// Texture to transition.
- /// \note Exactly one of pTexture or pBuffer must be non-null.
- struct ITexture* pTexture DEFAULT_INITIALIZER(nullptr);
-
- /// Buffer to transition.
- /// \note Exactly one of pTexture or pBuffer must be non-null.
- struct IBuffer* pBuffer DEFAULT_INITIALIZER(nullptr);
-
- /// When transitioning a texture, first mip level of the subresource range to transition.
- Uint32 FirstMipLevel DEFAULT_INITIALIZER(0);
-
- /// When transitioning a texture, number of mip levels of the subresource range to transition.
- Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS);
-
- /// When transitioning a texture, first array slice of the subresource range to transition.
- Uint32 FirstArraySlice DEFAULT_INITIALIZER(0);
-
- /// When transitioning a texture, number of array slices of the subresource range to transition.
- Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES);
-
- /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN,
- /// internal resource state will be used, which must be defined in this case.
- RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
-
- /// Resource state after transition.
- RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN);
-
- /// State transition type, see Diligent::STATE_TRANSITION_TYPE.
-
- /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS),
- /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE.
- STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE);
-
- /// If set to true, the internal resource state will be set to NewState and the engine
- /// will be able to take over the resource state management. In this case it is the
- /// responsibility of the application to make sure that all subresources are indeed in
- /// designated state.
- /// If set to false, internal resource state will be unchanged.
- /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false.
- bool UpdateResourceState DEFAULT_INITIALIZER(false);
-
-#if DILIGENT_CPP_INTERFACE
- StateTransitionDesc()noexcept{}
-
- StateTransitionDesc(ITexture* _pTexture,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- Uint32 _FirstMipLevel = 0,
- Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS,
- Uint32 _FirstArraySlice = 0,
- Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES,
- STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE,
- bool _UpdateState = false)noexcept :
- pTexture {_pTexture },
- FirstMipLevel {_FirstMipLevel },
- MipLevelsCount {_MipLevelsCount },
- FirstArraySlice {_FirstArraySlice},
- ArraySliceCount {_ArraySliceCount},
- OldState {_OldState },
- NewState {_NewState },
- TransitionType {_TransitionType },
- UpdateResourceState {_UpdateState }
- {}
-
- StateTransitionDesc(ITexture* _pTexture,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- bool _UpdateState)noexcept :
- StateTransitionDesc
- {
- _pTexture,
- _OldState,
- _NewState,
- 0,
- REMAINING_MIP_LEVELS,
- 0,
- REMAINING_ARRAY_SLICES,
- STATE_TRANSITION_TYPE_IMMEDIATE,
- _UpdateState
- }
- {}
-
- StateTransitionDesc(IBuffer* _pBuffer,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- bool _UpdateState)noexcept :
- pBuffer {_pBuffer },
- OldState {_OldState },
- NewState {_NewState },
- UpdateResourceState {_UpdateState}
- {}
-#endif
-};
-typedef struct StateTransitionDesc StateTransitionDesc;
-
DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h
index e45dc703..3afa83f2 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -223,6 +223,17 @@ struct RayTracingGeneralShaderGroup
/// AZ TODO
IShader* pShader DEFAULT_INITIALIZER(nullptr);
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingGeneralShaderGroup() noexcept
+ {}
+
+ RayTracingGeneralShaderGroup(const char* _Name,
+ IShader* _pShader) noexcept:
+ Name {_Name },
+ pShader{_pShader}
+ {}
+#endif
};
typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup;
@@ -237,6 +248,19 @@ struct RayTracingTriangleHitShaderGroup
/// AZ TODO
IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingTriangleHitShaderGroup() noexcept
+ {}
+
+ RayTracingTriangleHitShaderGroup(const char* _Name,
+ IShader* _pClosestHitShader,
+ IShader* _pAnyHitShader = nullptr) noexcept:
+ Name {_Name },
+ pClosestHitShader{_pClosestHitShader},
+ pAnyHitShader {_pAnyHitShader }
+ {}
+#endif
};
typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup;
@@ -254,6 +278,21 @@ struct RayTracingProceduralHitShaderGroup
/// AZ TODO
IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null
+
+#if DILIGENT_CPP_INTERFACE
+ RayTracingProceduralHitShaderGroup() noexcept
+ {}
+
+ RayTracingProceduralHitShaderGroup(const char* _Name,
+ IShader* _pIntersectionShader,
+ IShader* _pClosestHitShader = nullptr,
+ IShader* _pAnyHitShader = nullptr) noexcept:
+ Name {_Name },
+ pIntersectionShader{_pIntersectionShader},
+ pClosestHitShader {_pClosestHitShader },
+ pAnyHitShader {_pAnyHitShader }
+ {}
+#endif
};
typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup;
diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
index 514f9b7c..71fa25e4 100644
--- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
+++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h
@@ -157,10 +157,10 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject)
/// AZ TODO
VIRTUAL void METHOD(BindCallableShader)(THIS_
- Uint32 Index,
- const char* ShaderName,
- const void* Data DEFAULT_INITIALIZER(nullptr),
- Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE;
+ const char* ShaderGroupName,
+ Uint32 CallableIndex,
+ const void* Data DEFAULT_INITIALIZER(nullptr),
+ Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE;
/// AZ TODO
VIRTUAL void METHOD(BindAll)(THIS_
diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h
index 0e427864..630f8ddd 100644
--- a/Graphics/GraphicsEngine/interface/TopLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h
@@ -120,6 +120,25 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject)
/// AZ TODO
VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE;
+
+ /// Returns native acceleration structure handle specific to the underlying graphics API
+
+ /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n
+ /// VkAccelerationStructureKHR handle, for Vulkan implementation
+ VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE;
+
+ /// Sets the acceleration structure usage state.
+
+ /// \note This method does not perform state transition, but
+ /// resets the internal acceleration structure state to the given value.
+ /// This method should be used after the application finished
+ /// manually managing the acceleration structure state and wants to hand over
+ /// state management back to the engine.
+ VIRTUAL void METHOD(SetState)(THIS_
+ RESOURCE_STATE State) PURE;
+
+ /// Returns the internal acceleration structure state
+ VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -129,7 +148,11 @@ DILIGENT_END_INTERFACE
// clang-format off
-# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__)
+# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__)
+# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This)
+# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This)
+# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__)
+# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This)
// clang-format on
diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp
index aab770fd..5b72389a 100644
--- a/Graphics/GraphicsEngine/src/BufferBase.cpp
+++ b/Graphics/GraphicsEngine/src/BufferBase.cpp
@@ -45,7 +45,7 @@ namespace Diligent
void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps)
{
- static_assert(BIND_FLAGS_LAST == 0x400L, "AZ TODO");
+ static_assert(BIND_FLAGS_LAST == 0x400L, "Please update this function to handle the new bind flags");
constexpr Uint32 AllowedBindFlags =
BIND_VERTEX_BUFFER |
diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
index 6b613458..5e69da8e 100644
--- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
@@ -41,6 +41,8 @@
#include "FramebufferD3D11Impl.hpp"
#include "RenderPassD3D11Impl.hpp"
#include "DisjointQueryPool.hpp"
+#include "BottomLevelASBase.hpp"
+#include "TopLevelASBase.hpp"
#ifdef DILIGENT_DEBUG
# define VERIFY_CONTEXT_BINDINGS
@@ -58,6 +60,8 @@ struct DeviceContextD3D11ImplTraits
using QueryType = QueryD3D11Impl;
using FramebufferType = FramebufferD3D11Impl;
using RenderPassType = RenderPassD3D11Impl;
+ using BottomLevelASType = BottomLevelASBase<IBottomLevelAS, RenderDeviceD3D11Impl>;
+ using TopLevelASType = TopLevelASBase<ITopLevelAS, RenderDeviceD3D11Impl>;
};
/// Device context implementation in Direct3D11 backend.
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index 9286f3f8..e42dd2d0 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -2157,7 +2157,6 @@ void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, State
#ifdef DILIGENT_DEVELOPMENT
DvpVerifyStateTransitionDesc(Barrier);
#endif
- DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null");
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
@@ -2168,28 +2167,28 @@ void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, State
}
VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
- if (Barrier.pTexture)
+ RefCntAutoPtr<TextureBaseD3D11> pTexture{Barrier.pResource, IID_TextureD3D11};
+ if (pTexture)
{
- auto* pTextureD3D11Impl = ValidatedCast<TextureBaseD3D11>(Barrier.pTexture);
- auto OldState = Barrier.OldState;
+ auto OldState = Barrier.OldState;
if (OldState == RESOURCE_STATE_UNKNOWN)
{
- if (pTextureD3D11Impl->IsInKnownState())
+ if (pTexture->IsInKnownState())
{
- OldState = pTextureD3D11Impl->GetState();
+ OldState = pTexture->GetState();
}
else
{
- LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTextureD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
+ LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTexture->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
continue;
}
}
else
{
- if (pTextureD3D11Impl->IsInKnownState() && pTextureD3D11Impl->GetState() != OldState)
+ if (pTexture->IsInKnownState() && pTexture->GetState() != OldState)
{
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTextureD3D11Impl->GetState()), " of texture '",
- pTextureD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTexture->GetState()), " of texture '",
+ pTexture->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
" specified by the barrier");
}
}
@@ -2197,52 +2196,53 @@ void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, State
if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
{
DEV_CHECK_ERR((Barrier.NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) == 0, "Unordered access state is not compatible with any input state");
- UnbindTextureFromInput(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
+ UnbindTextureFromInput(pTexture, pTexture->GetD3D11Texture());
}
if ((Barrier.NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) != 0)
{
if ((OldState & RESOURCE_STATE_RENDER_TARGET) != 0)
- UnbindTextureFromRenderTarget(pTextureD3D11Impl);
+ UnbindTextureFromRenderTarget(pTexture);
if ((OldState & RESOURCE_STATE_DEPTH_WRITE) != 0)
- UnbindTextureFromDepthStencil(pTextureD3D11Impl);
+ UnbindTextureFromDepthStencil(pTexture);
if ((OldState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
{
- UnbindResourceFromUAV(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
- pTextureD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ UnbindResourceFromUAV(pTexture, pTexture->GetD3D11Texture());
+ pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
}
}
if (Barrier.UpdateResourceState)
{
- pTextureD3D11Impl->SetState(Barrier.NewState);
+ pTexture->SetState(Barrier.NewState);
}
+ continue;
}
- else
+
+ RefCntAutoPtr<BufferD3D11Impl> pBuffer{Barrier.pResource, IID_BufferD3D11};
+ if (pBuffer)
{
- VERIFY_EXPR(Barrier.pBuffer);
- auto* pBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(Barrier.pBuffer);
- auto OldState = Barrier.OldState;
+ auto OldState = Barrier.OldState;
if (OldState == RESOURCE_STATE_UNKNOWN)
{
- if (pBufferD3D11Impl->IsInKnownState())
+ if (pBuffer->IsInKnownState())
{
- OldState = pBufferD3D11Impl->GetState();
+ OldState = pBuffer->GetState();
}
else
{
- LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBufferD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
+ LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBuffer->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
continue;
}
}
else
{
- if (pBufferD3D11Impl->IsInKnownState() && pBufferD3D11Impl->GetState() != OldState)
+ if (pBuffer->IsInKnownState() && pBuffer->GetState() != OldState)
{
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBufferD3D11Impl->GetState()), " of buffer '",
- pBufferD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBuffer->GetState()), " of buffer '",
+ pBuffer->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
" specified by the barrier");
}
}
@@ -2250,19 +2250,22 @@ void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, State
if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
{
DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state");
- UnbindBufferFromInput(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
+ UnbindBufferFromInput(pBuffer, pBuffer->m_pd3d11Buffer);
}
if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0)
{
- UnbindResourceFromUAV(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
+ UnbindResourceFromUAV(pBuffer, pBuffer->m_pd3d11Buffer);
}
if (Barrier.UpdateResourceState)
{
- pBufferD3D11Impl->SetState(Barrier.NewState);
+ pBuffer->SetState(Barrier.NewState);
}
+ continue;
}
+
+ UNEXPECTED("unsupported resource type");
}
}
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt
index 9941b62b..611bcbda 100644
--- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt
+++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt
@@ -37,6 +37,9 @@ set(INCLUDE
include/SwapChainD3D12Impl.hpp
include/TextureD3D12Impl.hpp
include/TextureViewD3D12Impl.hpp
+ include/BottomLevelASD3D12Impl.hpp
+ include/TopLevelASD3D12Impl.hpp
+ include/ShaderBindingTableD3D12Impl.hpp
)
set(INTERFACE
@@ -55,6 +58,9 @@ set(INTERFACE
interface/SwapChainD3D12.h
interface/TextureD3D12.h
interface/TextureViewD3D12.h
+ interface/BottomLevelASD3D12.h
+ interface/TopLevelASD3D12.h
+ interface/ShaderBindingTableD3D12.h
)
@@ -89,6 +95,9 @@ set(SRC
src/SwapChainD3D12Impl.cpp
src/TextureD3D12Impl.cpp
src/TextureViewD3D12Impl.cpp
+ src/BottomLevelASD3D12Impl.cpp
+ src/TopLevelASD3D12Impl.cpp
+ src/ShaderBindingTableD3D12Impl.cpp
)
if(PLATFORM_WIN32)
diff --git a/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp
new file mode 100644
index 00000000..b631bdcc
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::BottomLevelASD3D12Impl class
+
+#include "BottomLevelASD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "BottomLevelASBase.hpp"
+#include "D3D12ResourceBase.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+
+namespace Diligent
+{
+
+/// Bottom-level acceleration structure object implementation in Direct3D12 backend.
+class BottomLevelASD3D12Impl final : public BottomLevelASBase<IBottomLevelASD3D12, RenderDeviceD3D12Impl>, public D3D12ResourceBase
+{
+public:
+ using TBottomLevelASBase = BottomLevelASBase<IBottomLevelASD3D12, RenderDeviceD3D12Impl>;
+
+ BottomLevelASD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const BottomLevelASDesc& Desc,
+ bool bIsDeviceInternal = false);
+ ~BottomLevelASD3D12Impl();
+
+ virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
+
+ /// Implementation of IBottomLevelAS::GetScratchBufferSizes() in DirectX 12 backend.
+ virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
+
+ /// Implementation of IBottomLevelASD3D12::GetD3D12BLAS().
+ virtual ID3D12Resource* DILIGENT_CALL_TYPE GetD3D12BLAS() override final { return GetD3D12Resource(); }
+
+ /// Implementation of IBottomLevelAS::GetNativeHandle() in Direct3D12 backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { return GetD3D12BLAS(); }
+
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress()
+ {
+ return GetD3D12Resource()->GetGPUVirtualAddress();
+ }
+
+private:
+ ScratchBufferSizes m_ScratchSize;
+};
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp
index ab90dfe7..ad3027a8 100644
--- a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp
@@ -103,6 +103,12 @@ public:
}
}
+ __forceinline D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress()
+ {
+ VERIFY_EXPR(m_Desc.Usage != USAGE_DYNAMIC);
+ return GetD3D12Resource()->GetGPUVirtualAddress();
+ }
+
D3D12_CPU_DESCRIPTOR_HANDLE GetCBVHandle() { return m_CBVDescriptorAllocation.GetCpuHandle(); }
private:
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp
index 94f74933..511f1a03 100644
--- a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp
@@ -34,6 +34,8 @@
#include "TextureViewD3D12.h"
#include "TextureD3D12.h"
#include "BufferD3D12.h"
+#include "BottomLevelASD3D12.h"
+#include "TopLevelASD3D12.h"
#include "DescriptorHeap.hpp"
namespace Diligent
@@ -114,6 +116,8 @@ public:
void TransitionResource(ITextureD3D12* pTexture, RESOURCE_STATE NewState);
void TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE NewState);
+ void TransitionResource(IBottomLevelASD3D12* pBLAS, RESOURCE_STATE NewState);
+ void TransitionResource(ITopLevelASD3D12* pTLAS, RESOURCE_STATE NewState);
void TransitionResource(const StateTransitionDesc& Barrier);
//void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
@@ -238,8 +242,25 @@ protected:
Uint32 m_MaxInterfaceVer = 0;
};
+class ComputeContext : public CommandContext
+{
+public:
+ void SetComputeRootSignature(ID3D12RootSignature* pRootSig)
+ {
+ if (pRootSig != m_pCurComputeRootSignature)
+ {
+ m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig);
+ }
+ }
-class GraphicsContext : public CommandContext
+ void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1)
+ {
+ FlushResourceBarriers();
+ m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ);
+ }
+};
+
+class GraphicsContext : public ComputeContext
{
public:
void ClearRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV, const float* Color)
@@ -254,7 +275,7 @@ public:
m_pCommandList->ClearDepthStencilView(DSV, ClearFlags, Depth, Stencil, 0, nullptr);
}
- void SetRootSignature(ID3D12RootSignature* pRootSig)
+ void SetGraphicsRootSignature(ID3D12RootSignature* pRootSig)
{
if (pRootSig != m_pCurGraphicsRootSignature)
{
@@ -291,47 +312,6 @@ public:
}
}
- void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants)
- {
- m_pCommandList->SetGraphicsRoot32BitConstants(RootIndex, NumConstants, pConstants, 0);
- }
-
- void SetConstants(UINT RootIndex, DWParam X)
- {
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0);
- }
-
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y)
- {
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1);
- }
-
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z)
- {
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2);
- }
-
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W)
- {
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2);
- m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, W.Uint, 3);
- }
-
- void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV)
- {
- m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV);
- }
-
- void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle)
- {
- m_pCommandList->SetGraphicsRootDescriptorTable(RootIndex, FirstHandle);
- }
-
void SetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW& IBView)
{
m_pCommandList->IASetIndexBuffer(&IBView);
@@ -384,83 +364,62 @@ public:
{
static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EndRenderPass();
}
-};
-class GraphicsContext5 : public GraphicsContext4
-{
-};
-
-class GraphicsContext6 : public GraphicsContext5
-{
-public:
- void DrawMesh(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ)
+ void SetRayTracingPipelineState(ID3D12StateObject* pPSO)
{
-#ifdef D3D12_H_HAS_MESH_SHADER
- FlushResourceBarriers();
- static_cast<ID3D12GraphicsCommandList6*>(m_pCommandList.p)->DispatchMesh(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);
-#else
- UNSUPPORTED("DrawMesh is not supported in current D3D12 header");
-#endif
- }
-};
-
-class ComputeContext : public CommandContext
-{
-public:
- void SetRootSignature(ID3D12RootSignature* pRootSig)
- {
- if (pRootSig != m_pCurComputeRootSignature)
+ if (pPSO != m_pCurPipelineState)
{
- m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig);
+ static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->SetPipelineState1(pPSO);
+ m_pCurPipelineState = pPSO;
}
}
- void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants)
- {
- m_pCommandList->SetComputeRoot32BitConstants(RootIndex, NumConstants, pConstants, 0);
- }
-
- void SetConstants(UINT RootIndex, DWParam X)
- {
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0);
- }
-
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y)
+ void BuildRaytracingAccelerationStructure(const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& Desc,
+ UINT NumPostbuildInfoDescs,
+ const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC* pPostbuildInfoDescs)
{
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1);
+ FlushResourceBarriers();
+ static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->BuildRaytracingAccelerationStructure(&Desc, NumPostbuildInfoDescs, pPostbuildInfoDescs);
}
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z)
+ void EmitRaytracingAccelerationStructurePostbuildInfo(const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC& Desc,
+ UINT NumSourceAccelerationStructures,
+ const D3D12_GPU_VIRTUAL_ADDRESS* pSourceAccelerationStructureData)
{
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2);
+ FlushResourceBarriers();
+ static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EmitRaytracingAccelerationStructurePostbuildInfo(&Desc, NumSourceAccelerationStructures, pSourceAccelerationStructureData);
}
- void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W)
+ void CopyRaytracingAccelerationStructure(D3D12_GPU_VIRTUAL_ADDRESS DestAccelerationStructureData,
+ D3D12_GPU_VIRTUAL_ADDRESS SourceAccelerationStructureData,
+ D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE Mode)
{
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2);
- m_pCommandList->SetComputeRoot32BitConstant(RootIndex, W.Uint, 3);
+ FlushResourceBarriers();
+ static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->CopyRaytracingAccelerationStructure(DestAccelerationStructureData, SourceAccelerationStructureData, Mode);
}
-
- void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV)
+ void DispatchRays(const D3D12_DISPATCH_RAYS_DESC& Desc)
{
- m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV);
+ FlushResourceBarriers();
+ static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->DispatchRays(&Desc);
}
+};
- void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle)
- {
- m_pCommandList->SetComputeRootDescriptorTable(RootIndex, FirstHandle);
- }
+class GraphicsContext5 : public GraphicsContext4
+{
+};
- void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1)
+class GraphicsContext6 : public GraphicsContext5
+{
+public:
+ void DrawMesh(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ)
{
+#ifdef D3D12_H_HAS_MESH_SHADER
FlushResourceBarriers();
- m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ);
+ static_cast<ID3D12GraphicsCommandList6*>(m_pCommandList.p)->DispatchMesh(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);
+#else
+ UNSUPPORTED("DrawMesh is not supported in current D3D12 header");
+#endif
}
};
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp
index 240ea165..e3a78c6c 100644
--- a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp
@@ -43,7 +43,7 @@ public:
ID3D12Resource* GetD3D12Resource() { return m_pd3d12Resource; }
protected:
- CComPtr<ID3D12Resource> m_pd3d12Resource; ///< D3D12 buffer object
+ CComPtr<ID3D12Resource> m_pd3d12Resource; ///< D3D12 resource object
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp
index c6678ddd..389b76a1 100644
--- a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp
@@ -78,5 +78,9 @@ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE AttachmentStoreOpToD3D12EndingAccessType
D3D12_SHADER_VISIBILITY ShaderTypeToD3D12ShaderVisibility(SHADER_TYPE ShaderType);
SHADER_TYPE D3D12ShaderVisibilityToShaderType(D3D12_SHADER_VISIBILITY ShaderVisibility);
+DXGI_FORMAT ValueTypeToIndexType(VALUE_TYPE Type);
+
+D3D12_RAYTRACING_GEOMETRY_FLAGS GeometryFlagsToD3D12RTGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags);
+D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags);
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
index 39a354dd..3ac65274 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
@@ -42,6 +42,8 @@
#include "RenderPassD3D12Impl.hpp"
#include "PipelineStateD3D12Impl.hpp"
#include "D3D12DynamicHeap.hpp"
+#include "BottomLevelASD3D12Impl.hpp"
+#include "TopLevelASD3D12Impl.hpp"
namespace Diligent
{
@@ -56,6 +58,8 @@ struct DeviceContextD3D12ImplTraits
using QueryType = QueryD3D12Impl;
using FramebufferType = FramebufferD3D12Impl;
using RenderPassType = RenderPassD3D12Impl;
+ using BottomLevelASType = BottomLevelASD3D12Impl;
+ using TopLevelASType = TopLevelASD3D12Impl;
};
/// Device context implementation in Direct3D12 backend.
@@ -125,13 +129,13 @@ public:
ITextureView* pDepthStencil,
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final;
- /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D11 backend.
+ /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D12 backend.
virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override final;
- /// Implementation of IDeviceContext::NextSubpass() in Direct3D11 backend.
+ /// Implementation of IDeviceContext::NextSubpass() in Direct3D12 backend.
virtual void DILIGENT_CALL_TYPE NextSubpass() override final;
- /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend.
+ /// Implementation of IDeviceContext::EndRenderPass() in Direct3D12 backend.
virtual void DILIGENT_CALL_TYPE EndRenderPass() override final;
// clang-format off
@@ -351,12 +355,23 @@ private:
RESOURCE_STATE_TRANSITION_MODE TransitionMode,
RESOURCE_STATE RequiredState,
const char* OperationName);
+ __forceinline void TransitionOrVerifyBLASState(CommandContext& CmdCtx,
+ BottomLevelASD3D12Impl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
+ __forceinline void TransitionOrVerifyTLASState(CommandContext& CmdCtx,
+ TopLevelASD3D12Impl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
__forceinline void PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags);
__forceinline void PrepareForIndexedDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags, VALUE_TYPE IndexType);
__forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx);
+ __forceinline void PrepareForDispatchRays(GraphicsContext& GraphCtx);
__forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx,
IBuffer* pAttribsBuffer,
diff --git a/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp
index 59642660..31b65866 100644
--- a/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp
@@ -39,7 +39,7 @@ namespace Diligent
class FixedBlockMemoryAllocator;
-/// Render pass implementation in Direct3D11 backend.
+/// Render pass implementation in Direct3D12 backend.
class FramebufferD3D12Impl final : public FramebufferBase<IFramebuffer, RenderDeviceD3D12Impl>
{
public:
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp
index 501e62df..00984731 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp
@@ -39,7 +39,7 @@ namespace Diligent
class FixedBlockMemoryAllocator;
-/// Render pass implementation in Direct3D11 backend.
+/// Render pass implementation in Direct3D12 backend.
class RenderPassD3D12Impl final : public RenderPassBase<IRenderPass, RenderDeviceD3D12Impl>
{
public:
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp
new file mode 100644
index 00000000..e866c6f2
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderBindingTableD3D12Impl class
+
+#include "ShaderBindingTableD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "ShaderBindingTableBase.hpp"
+#include "D3D12ResourceBase.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+#include "PipelineStateD3D12Impl.hpp"
+
+namespace Diligent
+{
+
+/// Shader binding table object implementation in Direct3D12 backend.
+class ShaderBindingTableD3D12Impl final : public ShaderBindingTableBase<IShaderBindingTableD3D12, PipelineStateD3D12Impl, RenderDeviceD3D12Impl>, public D3D12ResourceBase
+{
+public:
+ using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableD3D12, PipelineStateD3D12Impl, RenderDeviceD3D12Impl>;
+
+ ShaderBindingTableD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const ShaderBindingTableDesc& Desc,
+ bool bIsDeviceInternal = false);
+ ~ShaderBindingTableD3D12Impl();
+
+ 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;
+
+ virtual void DILIGENT_CALL_TYPE GetD3D12AddressRangeAndStride(IDeviceContextD3D12* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE& RaygenShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& MissShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& HitShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& CallableShaderBindingTable) override;
+
+private:
+ void ValidateDesc(const ShaderBindingTableDesc& Desc) const;
+
+private:
+ RefCntAutoPtr<IBuffer> m_pBuffer;
+};
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp
new file mode 100644
index 00000000..8eccf530
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::TopLevelASD3D12Impl class
+
+#include "TopLevelASD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "TopLevelASBase.hpp"
+#include "D3D12ResourceBase.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+
+namespace Diligent
+{
+
+/// Top-level acceleration structure object implementation in Direct3D12 backend.
+class TopLevelASD3D12Impl final : public TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>, public D3D12ResourceBase
+{
+public:
+ using TTopLevelASBase = TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>;
+
+ TopLevelASD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const TopLevelASDesc& Desc,
+ bool bIsDeviceInternal = false);
+ ~TopLevelASD3D12Impl();
+
+ virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
+
+ /// Implementation of ITopLevelASD3D12::GetScratchBufferSizes() in DirectX 12 backend.
+ virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
+
+ /// Implementation of ITopLevelASD3D12D3D12::GetD3D12TLAS().
+ virtual ID3D12Resource* DILIGENT_CALL_TYPE GetD3D12TLAS() override final { return GetD3D12Resource(); }
+
+ /// Implementation of ITopLevelASD3D12::GetNativeHandle() in Direct3D12 backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { return GetD3D12TLAS(); }
+
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress()
+ {
+ return GetD3D12Resource()->GetGPUVirtualAddress();
+ }
+
+ /// Implementation of ITopLevelASD3D12::GetCPUDescriptorHandle() in Direct3D12 backend.
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE DILIGENT_CALL_TYPE GetCPUDescriptorHandle() override final
+ {
+ return m_DescriptorHandle.GetCpuHandle();
+ }
+
+private:
+ ScratchBufferSizes m_ScratchSize;
+
+ // Allocation in a CPU-only descriptor heap
+ DescriptorHeapAllocation m_DescriptorHandle;
+};
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h b/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h
new file mode 100644
index 00000000..2b64da57
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBottomLevelASD3D12 interface
+
+#include "../../GraphicsEngine/interface/BottomLevelAS.h"
+#include "../../GraphicsEngine/interface/DeviceContext.h"
+
+DILIGENT_BEGIN_NAMESPACE(Diligent)
+
+// {610228AF-F161-4B12-A00E-71E6E3BB97FE}
+static const INTERFACE_ID IID_BottomLevelASD3D12 =
+ {0x610228af, 0xf161, 0x4b12, {0xa0, 0xe, 0x71, 0xe6, 0xe3, 0xbb, 0x97, 0xfe}};
+
+#define DILIGENT_INTERFACE_NAME IBottomLevelASD3D12
+#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
+
+#define IBottomLevelASD3D12InclusiveMethods \
+ IBottomLevelASInclusiveMethods; \
+ IBottomLevelASD3D12Methods BottomLevelASD3D12
+
+// clang-format off
+
+/// Exposes Direct3D12-specific functionality of a bottom-level acceleration structure object.
+DILIGENT_BEGIN_INTERFACE(IBottomLevelASD3D12, IBottomLevelAS)
+{
+ /// Returns ID3D12Resource interface of the internal D3D12 acceleration structure object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ VIRTUAL ID3D12Resource* METHOD(GetD3D12BLAS)(THIS) PURE;
+};
+DILIGENT_END_INTERFACE
+
+#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
+
+#if DILIGENT_C_INTERFACE
+
+# define IBottomLevelASD3D12_GetD3D12BLAS(This) CALL_IFACE_METHOD(IBottomLevelASD3D12, GetD3D12BLAS, This)
+
+#endif
+
+DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h
new file mode 100644
index 00000000..f33bac1b
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IShaderBindingTableD3D12 interface
+
+#include "../../GraphicsEngine/interface/ShaderBindingTable.h"
+#include "DeviceContextD3D12.h"
+
+DILIGENT_BEGIN_NAMESPACE(Diligent)
+
+// {DCA2FAD9-2C41-4419-9D16-79731C0ED9D8}
+static const INTERFACE_ID IID_ShaderBindingTableD3D12 =
+ {0xdca2fad9, 0x2c41, 0x4419, {0x9d, 0x16, 0x79, 0x73, 0x1c, 0xe, 0xd9, 0xd8}};
+
+#define DILIGENT_INTERFACE_NAME IShaderBindingTableD3D12
+#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
+
+#define IShaderBindingTableD3D12InclusiveMethods \
+ IShaderBindingTableInclusiveMethods; \
+ IShaderBindingTableD3D12Methods ShaderBindingTable
+// clang-format off
+
+/// Exposes Direct3D12-specific functionality of a shader binding table object.
+DILIGENT_BEGIN_INTERFACE(IShaderBindingTableD3D12, IShaderBindingTable)
+{
+ /// AZ TODO
+ VIRTUAL void METHOD(GetD3D12AddressRangeAndStride)(THIS_
+ IDeviceContextD3D12* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE REF RaygenShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF MissShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF HitShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF CallableShaderBindingTable) PURE;
+};
+DILIGENT_END_INTERFACE
+
+#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
+
+#if DILIGENT_C_INTERFACE
+
+
+#endif
+
+DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h b/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h
new file mode 100644
index 00000000..5b2bd512
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ITopLevelASD3D12 interface
+
+#include "../../GraphicsEngine/interface/TopLevelAS.h"
+#include "../../GraphicsEngine/interface/DeviceContext.h"
+
+DILIGENT_BEGIN_NAMESPACE(Diligent)
+
+// {46334F12-64CB-4F7C-BB71-31515B6F386D}
+static const INTERFACE_ID IID_TopLevelASD3D12 =
+ {0x46334f12, 0x64cb, 0x4f7c, {0xbb, 0x71, 0x31, 0x51, 0x5b, 0x6f, 0x38, 0x6d}};
+
+#define DILIGENT_INTERFACE_NAME ITopLevelASD3D12
+#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
+
+#define ITopLevelASD3D12InclusiveMethods \
+ ITopLevelASInclusiveMethods; \
+ ITopLevelASD3D12Methods TopLevelASD3D12
+
+// clang-format off
+
+/// Exposes Direct3D12-specific functionality of a top-level acceleration structure object.
+DILIGENT_BEGIN_INTERFACE(ITopLevelASD3D12, ITopLevelAS)
+{
+ /// Returns ID3D12Resource interface of the internal D3D12 acceleration structure object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ VIRTUAL ID3D12Resource* METHOD(GetD3D12TLAS)(THIS) PURE;
+
+ /// Returns a CPU descriptor handle of the D3D12 acceleration structure
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ VIRTUAL D3D12_CPU_DESCRIPTOR_HANDLE METHOD(GetCPUDescriptorHandle)(THIS) PURE;
+};
+DILIGENT_END_INTERFACE
+
+#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
+
+#if DILIGENT_C_INTERFACE
+
+# define ITopLevelASD3D12_GetD3D12TLAS(This) CALL_IFACE_METHOD(ITopLevelASD3D12, GetD3D12TLAS, This)
+# define ITopLevelASD3D12_GetCPUDescriptorHandle(This) CALL_IFACE_METHOD(ITopLevelASD3D12, GetCPUDescriptorHandle, This)
+
+#endif
+
+DILIGENT_END_NAMESPACE // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp
new file mode 100644
index 00000000..31f0e6a3
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 "pch.h"
+#include "BottomLevelASD3D12Impl.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+#include "DeviceContextD3D12Impl.hpp"
+#include "D3D12TypeConversions.hpp"
+#include "GraphicsAccessories.hpp"
+#include "DXGITypeConversions.hpp"
+#include "EngineMemory.h"
+#include "StringTools.hpp"
+
+namespace Diligent
+{
+
+BottomLevelASD3D12Impl::BottomLevelASD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const BottomLevelASDesc& Desc,
+ bool bIsDeviceInternal) :
+ TBottomLevelASBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal}
+{
+ D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO BottomLevelPrebuildInfo = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS BottomLevelInputs = {};
+ std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries;
+
+ if (m_Desc.pTriangles != nullptr)
+ {
+ Geometries.resize(m_Desc.TriangleCount);
+ Uint32 MaxPrimitiveCount = 0;
+ for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i)
+ {
+ auto& src = m_Desc.pTriangles[i];
+ auto& dst = Geometries[i];
+
+ dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
+ dst.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE;
+ dst.Triangles.VertexBuffer.StartAddress = 0;
+ dst.Triangles.VertexBuffer.StrideInBytes = 0;
+ dst.Triangles.VertexFormat = TypeToDXGI_Format(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16);
+ dst.Triangles.VertexCount = src.MaxVertexCount;
+ dst.Triangles.IndexCount = src.MaxIndexCount;
+ dst.Triangles.IndexFormat = ValueTypeToIndexType(src.IndexType);
+ dst.Triangles.IndexBuffer = 0;
+ dst.Triangles.Transform3x4 = 0;
+
+ MaxPrimitiveCount += src.MaxIndexCount ? src.MaxIndexCount / 3 : src.MaxVertexCount / 3;
+ }
+ VERIFY_EXPR(MaxPrimitiveCount <= D3D12_RAYTRACING_MAX_PRIMITIVES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE);
+ }
+ else if (m_Desc.pBoxes != nullptr)
+ {
+ Geometries.resize(m_Desc.BoxCount);
+ Uint32 MaxBoxCount = 0;
+ for (uint32_t i = 0; i < m_Desc.BoxCount; ++i)
+ {
+ auto& src = m_Desc.pBoxes[i];
+ auto& dst = Geometries[i];
+
+ dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS;
+ dst.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE;
+ dst.AABBs.AABBCount = src.MaxBoxCount;
+ dst.AABBs.AABBs.StartAddress = 0;
+ dst.AABBs.AABBs.StrideInBytes = 0;
+
+ MaxBoxCount += src.MaxBoxCount;
+ }
+ VERIFY_EXPR(MaxBoxCount <= D3D12_RAYTRACING_MAX_PRIMITIVES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE);
+ }
+
+ VERIFY_EXPR(Geometries.size() <= D3D12_RAYTRACING_MAX_GEOMETRIES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE);
+
+ BottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
+ BottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE;
+ BottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
+ BottomLevelInputs.pGeometryDescs = Geometries.data();
+ BottomLevelInputs.NumDescs = static_cast<UINT>(Geometries.size());
+
+ auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5();
+
+ pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&BottomLevelInputs, &BottomLevelPrebuildInfo);
+ if (BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0)
+ LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info");
+
+ 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;
+
+ D3D12_RESOURCE_DESC ASDesc = {};
+ ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ ASDesc.Alignment = 0;
+ ASDesc.Width = BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes;
+ ASDesc.Height = 1;
+ ASDesc.DepthOrArraySize = 1;
+ ASDesc.MipLevels = 1;
+ ASDesc.Format = DXGI_FORMAT_UNKNOWN;
+ ASDesc.SampleDesc.Count = 1;
+ ASDesc.SampleDesc.Quality = 0;
+ ASDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ ASDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
+ &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr,
+ __uuidof(m_pd3d12Resource),
+ reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource)));
+ if (FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create D3D12 Bottom-level acceleration structure");
+
+ if (*m_Desc.Name != 0)
+ m_pd3d12Resource->SetName(WidenString(m_Desc.Name).c_str());
+
+ m_ScratchSize.Build = static_cast<Uint32>(BottomLevelPrebuildInfo.ScratchDataSizeInBytes);
+ m_ScratchSize.Update = static_cast<Uint32>(BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes);
+}
+
+BottomLevelASD3D12Impl::~BottomLevelASD3D12Impl()
+{
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ auto* pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12Impl->SafeReleaseDeviceObject(std::move(m_pd3d12Resource), m_Desc.CommandQueueMask);
+}
+
+IMPLEMENT_QUERY_INTERFACE(BottomLevelASD3D12Impl, IID_BottomLevelASD3D12, TBottomLevelASBase)
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
index d7cd54b6..8e84b844 100644
--- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
@@ -118,9 +118,9 @@ BufferD3D12Impl::BufferD3D12Impl(IReferenceCounters* pRefCounters,
// understood by applications and row-major texture data is commonly marshaled through buffers.
D3D12BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- if (m_Desc.BindFlags & BIND_UNORDERED_ACCESS)
+ if ((m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || (m_Desc.BindFlags & BIND_RAY_TRACING))
D3D12BuffDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- if (!(m_Desc.BindFlags & BIND_SHADER_RESOURCE))
+ if (!(m_Desc.BindFlags & BIND_SHADER_RESOURCE) && !(m_Desc.BindFlags & BIND_RAY_TRACING))
D3D12BuffDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
index 389bf3eb..6bc55ac3 100644
--- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
@@ -30,6 +30,8 @@
#include "CommandContext.hpp"
#include "TextureD3D12Impl.hpp"
#include "BufferD3D12Impl.hpp"
+#include "BottomLevelASD3D12Impl.hpp"
+#include "TopLevelASD3D12Impl.hpp"
#include "CommandListManager.hpp"
#include "D3D12TypeConversions.hpp"
@@ -39,9 +41,9 @@ namespace Diligent
CommandContext::CommandContext(CommandListManager& CmdListManager) :
// clang-format off
- m_pCurGraphicsRootSignature {nullptr},
- m_pCurPipelineState {nullptr},
- m_pCurComputeRootSignature {nullptr},
+ m_pCurGraphicsRootSignature {nullptr},
+ m_pCurPipelineState {nullptr},
+ m_pCurComputeRootSignature {nullptr},
m_PendingResourceBarriers (STD_ALLOCATOR_RAW_MEM(D3D12_RESOURCE_BARRIER, GetRawAllocator(), "Allocator for vector<D3D12_RESOURCE_BARRIER>"))
// clang-format on
{
@@ -78,7 +80,7 @@ void CommandContext::Reset(CommandListManager& CmdListManager)
m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
#if 0
- BindDescriptorHeaps();
+ BindDescriptorHeaps();
#endif
}
@@ -115,6 +117,24 @@ void CommandContext::TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE Ne
TransitionResource(BufferBarrier);
}
+void CommandContext::TransitionResource(IBottomLevelASD3D12* pBLAS, RESOURCE_STATE NewState)
+{
+ VERIFY_EXPR(pBLAS != nullptr);
+ auto* pBLASfD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(pBLAS);
+ VERIFY(pBLASfD3D12->IsInKnownState(), "BLAS state can't be unknown");
+ StateTransitionDesc ASBarrier(pBLAS, RESOURCE_STATE_UNKNOWN, NewState, true);
+ TransitionResource(ASBarrier);
+}
+
+void CommandContext::TransitionResource(ITopLevelASD3D12* pTLAS, RESOURCE_STATE NewState)
+{
+ VERIFY_EXPR(pTLAS != nullptr);
+ auto* pTLASfD3D12 = ValidatedCast<TopLevelASD3D12Impl>(pTLAS);
+ VERIFY(pTLASfD3D12->IsInKnownState(), "TLAS state can't be unknown");
+ StateTransitionDesc ASBarrier(pTLAS, RESOURCE_STATE_UNKNOWN, NewState, true);
+ TransitionResource(ASBarrier);
+}
+
void CommandContext::InsertUAVBarrier(ID3D12Resource* pd3d12Resource)
{
m_PendingResourceBarriers.emplace_back();
@@ -147,25 +167,23 @@ static D3D12_RESOURCE_BARRIER_FLAGS TransitionTypeToD3D12ResourceBarrierFlag(STA
void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
{
- DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null");
-
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
- RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
- ID3D12Resource* pd3d12Resource = nullptr;
- TextureD3D12Impl* pTextureD3D12Impl = nullptr;
- BufferD3D12Impl* pBufferD3D12Impl = nullptr;
- if (Barrier.pTexture)
+ RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
+ ID3D12Resource* pd3d12Resource = nullptr;
+ RefCntAutoPtr<TextureD3D12Impl> pTextureD3D12Impl{Barrier.pResource, IID_TextureD3D12};
+ RefCntAutoPtr<BufferD3D12Impl> pBufferD3D12Impl{Barrier.pResource, IID_BufferD3D12};
+ RefCntAutoPtr<BottomLevelASD3D12Impl> pBLASD3D12Impl{Barrier.pResource, IID_BottomLevelASD3D12};
+ RefCntAutoPtr<TopLevelASD3D12Impl> pTLASD3D12Impl{Barrier.pResource, IID_TopLevelASD3D12};
+
+ if (pTextureD3D12Impl)
{
- pTextureD3D12Impl = ValidatedCast<TextureD3D12Impl>(Barrier.pTexture);
- pd3d12Resource = pTextureD3D12Impl->GetD3D12Resource();
- OldState = pTextureD3D12Impl->GetState();
+ pd3d12Resource = pTextureD3D12Impl->GetD3D12Resource();
+ OldState = pTextureD3D12Impl->GetState();
}
- else
+ else if (pBufferD3D12Impl)
{
- VERIFY_EXPR(Barrier.pBuffer != nullptr);
- pBufferD3D12Impl = ValidatedCast<BufferD3D12Impl>(Barrier.pBuffer);
- pd3d12Resource = pBufferD3D12Impl->GetD3D12Resource();
- OldState = pBufferD3D12Impl->GetState();
+ pd3d12Resource = pBufferD3D12Impl->GetD3D12Resource();
+ OldState = pBufferD3D12Impl->GetState();
#ifdef DILIGENT_DEVELOPMENT
// Dynamic buffers wtih no SRV/UAV bind flags are suballocated in
@@ -178,6 +196,20 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
}
#endif
}
+ else if (pBLASD3D12Impl)
+ {
+ pd3d12Resource = pBLASD3D12Impl->GetD3D12Resource();
+ OldState = pBLASD3D12Impl->GetState();
+ }
+ else if (pTLASD3D12Impl)
+ {
+ pd3d12Resource = pTLASD3D12Impl->GetD3D12Resource();
+ OldState = pTLASD3D12Impl->GetState();
+ }
+ else
+ {
+ UNEXPECTED("unsupported resource type");
+ }
if (OldState == RESOURCE_STATE_UNKNOWN)
{
@@ -243,9 +275,8 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
}
}
}
- else
+ else if (pBufferD3D12Impl)
{
- VERIFY_EXPR(pBufferD3D12Impl);
m_PendingResourceBarriers.emplace_back(BarrierDesc);
}
}
@@ -259,10 +290,8 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
pTextureD3D12Impl->SetState(NewState);
}
}
- else
+ else if (pBufferD3D12Impl)
{
- VERIFY_EXPR(pBufferD3D12Impl);
-
VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END),
"Buffer state can't be updated in begin-split barrier");
if (Barrier.UpdateResourceState)
@@ -275,9 +304,29 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
"Dynamic buffers without SRV/UAV bind flag are expected to never "
"transition from RESOURCE_STATE_GENERIC_READ state");
}
+ else if (pBLASD3D12Impl)
+ {
+ VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END),
+ "Bottom-level acceleration structure state can't be updated in begin-split barrier");
+ if (Barrier.UpdateResourceState)
+ {
+ pBLASD3D12Impl->SetState(NewState);
+ }
+ }
+ else if (pTLASD3D12Impl)
+ {
+ VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END),
+ "Top-level acceleration structure state can't be updated in begin-split barrier");
+ if (Barrier.UpdateResourceState)
+ {
+ pTLASD3D12Impl->SetState(NewState);
+ }
+ }
}
- if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ if ((OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) ||
+ (OldState == RESOURCE_STATE_BUILD_AS_WRITE && Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE) ||
+ (OldState == RESOURCE_STATE_RAY_TRACING && Barrier.NewState == RESOURCE_STATE_RAY_TRACING))
{
DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "UAV barriers must not be split");
InsertUAVBarrier(pd3d12Resource);
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
index 3ea4bad0..ddab5096 100644
--- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
@@ -351,8 +351,9 @@ static D3D12_RESOURCE_STATES ResourceStateFlagToD3D12ResourceState(RESOURCE_STAT
case RESOURCE_STATE_RESOLVE_SOURCE: return D3D12_RESOURCE_STATE_RESOLVE_SOURCE;
case RESOURCE_STATE_INPUT_ATTACHMENT: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case RESOURCE_STATE_PRESENT: return D3D12_RESOURCE_STATE_PRESENT;
- case RESOURCE_STATE_BUILD_AS: return D3D12_RESOURCE_STATES(0);
- case RESOURCE_STATE_RAY_TRACING: return D3D12_RESOURCE_STATES(0); // AZ TODO
+ case RESOURCE_STATE_BUILD_AS_READ: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ case RESOURCE_STATE_BUILD_AS_WRITE: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+ case RESOURCE_STATE_RAY_TRACING: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
// clang-format on
default:
UNEXPECTED("Unexpected resource state flag");
@@ -379,7 +380,7 @@ public:
}
private:
- static constexpr Uint32 MaxFlagBitPos = 18;
+ static constexpr Uint32 MaxFlagBitPos = 19;
std::array<D3D12_RESOURCE_STATES, MaxFlagBitPos + 1> FlagBitPosToResStateMap;
};
@@ -422,7 +423,6 @@ static RESOURCE_STATE D3D12ResourceStateToResourceStateFlags(D3D12_RESOURCE_STAT
case D3D12_RESOURCE_STATE_COPY_SOURCE: return RESOURCE_STATE_COPY_SOURCE;
case D3D12_RESOURCE_STATE_RESOLVE_DEST: return RESOURCE_STATE_RESOLVE_DEST;
case D3D12_RESOURCE_STATE_RESOLVE_SOURCE: return RESOURCE_STATE_RESOLVE_SOURCE;
- // AZ TODO
// clang-format on
default:
UNEXPECTED("Unexpected D3D12 resource state");
@@ -592,5 +592,67 @@ SHADER_TYPE D3D12ShaderVisibilityToShaderType(D3D12_SHADER_VISIBILITY ShaderVisi
}
}
+DXGI_FORMAT ValueTypeToIndexType(VALUE_TYPE IndexType)
+{
+ switch (IndexType)
+ {
+ // clang-format off
+ case VT_UNDEFINED: return DXGI_FORMAT_UNKNOWN; // only for ray tracing
+ case VT_UINT16: return DXGI_FORMAT_R16_UINT;
+ case VT_UINT32: return DXGI_FORMAT_R32_UINT;
+ // clang-format on
+ default:
+ UNEXPECTED("Unexpected index type");
+ return DXGI_FORMAT_R32_UINT;
+ }
+}
+
+D3D12_RAYTRACING_GEOMETRY_FLAGS GeometryFlagsToD3D12RTGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags)
+{
+ static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION,
+ "Please update the switch below to handle the new ray tracing geometry flag");
+
+ Uint32 Result = 0;
+ for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1)
+ {
+ if ((Flags & Bit) != Bit)
+ continue;
+
+ switch (static_cast<RAYTRACING_GEOMETRY_FLAGS>(Bit))
+ {
+ // clang-format off
+ case RAYTRACING_GEOMETRY_OPAQUE: Result |= D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; break;
+ case RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= D3D12_RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION; break;
+ // clang-format on
+ default: UNEXPECTED("unknown geometry flag");
+ }
+ }
+ return static_cast<D3D12_RAYTRACING_GEOMETRY_FLAGS>(Result);
+}
+
+D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags)
+{
+ static_assert(RAYTRACING_INSTANCE_FLAGS_LAST == RAYTRACING_INSTANCE_FORCE_NO_OPAQUE,
+ "Please update the switch below to handle the new ray tracing instance flag");
+
+ Uint32 Result = 0;
+ for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1)
+ {
+ if ((Flags & Bit) != Bit)
+ continue;
+
+ switch (static_cast<RAYTRACING_INSTANCE_FLAGS>(Bit))
+ {
+ // clang-format off
+ case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_CULL_DISABLE ; break;
+ case RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE ; break;
+ case RAYTRACING_INSTANCE_FORCE_OPAQUE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_OPAQUE ; break;
+ case RAYTRACING_INSTANCE_FORCE_NO_OPAQUE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_NON_OPAQUE ; break;
+ // clang-format on
+ default: UNEXPECTED("unknown instance flag");
+ }
+ }
+ return static_cast<D3D12_RAYTRACING_INSTANCE_FLAGS>(Result);
+}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 6ca74c27..95025c4c 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -39,6 +39,7 @@
#include "D3D12DynamicHeap.hpp"
#include "CommandListD3D12Impl.hpp"
#include "DXGITypeConversions.hpp"
+#include "ShaderBindingTableD3D12Impl.hpp"
namespace Diligent
{
@@ -262,6 +263,8 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState)
}
case PIPELINE_TYPE_RAY_TRACING:
{
+ auto* pd3d12SO = pPipelineStateD3D12->GetD3D12StateObject();
+ CmdCtx.AsGraphicsContext4().SetRayTracingPipelineState(pd3d12SO);
break;
}
default:
@@ -449,7 +452,7 @@ void DeviceContextD3D12Impl::PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAG
}
#endif
- GraphCtx.SetRootSignature(m_pPipelineState->GetD3D12RootSignature());
+ GraphCtx.SetGraphicsRootSignature(m_pPipelineState->GetD3D12RootSignature());
if (m_State.pCommittedResourceCache != nullptr)
{
@@ -605,7 +608,7 @@ void DeviceContextD3D12Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Att
void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCtx)
{
- ComputeCtx.SetRootSignature(m_pPipelineState->GetD3D12RootSignature());
+ ComputeCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature());
if (m_State.pCommittedResourceCache != nullptr)
{
if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0)
@@ -634,6 +637,37 @@ void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCt
#endif
}
+void DeviceContextD3D12Impl::PrepareForDispatchRays(GraphicsContext& GraphCtx)
+{
+ GraphCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature());
+ if (m_State.pCommittedResourceCache != nullptr)
+ {
+ if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0)
+ {
+ // Only process dynamic buffers. Non-dynamic buffers are committed by CommitShaderResources
+ m_pPipelineState->GetRootSignature()
+ .CommitRootViews(*m_State.pCommittedResourceCache,
+ GraphCtx,
+ true, // IsCompute
+ m_ContextId,
+ this,
+ true, // CommitViews
+ true, // ProcessDynamicBuffers
+ false, // ProcessNonDynamicBuffers
+ false, // TransitionStates
+ false // ValidateStates
+ );
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else
+ {
+ if (m_pPipelineState->ContainsShaderResources())
+ LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called with non-null SRB");
+ }
+#endif
+}
+
void DeviceContextD3D12Impl::DispatchCompute(const DispatchComputeAttribs& Attribs)
{
if (!DvpVerifyDispatchArguments(Attribs))
@@ -2139,6 +2173,46 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTextureState(CommandContext&
#endif
}
+void DeviceContextD3D12Impl::TransitionOrVerifyBLASState(CommandContext& CmdCtx,
+ BottomLevelASD3D12Impl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState))
+ CmdCtx.TransitionResource(&BLAS, RequiredState);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyBLASState(BLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
+void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext& CmdCtx,
+ TopLevelASD3D12Impl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ 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))
+ CmdCtx.TransitionResource(&TLAS, RequiredState);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTLASState(TLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
void DeviceContextD3D12Impl::TransitionTextureState(ITexture* pTexture, D3D12_RESOURCE_STATES State)
{
VERIFY_EXPR(pTexture != nullptr);
@@ -2202,22 +2276,218 @@ void DeviceContextD3D12Impl::ResolveTextureSubresource(ITexture*
void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs)
{
+ if (!TDeviceContextBase::BuildBLAS(Attribs, 0))
+ return;
+
+ auto* pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pBLAS);
+ auto* pScratchD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pScratchBuffer);
+ auto& BLASDesc = pBLASD12->GetDesc();
+
+ auto& CmdCtx = GetCmdContext();
+ const char* OpName = "Build BottomLevelAS (DeviceContextD3D12Impl::BuildBLAS)";
+ TransitionOrVerifyBLASState(CmdCtx, *pBLASD12, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+ TransitionOrVerifyBufferState(CmdCtx, *pScratchD12, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC Desc = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& Inputs = Desc.Inputs;
+ std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries;
+
+ if (Attribs.pTriangleData != nullptr)
+ {
+ Geometries.resize(Attribs.TriangleDataCount);
+
+ for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
+ {
+ auto& src = Attribs.pTriangleData[i];
+ Uint32 j = pBLASD12->GetGeometryIndex(src.GeometryName);
+ auto& dst = Geometries.data()[j];
+ auto& tri = dst.Triangles;
+
+ if (j >= Geometries.size())
+ {
+ UNEXPECTED("Failed to find geometry by name");
+ continue;
+ }
+
+ dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
+ dst.Flags = GeometryFlagsToD3D12RTGeometryFlags(src.Flags);
+
+ auto* pVB = ValidatedCast<BufferD3D12Impl>(src.pVertexBuffer);
+ tri.VertexFormat = TypeToDXGI_Format(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16);
+ tri.VertexCount = src.VertexCount;
+ tri.VertexBuffer.StartAddress = pVB->GetGPUAddress() + src.VertexOffset;
+ tri.VertexBuffer.StrideInBytes = src.VertexStride;
+
+ if (src.pIndexBuffer)
+ {
+ auto* pIB = ValidatedCast<BufferD3D12Impl>(src.pIndexBuffer);
+ tri.IndexBuffer = pIB->GetGPUAddress() + src.IndexOffset;
+ tri.IndexCount = src.IndexCount;
+ tri.IndexFormat = ValueTypeToIndexType(src.IndexType);
+
+ TransitionOrVerifyBufferState(CmdCtx, *pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ }
+ else
+ {
+ tri.IndexFormat = DXGI_FORMAT_UNKNOWN;
+ tri.IndexBuffer = 0;
+ }
+
+ if (src.pTransformBuffer)
+ {
+ VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms);
+
+ auto* pTB = ValidatedCast<BufferD3D12Impl>(src.pTransformBuffer);
+ tri.Transform3x4 = pTB->GetGPUAddress() + src.TransformBufferOffset;
+
+ TransitionOrVerifyBufferState(CmdCtx, *pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ }
+ else
+ {
+ VERIFY_EXPR(!BLASDesc.pTriangles[j].AllowsTransforms);
+ tri.Transform3x4 = 0;
+ }
+ }
+ }
+ else if (Attribs.pBoxData != nullptr)
+ {
+ Geometries.resize(Attribs.BoxDataCount);
+
+ for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
+ {
+ auto& src = Attribs.pBoxData[i];
+ Uint32 j = pBLASD12->GetGeometryIndex(src.GeometryName);
+ auto& dst = Geometries.data()[j];
+ auto& box = dst.AABBs;
+
+ if (j >= Geometries.size())
+ {
+ UNEXPECTED("Failed to find geometry by name");
+ continue;
+ }
+
+ dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS;
+ dst.Flags = GeometryFlagsToD3D12RTGeometryFlags(src.Flags);
+
+ auto* pBB = ValidatedCast<BufferD3D12Impl>(src.pBoxBuffer);
+ box.AABBCount = src.BoxCount;
+ box.AABBs.StartAddress = pBB->GetGPUAddress() + src.BoxOffset;
+ box.AABBs.StrideInBytes = src.BoxStride;
+
+ TransitionOrVerifyBufferState(CmdCtx, *pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ }
+ }
+
+ Inputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
+ Inputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
+ Inputs.NumDescs = static_cast<UINT>(Geometries.size());
+ Inputs.pGeometryDescs = Geometries.data();
+
+ Desc.DestAccelerationStructureData = pBLASD12->GetGPUAddress();
+ Desc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress();
+ Desc.SourceAccelerationStructureData = 0;
+
+ CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr);
+ ++m_State.NumCommands;
}
void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs)
{
+ if (!TDeviceContextBase::BuildTLAS(Attribs, 0))
+ return;
+
+ static_assert(TLAS_INSTANCE_DATA_SIZE == sizeof(D3D12_RAYTRACING_INSTANCE_DESC), "Value in TLAS_INSTANCE_DATA_SIZE doesn't match the actual instance description size");
+
+ 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)";
+ TransitionOrVerifyTLASState(CmdCtx, *pTLASD12, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+ TransitionOrVerifyBufferState(CmdCtx, *pScratchD12, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
+ pTLASD12->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance);
+
+ // copy instance data into instance buffer
+ {
+ size_t Size = Attribs.InstanceCount * sizeof(D3D12_RAYTRACING_INSTANCE_DESC);
+ auto TmpSpace = m_DynamicHeap.Allocate(Size, 16, m_ContextFrameNumber);
+ void* pMappedInstances = TmpSpace.CPUAddress;
+
+ for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
+ {
+ auto& src = Attribs.pInstances[i];
+ auto& dst = static_cast<D3D12_RAYTRACING_INSTANCE_DESC*>(pMappedInstances)[i];
+ auto* pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(src.pBLAS);
+
+ static_assert(sizeof(dst.Transform) == sizeof(src.Transform), "size mismatch");
+ std::memcpy(&dst.Transform, src.Transform, sizeof(dst.Transform));
+
+ dst.InstanceID = src.CustomId;
+ dst.InstanceContributionToHitGroupIndex = pTLASD12->GetInstanceDesc(src.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize
+ dst.InstanceMask = src.Mask;
+ dst.Flags = InstanceFlagsToD3D12RTInstanceFlags(src.Flags);
+ dst.AccelerationStructure = pBLASD12->GetGPUAddress();
+
+ TransitionOrVerifyBLASState(CmdCtx, *pBLASD12, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ }
+ UpdateBufferRegion(pInstancesD12, TmpSpace, Attribs.InstanceBufferOffset, Size, Attribs.InstanceBufferTransitionMode);
+ }
+ TransitionOrVerifyBufferState(CmdCtx, *pInstancesD12, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC Desc = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& Inputs = Desc.Inputs;
+
+ Inputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
+ Inputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
+ Inputs.NumDescs = Attribs.InstanceCount;
+ Inputs.InstanceDescs = pInstancesD12->GetGPUAddress();
+
+ Desc.DestAccelerationStructureData = pTLASD12->GetGPUAddress();
+ Desc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress();
+ Desc.SourceAccelerationStructureData = 0;
+
+ CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr);
+ ++m_State.NumCommands;
}
void DeviceContextD3D12Impl::CopyBLAS(const CopyBLASAttribs& Attribs)
{
+ if (!TDeviceContextBase::CopyBLAS(Attribs, 0))
+ return;
+
+ // AZ TODO
}
void DeviceContextD3D12Impl::CopyTLAS(const CopyTLASAttribs& Attribs)
{
+ if (!TDeviceContextBase::CopyTLAS(Attribs, 0))
+ return;
+
+ // AZ TODO
}
void DeviceContextD3D12Impl::TraceRays(const TraceRaysAttribs& Attribs)
{
+ if (!TDeviceContextBase::TraceRays(Attribs, 0))
+ return;
+
+ D3D12_DISPATCH_RAYS_DESC Desc = {};
+
+ Desc.Width = Attribs.DimensionX;
+ Desc.Height = Attribs.DimensionY;
+ Desc.Depth = Attribs.DimensionZ;
+
+ auto* pSBTD12 = ValidatedCast<ShaderBindingTableD3D12Impl>(Attribs.pSBT);
+ pSBTD12->GetD3D12AddressRangeAndStride(this, Attribs.TransitionMode, Desc.RayGenerationShaderRecord, Desc.MissShaderTable, Desc.HitGroupTable, Desc.CallableShaderTable);
+
+ auto& CmdCtx = GetCmdContext().AsGraphicsContext4();
+ PrepareForDispatchRays(CmdCtx);
+
+ CmdCtx.DispatchRays(Desc);
+ ++m_State.NumCommands;
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
index be5c68eb..0da4470b 100644
--- a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
@@ -113,7 +113,7 @@ GenerateMipsHelper::GenerateMipsHelper(ID3D12Device* pd3d12Device)
void GenerateMipsHelper::GenerateMips(ID3D12Device* pd3d12Device, TextureViewD3D12Impl* pTexView, CommandContext& Ctx) const
{
auto& ComputeCtx = Ctx.AsComputeContext();
- ComputeCtx.SetRootSignature(m_pGenerateMipsRS);
+ ComputeCtx.SetComputeRootSignature(m_pGenerateMipsRS);
auto* pTexD3D12 = pTexView->GetTexture<TextureD3D12Impl>();
const auto& TexDesc = pTexD3D12->GetDesc();
const auto& ViewDesc = pTexView->GetDesc();
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
index efae7b37..9cc7faa5 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -877,9 +877,9 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou
if (Attrib.CommitResources)
{
if (m_Desc.IsAnyGraphicsPipeline())
- CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature());
+ CmdCtx.AsGraphicsContext().SetGraphicsRootSignature(GetD3D12RootSignature());
else
- CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature());
+ CmdCtx.AsComputeContext().SetComputeRootSignature(GetD3D12RootSignature());
}
return nullptr;
}
@@ -906,9 +906,9 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou
if (Attrib.CommitResources)
{
if (m_Desc.IsAnyGraphicsPipeline())
- CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature());
+ CmdCtx.AsGraphicsContext().SetGraphicsRootSignature(GetD3D12RootSignature());
else
- CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature());
+ CmdCtx.AsComputeContext().SetComputeRootSignature(GetD3D12RootSignature());
if (Attrib.TransitionResources)
{
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 9feabb6a..f8f545e7 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -40,6 +40,9 @@
#include "QueryD3D12Impl.hpp"
#include "RenderPassD3D12Impl.hpp"
#include "FramebufferD3D12Impl.hpp"
+#include "BottomLevelASD3D12Impl.hpp"
+#include "TopLevelASD3D12Impl.hpp"
+#include "ShaderBindingTableD3D12Impl.hpp"
#include "EngineMemory.h"
namespace Diligent
@@ -137,9 +140,9 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo
sizeof(QueryD3D12Impl),
sizeof(RenderPassD3D12Impl),
sizeof(FramebufferD3D12Impl),
- 0,
- 0,
- 0
+ sizeof(BottomLevelASD3D12Impl),
+ sizeof(TopLevelASD3D12Impl),
+ sizeof(ShaderBindingTableD3D12Impl)
}
},
m_pd3d12Device {pd3d12Device},
@@ -725,19 +728,37 @@ void RenderDeviceD3D12Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram
void RenderDeviceD3D12Impl::CreateBLAS(const BottomLevelASDesc& Desc,
IBottomLevelAS** ppBLAS)
{
- // AZ TODO
+ CreateDeviceObject("BottomLevelAS", Desc, ppBLAS,
+ [&]() //
+ {
+ BottomLevelASD3D12Impl* pBottomLevelASVk(NEW_RC_OBJ(m_BLASAllocator, "BottomLevelASD3D12Impl instance", BottomLevelASD3D12Impl)(this, Desc));
+ pBottomLevelASVk->QueryInterface(IID_BottomLevelAS, reinterpret_cast<IObject**>(ppBLAS));
+ OnCreateDeviceObject(pBottomLevelASVk);
+ });
}
void RenderDeviceD3D12Impl::CreateTLAS(const TopLevelASDesc& Desc,
ITopLevelAS** ppTLAS)
{
- // AZ TODO
+ CreateDeviceObject("TopLevelAS", Desc, ppTLAS,
+ [&]() //
+ {
+ TopLevelASD3D12Impl* pTopLevelASVk(NEW_RC_OBJ(m_TLASAllocator, "TopLevelASD3D12Impl instance", TopLevelASD3D12Impl)(this, Desc));
+ pTopLevelASVk->QueryInterface(IID_TopLevelAS, reinterpret_cast<IObject**>(ppTLAS));
+ OnCreateDeviceObject(pTopLevelASVk);
+ });
}
void RenderDeviceD3D12Impl::CreateSBT(const ShaderBindingTableDesc& Desc,
IShaderBindingTable** ppSBT)
{
- // AZ TODO
+ CreateDeviceObject("ShaderBindingTable", Desc, ppSBT,
+ [&]() //
+ {
+ ShaderBindingTableD3D12Impl* pSBTVk(NEW_RC_OBJ(m_SBTAllocator, "ShaderBindingTableD3D12Impl instance", ShaderBindingTableD3D12Impl)(this, Desc));
+ pSBTVk->QueryInterface(IID_ShaderBindingTable, reinterpret_cast<IObject**>(ppSBT));
+ OnCreateDeviceObject(pSBTVk);
+ });
}
DescriptorHeapAllocation RenderDeviceD3D12Impl::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count /*= 1*/)
diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
index 35274af3..d0db2201 100644
--- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
@@ -33,6 +33,7 @@
#include "CommandContext.hpp"
#include "RenderDeviceD3D12Impl.hpp"
#include "TextureD3D12Impl.hpp"
+#include "TopLevelASD3D12Impl.hpp"
#include "D3D12TypeConversions.hpp"
#include "HashUtils.hpp"
@@ -702,6 +703,10 @@ __forceinline void TransitionResource(CommandContext& Ctx,
case CachedResourceType::AccelStruct:
{
+ 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))
+ Ctx.TransitionResource(pTLASD3D12, RESOURCE_STATE_RAY_TRACING);
}
break;
@@ -806,6 +811,16 @@ void RootSignature::DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resou
case CachedResourceType::AccelStruct:
{
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
+ const auto* pTLASD3D12 = Res.pObject.RawPtr<const TopLevelASD3D12Impl>();
+ if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING))
+ {
+ LOG_ERROR_MESSAGE("TLAS '", pTLASD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_RAY_TRACING state. Actual state: ",
+ GetResourceStateString(pTLASD3D12->GetState()),
+ ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
+ "with IDeviceContext::TransitionResourceStates().");
+ }
}
break;
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp
new file mode 100644
index 00000000..3727913f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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 "pch.h"
+#include "ShaderBindingTableD3D12Impl.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+#include "DeviceContextD3D12Impl.hpp"
+#include "D3D12TypeConversions.hpp"
+#include "GraphicsAccessories.hpp"
+#include "DXGITypeConversions.hpp"
+#include "EngineMemory.h"
+#include "StringTools.hpp"
+
+namespace Diligent
+{
+
+ShaderBindingTableD3D12Impl::ShaderBindingTableD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const ShaderBindingTableDesc& Desc,
+ bool bIsDeviceInternal) :
+ TShaderBindingTableBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal}
+{
+ ValidateDesc(Desc);
+
+ m_ShaderRecordStride = m_Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
+}
+
+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
+}
+
+void ShaderBindingTableD3D12Impl::BindAll(const BindAllAttribs& Attribs)
+{
+ // AZ TODO
+}
+
+void ShaderBindingTableD3D12Impl::GetD3D12AddressRangeAndStride(IDeviceContextD3D12* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE& RaygenShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& MissShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& HitShaderBindingTable,
+ D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& CallableShaderBindingTable)
+{
+ const auto AlignToLarger = [](size_t offset) -> Uint32 {
+ return Align(static_cast<Uint32>(offset), static_cast<Uint32>(D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT));
+ };
+
+ const Uint32 RayGenOffset = 0;
+ const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size());
+ const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size());
+ const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size());
+ const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size());
+
+ // recreate buffer
+ if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize)
+ {
+ m_pBuffer = nullptr;
+
+ String BuffName = String{GetDesc().Name} + " - internal buffer";
+ BufferDesc BuffDesc;
+ BuffDesc.Name = BuffName.c_str();
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.BindFlags = BIND_RAY_TRACING;
+ BuffDesc.uiSizeInBytes = BufSize;
+
+ GetDevice()->CreateBuffer(BuffDesc, nullptr, &m_pBuffer);
+ VERIFY_EXPR(m_pBuffer != nullptr);
+ }
+
+ if (m_pBuffer == nullptr)
+ return; // something goes wrong
+
+ const D3D12_GPU_VIRTUAL_ADDRESS BuffHandle = m_pBuffer.RawPtr<BufferD3D12Impl>()->GetGPUAddress(0, ValidatedCast<DeviceContextD3D12Impl>(pContext));
+
+ if (m_RayGenShaderRecord.size())
+ {
+ RaygenShaderBindingTable.StartAddress = BuffHandle + RayGenOffset;
+ RaygenShaderBindingTable.SizeInBytes = m_RayGenShaderRecord.size();
+ }
+
+ if (m_MissShadersRecord.size())
+ {
+ MissShaderBindingTable.StartAddress = BuffHandle + MissShaderOffset;
+ MissShaderBindingTable.SizeInBytes = m_MissShadersRecord.size();
+ MissShaderBindingTable.StrideInBytes = m_ShaderRecordStride;
+ }
+
+ if (m_HitGroupsRecord.size())
+ {
+ HitShaderBindingTable.StartAddress = BuffHandle + HitGroupOffset;
+ HitShaderBindingTable.SizeInBytes = m_HitGroupsRecord.size();
+ HitShaderBindingTable.StrideInBytes = m_ShaderRecordStride;
+ }
+
+ if (m_CallableShadersRecord.size())
+ {
+ CallableShaderBindingTable.StartAddress = BuffHandle + CallableShadersOffset;
+ CallableShaderBindingTable.SizeInBytes = m_CallableShadersRecord.size();
+ CallableShaderBindingTable.StrideInBytes = m_ShaderRecordStride;
+ }
+
+ if (!m_Changed)
+ return;
+
+ m_Changed = false;
+
+ // update buffer data
+ if (m_RayGenShaderRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, RayGenOffset, static_cast<Uint32>(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode);
+
+ if (m_MissShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast<Uint32>(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode);
+
+ if (m_HitGroupsRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast<Uint32>(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode);
+
+ if (m_CallableShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast<Uint32>(m_CallableShadersRecord.size()), m_CallableShadersRecord.data(), TransitionMode);
+
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ StateTransitionDesc Barrier;
+ Barrier.pResource = m_pBuffer;
+ Barrier.NewState = RESOURCE_STATE_RAY_TRACING;
+ Barrier.UpdateResourceState = true;
+ pContext->TransitionResourceStates(1, &Barrier);
+ }
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ VERIFY_EXPR(m_pBuffer->GetState() == RESOURCE_STATE_RAY_TRACING);
+ }
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
index b4bb1f72..6dbdb97f 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
@@ -40,6 +40,7 @@
#include "ShaderResourceVariableBase.hpp"
#include "ShaderVariableD3DBase.hpp"
#include "LinearAllocator.hpp"
+#include "TopLevelASD3D12.h"
namespace Diligent
{
@@ -622,6 +623,35 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheAccelStruct(IDeviceObject*
Uint32 ArrayIndex,
D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const
{
+ VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point");
+ VERIFY_EXPR(ArrayIndex < Attribs.BindCount);
+
+ RefCntAutoPtr<ITopLevelASD3D12> pTLASD3D12(pTLAS, IID_TopLevelASD3D12);
+ if (pTLASD3D12)
+ {
+ if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
+ {
+ // Do not update resource if one is already bound unless it is dynamic. This may be
+ // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor.
+ return;
+ }
+
+ DstRes.Type = GetResType();
+ DstRes.CPUDescriptorHandle = pTLASD3D12->GetCPUDescriptorHandle();
+ VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 resource");
+
+ if (ShdrVisibleHeapCPUDescriptorHandle.ptr != 0)
+ {
+ // Dynamic resources are assigned descriptor in the GPU-visible heap at every draw call, and
+ // the descriptor is copied by the RootSignature when resources are committed
+ VERIFY(DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once");
+
+ ID3D12Device* pd3d12Device = ParentResLayout.m_pd3d12Device;
+ pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+
+ DstRes.pObject = std::move(pTLASD3D12);
+ }
}
const ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv) const
diff --git a/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp
new file mode 100644
index 00000000..5f411640
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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 "pch.h"
+#include "TopLevelASD3D12Impl.hpp"
+#include "RenderDeviceD3D12Impl.hpp"
+#include "DeviceContextD3D12Impl.hpp"
+#include "D3D12TypeConversions.hpp"
+#include "GraphicsAccessories.hpp"
+#include "DXGITypeConversions.hpp"
+#include "EngineMemory.h"
+#include "StringTools.hpp"
+
+namespace Diligent
+{
+
+TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounters,
+ class RenderDeviceD3D12Impl* pDeviceD3D12,
+ const TopLevelASDesc& Desc,
+ bool bIsDeviceInternal) :
+ TTopLevelASBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal}
+{
+ D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO TopLevelPrebuildInfo = {};
+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS TopLevelInputs = {};
+
+ TopLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
+ TopLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE;
+ TopLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
+ TopLevelInputs.NumDescs = Desc.MaxInstanceCount;
+
+ VERIFY_EXPR(Desc.MaxInstanceCount <= D3D12_RAYTRACING_MAX_INSTANCES_PER_TOP_LEVEL_ACCELERATION_STRUCTURE);
+
+ auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5();
+
+ pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&TopLevelInputs, &TopLevelPrebuildInfo);
+ if (TopLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0)
+ LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info");
+
+ 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;
+
+ D3D12_RESOURCE_DESC ASDesc = {};
+ ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ ASDesc.Alignment = 0;
+ ASDesc.Width = TopLevelPrebuildInfo.ResultDataMaxSizeInBytes;
+ ASDesc.Height = 1;
+ ASDesc.DepthOrArraySize = 1;
+ ASDesc.MipLevels = 1;
+ ASDesc.Format = DXGI_FORMAT_UNKNOWN;
+ ASDesc.SampleDesc.Count = 1;
+ ASDesc.SampleDesc.Quality = 0;
+ ASDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ ASDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,
+ &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr,
+ __uuidof(m_pd3d12Resource),
+ reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource)));
+ if (FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create D3D12 Top-level acceleration structure");
+
+ if (*m_Desc.Name != 0)
+ m_pd3d12Resource->SetName(WidenString(m_Desc.Name).c_str());
+
+ m_ScratchSize.Build = static_cast<Uint32>(TopLevelPrebuildInfo.ScratchDataSizeInBytes);
+ m_ScratchSize.Update = static_cast<Uint32>(TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes);
+
+ m_DescriptorHandle = pDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ 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 = GetGPUAddress();
+ pd3d12Device->CreateShaderResourceView(nullptr, &SRVDesc, m_DescriptorHandle.GetCpuHandle());
+}
+
+TopLevelASD3D12Impl::~TopLevelASD3D12Impl()
+{
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ auto* pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12Impl->SafeReleaseDeviceObject(std::move(m_pd3d12Resource), m_Desc.CommandQueueMask);
+}
+
+IMPLEMENT_QUERY_INTERFACE(TopLevelASD3D12Impl, IID_TopLevelASD3D12, TTopLevelASBase)
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
index 8f1b4c37..0b2154e6 100644
--- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
@@ -40,6 +40,8 @@
#include "FramebufferGLImpl.hpp"
#include "RenderPassGLImpl.hpp"
#include "PipelineStateGLImpl.hpp"
+#include "BottomLevelASBase.hpp"
+#include "TopLevelASBase.hpp"
namespace Diligent
{
@@ -53,6 +55,8 @@ struct DeviceContextGLImplTraits
using QueryType = QueryGLImpl;
using FramebufferType = FramebufferGLImpl;
using RenderPassType = RenderPassGLImpl;
+ using BottomLevelASType = BottomLevelASBase<IBottomLevelAS, RenderDeviceGLImpl>;
+ using TopLevelASType = TopLevelASBase<ITopLevelAS, RenderDeviceGLImpl>;
};
/// Device context implementation in OpenGL backend.
diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
index eb485370..e907337d 100644
--- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
@@ -50,10 +50,20 @@ public:
bool bIsDeviceInternal = false);
~BottomLevelASVkImpl();
+ /// Implementation of IBottomLevelAS::GetScratchBufferSizes() in Vulkan backend.
virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
+ /// Implementation of IBottomLevelAS::GetNativeHandle() in Vulkan backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final
+ {
+ auto Handle = GetVkBLAS();
+ return reinterpret_cast<void*>(Handle);
+ }
+
+ /// Implementation of IBottomLevelASVk::GetVkBLAS().
virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkBLAS() const override { return m_VulkanBLAS; }
+ /// Implementation of IBottomLevelASVk::GetVkDeviceAddress().
virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; }
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelASVk, TBottomLevelASBase);
@@ -62,6 +72,7 @@ private:
VkDeviceAddress m_DeviceAddress = 0;
VulkanUtilities::AccelStructWrapper m_VulkanBLAS;
VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation;
+ VkDeviceSize m_MemoryAlignedOffset = 0;
ScratchBufferSizes m_ScratchSize;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
index 98438da3..41a8cac3 100644
--- a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
@@ -137,17 +137,7 @@ public:
std::string PoolName,
std::vector<VkDescriptorPoolSize> PoolSizes,
uint32_t MaxSets,
- bool AllowFreeing) noexcept:
- m_DeviceVkImpl{DeviceVkImpl },
- m_PoolName {std::move(PoolName) },
- m_PoolSizes (std::move(PoolSizes)),
- m_MaxSets {MaxSets },
- m_AllowFreeing{AllowFreeing }
- {
-#ifdef DILIGENT_DEVELOPMENT
- m_AllocatedPoolCounter = 0;
-#endif
- }
+ bool AllowFreeing) noexcept;
~DescriptorPoolManager();
DescriptorPoolManager (const DescriptorPoolManager&) = delete;
@@ -175,9 +165,9 @@ protected:
RenderDeviceVkImpl& m_DeviceVkImpl;
const std::string m_PoolName;
- const std::vector<VkDescriptorPoolSize> m_PoolSizes;
- const uint32_t m_MaxSets;
- const bool m_AllowFreeing;
+ std::vector<VkDescriptorPoolSize> m_PoolSizes;
+ const uint32_t m_MaxSets;
+ const bool m_AllowFreeing;
std::mutex m_Mutex;
std::deque<VulkanUtilities::DescriptorPoolWrapper> m_Pools;
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
index 26142ba0..40e19d80 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
@@ -50,6 +50,9 @@
#include "HashUtils.hpp"
#include "ManagedVulkanObject.hpp"
#include "QueryManagerVk.hpp"
+#include "BottomLevelASVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
+#include "ShaderBindingTableVkImpl.hpp"
namespace Diligent
@@ -65,6 +68,8 @@ struct DeviceContextVkImplTraits
using QueryType = QueryVkImpl;
using FramebufferType = FramebufferVkImpl;
using RenderPassType = RenderPassVkImpl;
+ using BottomLevelASType = BottomLevelASVkImpl;
+ using TopLevelASType = TopLevelASVkImpl;
};
/// Device context implementation in Vulkan backend.
@@ -294,6 +299,20 @@ public:
virtual void DILIGENT_CALL_TYPE BufferMemoryBarrier(IBuffer* pBuffer, VkAccessFlags NewAccessFlags) override final;
+ // Transitions BLAS state from OldState to NewState, and optionally updates internal state.
+ // If OldState == RESOURCE_STATE_UNKNOWN, internal BLAS state is used as old state.
+ void TransitionBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState);
+
+ // Transitions TLAS state from OldState to NewState, and optionally updates internal state.
+ // If OldState == RESOURCE_STATE_UNKNOWN, internal TLAS state is used as old state.
+ void TransitionTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState);
+
void AddWaitSemaphore(ManagedSemaphore* pWaitSemaphore, VkPipelineStageFlags WaitDstStageMask)
{
VERIFY_EXPR(pWaitSemaphore != nullptr);
@@ -386,6 +405,15 @@ private:
VkImageLayout ExpectedLayout,
const char* OperationName);
+ __forceinline void TransitionOrVerifyBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
+
+ __forceinline void TransitionOrVerifyTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
__forceinline void EnsureVkCmdBuffer()
{
@@ -438,6 +466,7 @@ private:
__forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType);
__forceinline BufferVkImpl* PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode);
__forceinline void PrepareForDispatchCompute();
+ __forceinline void PrepareForRayTracing();
void DvpLogRenderPass_PSOMismatch();
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 6abe5213..e13f1a76 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -178,16 +178,16 @@ public:
FramebufferCache& GetFramebufferCache() { return m_FramebufferCache; }
RenderPassCache& GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache; }
- VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties)
+ VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties, VkMemoryAllocateFlags AllocateFlags = 0)
{
- return m_MemoryMgr.Allocate(MemReqs, MemoryProperties);
+ return m_MemoryMgr.Allocate(MemReqs, MemoryProperties, AllocateFlags);
}
- VulkanUtilities::VulkanMemoryAllocation AllocateMemory(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex)
+ VulkanUtilities::VulkanMemoryAllocation AllocateMemory(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, VkMemoryAllocateFlags AllocateFlags = 0)
{
const auto& MemoryProps = m_PhysicalDevice->GetMemoryProperties();
VERIFY_EXPR(MemoryTypeIndex < MemoryProps.memoryTypeCount);
const auto MemoryFlags = MemoryProps.memoryTypes[MemoryTypeIndex].propertyFlags;
- return m_MemoryMgr.Allocate(Size, Alignment, MemoryTypeIndex, (MemoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0);
+ return m_MemoryMgr.Allocate(Size, Alignment, MemoryTypeIndex, (MemoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0, AllocateFlags);
}
VulkanUtilities::VulkanMemoryManager& GetGlobalMemoryManager() { return m_MemoryMgr; }
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
index 92d83160..1b2db950 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
@@ -30,20 +30,20 @@
/// \file
/// Definition of the Diligent::ShaderBindingTableVkImpl class
-#include "BufferVkImpl.hpp"
#include "RenderDeviceVk.h"
#include "RenderDeviceVkImpl.hpp"
#include "ShaderBindingTableVk.h"
#include "ShaderBindingTableBase.hpp"
+#include "PipelineStateVkImpl.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
namespace Diligent
{
-class ShaderBindingTableVkImpl final : public ShaderBindingTableBase<IShaderBindingTableVk, RenderDeviceVkImpl>
+class ShaderBindingTableVkImpl final : public ShaderBindingTableBase<IShaderBindingTableVk, PipelineStateVkImpl, RenderDeviceVkImpl>
{
public:
- using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableVk, RenderDeviceVkImpl>;
+ using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableVk, PipelineStateVkImpl, RenderDeviceVkImpl>;
ShaderBindingTableVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pRenderDeviceVk,
@@ -56,37 +56,14 @@ public:
virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override;
virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override;
-
- virtual void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindHitGroup(ITopLevelAS* pTLAS,
- const char* InstanceName,
- const char* GeometryName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindHitGroups(ITopLevelAS* pTLAS,
- const char* InstanceName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindCallableShader(Uint32 Index,
- const char* ShaderName,
- const void* Data,
- Uint32 DataSize) override;
-
virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override;
- virtual void DILIGENT_CALL_TYPE GetVkStridedBufferRegions(VkStridedBufferRegionKHR& RaygenShaderBindingTable,
- VkStridedBufferRegionKHR& MissShaderBindingTable,
- VkStridedBufferRegionKHR& HitShaderBindingTable,
- VkStridedBufferRegionKHR& CallableShaderBindingTable) override;
+ virtual void DILIGENT_CALL_TYPE GetVkStridedBufferRegions(IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR& RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR& MissShaderBindingTable,
+ VkStridedBufferRegionKHR& HitShaderBindingTable,
+ VkStridedBufferRegionKHR& CallableShaderBindingTable) override;
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase);
@@ -94,17 +71,7 @@ private:
void ValidateDesc(const ShaderBindingTableDesc& Desc) const;
private:
- RefCntAutoPtr<BufferVkImpl> m_pBuffer;
- std::vector<Uint32> m_ShaderRecords;
-
- Uint32 m_MissShadersOffset = 0;
- Uint32 m_HitGroupsOffset = 0;
- Uint32 m_CallbaleShadersOffset = 0;
- Uint32 m_MissShaderCount = 0;
- Uint32 m_HitGroupCount = 0;
- Uint32 m_CallableShaderCount = 0;
- Uint32 m_ShaderGroupHandleSize = 0;
- Uint32 m_ShaderGroupBaseAlignment = 0;
+ RefCntAutoPtr<IBuffer> m_pBuffer;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
index 11c1ebef..b2801eca 100644
--- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
@@ -50,18 +50,27 @@ public:
bool bIsDeviceInternal = false);
~TopLevelASVkImpl();
+ /// Implementation of ITopLevelAS::GetScratchBufferSizes() in Vulkan backend.
virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
- virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; }
+ /// Implementation of ITopLevelAS::GetNativeHandle() in Vulkan backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final
+ {
+ auto Handle = GetVkTLAS();
+ return reinterpret_cast<void*>(Handle);
+ }
- virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; }
+ /// Implementation of ITopLevelASVk::GetVkTLAS().
+ virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; }
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase);
+ const VkAccelerationStructureKHR* GetVkTLASPtr() const { return &m_VulkanTLAS; }
+
private:
- VkDeviceAddress m_DeviceAddress = 0;
VulkanUtilities::AccelStructWrapper m_VulkanTLAS;
VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation;
+ VkDeviceSize m_MemoryAlignedOffset = 0;
ScratchBufferSizes m_ScratchSize;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index e88c93d2..8f90a914 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -65,8 +65,9 @@ VkSamplerMipmapMode FilterTypeToVkMipmapMode(FILTER_TYPE FilterType);
VkSamplerAddressMode AddressModeToVkAddressMode(TEXTURE_ADDRESS_MODE AddressMode);
VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[]);
-VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags);
-VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false);
+VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages);
+VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags);
+VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false);
RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags);
RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout);
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
index 0cd6de63..50a4c99f 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
@@ -36,8 +36,8 @@ namespace VulkanUtilities
class VulkanCommandBuffer
{
public:
- VulkanCommandBuffer(VkPipelineStageFlags EnabledGraphicsShaderStages) noexcept :
- m_EnabledGraphicsShaderStages{EnabledGraphicsShaderStages}
+ VulkanCommandBuffer(VkPipelineStageFlags EnabledShaderStages) noexcept :
+ m_EnabledShaderStages{EnabledShaderStages}
{}
// clang-format off
@@ -280,6 +280,17 @@ public:
}
}
+ __forceinline void BindRayTracingPipeline(VkPipeline RayTracingPipeline)
+ {
+ // 9.8
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RayTracingPipeline != RayTracingPipeline)
+ {
+ vkCmdBindPipeline(m_VkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, RayTracingPipeline);
+ m_State.RayTracingPipeline = RayTracingPipeline;
+ }
+ }
+
__forceinline void SetViewports(uint32_t FirstViewport, uint32_t ViewportCount, const VkViewport* pViewports)
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
@@ -331,7 +342,7 @@ public:
VkImageLayout OldLayout,
VkImageLayout NewLayout,
const VkImageSubresourceRange& SubresRange,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages = 0,
VkPipelineStageFlags DestStages = 0);
@@ -349,7 +360,7 @@ public:
// dependencies between attachments
EndRenderPass();
}
- TransitionImageLayout(m_VkCmdBuffer, Image, OldLayout, NewLayout, SubresRange, m_EnabledGraphicsShaderStages, SrcStages, DestStages);
+ TransitionImageLayout(m_VkCmdBuffer, Image, OldLayout, NewLayout, SubresRange, m_EnabledShaderStages, SrcStages, DestStages);
}
@@ -357,7 +368,7 @@ public:
VkBuffer Buffer,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages = 0,
VkPipelineStageFlags DestStages = 0);
@@ -374,7 +385,31 @@ public:
// dependencies between attachments
EndRenderPass();
}
- BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, m_EnabledGraphicsShaderStages, SrcStages, DestStages);
+ BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, m_EnabledShaderStages, SrcStages, DestStages);
+ }
+
+
+ // for Acceleration structures
+ static void ASMemoryBarrier(VkCommandBuffer CmdBuffer,
+ VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags EnabledShaderStages,
+ VkPipelineStageFlags SrcStages = 0,
+ VkPipelineStageFlags DestStages = 0);
+
+ __forceinline void ASMemoryBarrier(VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags SrcStages = 0,
+ VkPipelineStageFlags DestStages = 0)
+ {
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Image layout transitions within a render pass execute
+ // dependencies between attachments
+ EndRenderPass();
+ }
+ ASMemoryBarrier(m_VkCmdBuffer, srcAccessMask, dstAccessMask, m_EnabledShaderStages, SrcStages, DestStages);
}
__forceinline void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
@@ -575,6 +610,12 @@ public:
const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Build AS operations must be performed outside of render pass.
+ EndRenderPass();
+ }
vkCmdBuildAccelerationStructureKHR(m_VkCmdBuffer, infoCount, pInfos, ppOffsetInfos);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -584,6 +625,12 @@ public:
__forceinline void CopyAccelerationStructure(const VkCopyAccelerationStructureInfoKHR& Info)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Copy AS operations must be performed outside of render pass.
+ EndRenderPass();
+ }
vkCmdCopyAccelerationStructureKHR(m_VkCmdBuffer, &Info);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -599,6 +646,9 @@ public:
uint32_t depth)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ VERIFY(m_State.RayTracingPipeline != VK_NULL_HANDLE, "No ray tracing pipeline bound");
+
vkCmdTraceRaysKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, width, height, depth);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -613,12 +663,15 @@ public:
}
VkCommandBuffer GetVkCmdBuffer() const { return m_VkCmdBuffer; }
+ VkPipelineStageFlags GetEnabledShaderStages() const { return m_EnabledShaderStages; }
+
struct StateCache
{
VkRenderPass RenderPass = VK_NULL_HANDLE;
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
VkPipeline ComputePipeline = VK_NULL_HANDLE;
+ VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
VkBuffer IndexBuffer = VK_NULL_HANDLE;
VkDeviceSize IndexBufferOffset = 0;
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
@@ -633,7 +686,7 @@ public:
private:
StateCache m_State;
VkCommandBuffer m_VkCmdBuffer = VK_NULL_HANDLE;
- const VkPipelineStageFlags m_EnabledGraphicsShaderStages;
+ const VkPipelineStageFlags m_EnabledShaderStages;
};
} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
index 5e60a343..f68d7138 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
@@ -219,8 +219,9 @@ public:
dataSize, pData, stride, flags);
}
- VkPipelineStageFlags GetEnabledGraphicsShaderStages() const { return m_EnabledGraphicsShaderStages; }
- VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const;
+ VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const;
+
+ VkPipelineStageFlags GetEnabledShaderStages() const { return m_EnabledShaderStages; }
const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; }
const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; }
@@ -242,7 +243,7 @@ private:
VkDevice m_VkDevice = VK_NULL_HANDLE;
const VkAllocationCallbacks* const m_VkAllocator;
- VkPipelineStageFlags m_EnabledGraphicsShaderStages = 0;
+ VkPipelineStageFlags m_EnabledShaderStages = 0;
const VkPhysicalDeviceFeatures m_EnabledFeatures;
ExtensionFeatures m_EnabledExtFeatures = {};
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
index 4ada51be..4d9eaa7f 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
@@ -95,10 +95,11 @@ struct VulkanMemoryAllocation
class VulkanMemoryPage
{
public:
- VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
- VkDeviceSize PageSize,
- uint32_t MemoryTypeIndex,
- bool IsHostVisible) noexcept;
+ VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
+ VkDeviceSize PageSize,
+ uint32_t MemoryTypeIndex,
+ bool IsHostVisible,
+ VkMemoryAllocateFlags AllocateFlags) noexcept;
~VulkanMemoryPage();
// clang-format off
@@ -198,8 +199,8 @@ public:
VulkanMemoryManager& operator= (VulkanMemoryManager&&) = delete;
// clang-format on
- VulkanMemoryAllocation Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible);
- VulkanMemoryAllocation Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps);
+ VulkanMemoryAllocation Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible, VkMemoryAllocateFlags AllocateFlags);
+ VulkanMemoryAllocation Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps, VkMemoryAllocateFlags AllocateFlags);
void ShrinkMemory();
protected:
@@ -218,19 +219,23 @@ protected:
std::mutex m_PagesMtx;
struct MemoryPageIndex
{
- const uint32_t MemoryTypeIndex;
- const bool IsHostVisible;
+ const uint32_t MemoryTypeIndex;
+ const VkMemoryAllocateFlags AllocateFlags;
+ const bool IsHostVisible;
// clang-format off
- MemoryPageIndex(uint32_t _MemoryTypeIndex,
- bool _IsHostVisible) :
- MemoryTypeIndex(_MemoryTypeIndex),
- IsHostVisible (_IsHostVisible)
+ MemoryPageIndex(uint32_t _MemoryTypeIndex,
+ bool _IsHostVisible,
+ VkMemoryAllocateFlags _AllocateFlags) :
+ MemoryTypeIndex{_MemoryTypeIndex},
+ AllocateFlags {_AllocateFlags},
+ IsHostVisible {_IsHostVisible}
{}
bool operator == (const MemoryPageIndex& rhs)const
{
return MemoryTypeIndex == rhs.MemoryTypeIndex &&
+ AllocateFlags == rhs.AllocateFlags &&
IsHostVisible == rhs.IsHostVisible;
}
// clang-format on
@@ -239,7 +244,7 @@ protected:
{
size_t operator()(const MemoryPageIndex& PageIndex) const
{
- return Diligent::ComputeHash(PageIndex.MemoryTypeIndex, PageIndex.IsHostVisible);
+ return Diligent::ComputeHash(PageIndex.MemoryTypeIndex, PageIndex.AllocateFlags, PageIndex.IsHostVisible);
}
};
};
diff --git a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
index 345b0f3b..ea785a51 100644
--- a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
@@ -61,7 +61,8 @@ DILIGENT_END_INTERFACE
#if DILIGENT_C_INTERFACE
-# define IBottomLevelASVk_GetVkBLAS(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkBLAS, This)
+# define IBottomLevelASVk_GetVkBLAS(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkBLAS, This)
+# define IBottomLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkDeviceAddress, This)
#endif
diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
index 76e0eadd..d879faac 100644
--- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
@@ -31,6 +31,7 @@
/// Definition of the Diligent::IShaderBindingTableVk interface
#include "../../GraphicsEngine/interface/ShaderBindingTable.h"
+#include "DeviceContextVk.h"
DILIGENT_BEGIN_NAMESPACE(Diligent)
@@ -51,10 +52,12 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable)
{
/// AZ TODO
VIRTUAL void METHOD(GetVkStridedBufferRegions)(THIS_
- VkStridedBufferRegionKHR REF RaygenShaderBindingTable,
- VkStridedBufferRegionKHR REF MissShaderBindingTable,
- VkStridedBufferRegionKHR REF HitShaderBindingTable,
- VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE;
+ IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR REF RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR REF MissShaderBindingTable,
+ VkStridedBufferRegionKHR REF HitShaderBindingTable,
+ VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE;
};
DILIGENT_END_INTERFACE
// clang-format on
diff --git a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
index c09f10c0..161de182 100644
--- a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
@@ -50,9 +50,6 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelASVk, ITopLevelAS)
{
/// Returns a Vulkan TLAS object handle.
VIRTUAL VkAccelerationStructureKHR METHOD(GetVkTLAS)(THIS) CONST PURE;
-
- /// Returns a Vulkan TLAS device address.
- VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -60,8 +57,7 @@ DILIGENT_END_INTERFACE
#if DILIGENT_C_INTERFACE
-# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This)
-# define ITopLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkDeviceAddress, This)
+# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This)
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
index 6e0bcbb8..a1172130 100644
--- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
@@ -60,7 +60,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
if (m_Desc.pTriangles != nullptr)
{
Uint32 MaxPrimitiveCount = 0;
- for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i)
+ for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i)
{
auto& src = m_Desc.pTriangles[i];
auto& dst = Geometries[i];
@@ -81,7 +81,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
else if (m_Desc.pBoxes != nullptr)
{
Uint32 MaxBoxCount = 0;
- for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i)
+ for (uint32_t i = 0; i < m_Desc.BoxCount; ++i)
{
auto& src = m_Desc.pBoxes[i];
auto& dst = Geometries[i];
@@ -122,10 +122,12 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Failed to find suitable memory type for BLAS '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
+ VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_MemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindASMemory(m_VulkanBLAS, Memory, 0);
+ auto err = LogicalDevice.BindASMemory(m_VulkanBLAS, Memory, m_MemoryAlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory");
m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS);
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 6b29af25..ef6685a3 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -87,7 +87,7 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | // The buffer can be used as the source of a transfer command
VK_BUFFER_USAGE_TRANSFER_DST_BIT; // The buffer can be used as the destination of a transfer command
- static_assert(BIND_FLAGS_LAST == 0x400, "AZ TODO");
+ static_assert(BIND_FLAGS_LAST == 0x400, "Please update this function to handle the new bind flags");
for (Uint32 BindFlag = 1; BindFlag <= m_Desc.BindFlags; BindFlag <<= 1)
{
@@ -245,11 +245,15 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, vkMemoryFlags);
}
+ VkMemoryAllocateFlags AllocateFlags = 0;
+ if (VkBuffCI.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
+ AllocateFlags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
+
if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
LOG_ERROR_AND_THROW("Failed to find suitable memory type for buffer '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, AllocateFlags);
m_BufferMemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_BufferMemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
@@ -317,12 +321,12 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VkCommandBuffer vkCmdBuff;
pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
- auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledGraphicsShaderStages);
+ auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledShaderStages);
InitialState = RESOURCE_STATE_COPY_DEST;
VkAccessFlags AccessFlags = ResourceStateFlagsToVkAccessFlags(InitialState);
VERIFY_EXPR(AccessFlags == VK_ACCESS_TRANSFER_WRITE_BIT);
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledGraphicsShaderStages);
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledShaderStages);
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
index e7fbc9bd..6d0e1ab2 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
@@ -53,14 +53,17 @@ VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(cons
{
std::lock_guard<std::mutex> LockGuard{m_Mutex};
+ auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
+
VulkanUtilities::CommandPoolWrapper CmdPool;
if (!m_CmdPools.empty())
{
CmdPool = std::move(m_CmdPools.front());
m_CmdPools.pop_front();
+
+ LogicalDevice.ResetCommandPool(CmdPool);
}
- auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
if (CmdPool == VK_NULL_HANDLE)
{
VkCommandPoolCreateInfo CmdPoolCI = {};
@@ -74,8 +77,6 @@ VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(cons
DEV_CHECK_ERR(CmdPool != VK_NULL_HANDLE, "Failed to create Vulkan command pool");
}
- LogicalDevice.ResetCommandPool(CmdPool);
-
#ifdef DILIGENT_DEVELOPMENT
++m_AllocatedPoolCounter;
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
index 412ddd7b..6557ac6d 100644
--- a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
@@ -59,6 +59,41 @@ VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::CreateDescriptorPo
return m_DeviceVkImpl.GetLogicalDevice().CreateDescriptorPool(PoolCI, DebugName);
}
+DescriptorPoolManager::DescriptorPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
+ std::string PoolName,
+ std::vector<VkDescriptorPoolSize> PoolSizes,
+ uint32_t MaxSets,
+ bool AllowFreeing) noexcept :
+ // clang-format off
+ m_DeviceVkImpl{DeviceVkImpl },
+ m_PoolName {std::move(PoolName) },
+ m_PoolSizes (std::move(PoolSizes)),
+ m_MaxSets {MaxSets },
+ m_AllowFreeing{AllowFreeing }
+// clang-format on
+{
+ const auto& Feats = m_DeviceVkImpl.GetLogicalDevice().GetEnabledExtFeatures();
+
+ for (auto iter = m_PoolSizes.begin(); iter != m_PoolSizes.end();)
+ {
+ switch (iter->type)
+ {
+ case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
+ if (Feats.RayTracing.rayTracing == VK_FALSE)
+ iter = m_PoolSizes.erase(iter);
+ else
+ ++iter;
+ break;
+ default:
+ ++iter;
+ }
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ m_AllocatedPoolCounter = 0;
+#endif
+}
+
DescriptorPoolManager::~DescriptorPoolManager()
{
DEV_CHECK_ERR(m_AllocatedPoolCounter == 0, "Not all allocated descriptor pools are returned to the pool manager");
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 42f69dac..554352ad 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -36,9 +36,6 @@
#include "VulkanTypeConversions.hpp"
#include "CommandListVkImpl.hpp"
#include "FenceVkImpl.hpp"
-#include "BottomLevelASVkImpl.hpp"
-#include "TopLevelASVkImpl.hpp"
-#include "ShaderBindingTableVkImpl.hpp"
#include "GraphicsAccessories.hpp"
namespace Diligent
@@ -72,7 +69,7 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p
bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdBuffer,
bIsDeferred
},
- m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() },
+ m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledShaderStages() },
m_CmdListAllocator { GetRawAllocator(), sizeof(CommandListVkImpl), 64 },
// Command pools must be thread safe because command buffers are returned into pools by release queues
// potentially running in another thread
@@ -303,7 +300,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
}
case PIPELINE_TYPE_RAY_TRACING:
{
- //m_CommandBuffer.BindRayTracingPipeline(vkPipeline);
+ m_CommandBuffer.BindRayTracingPipeline(vkPipeline);
break;
}
default:
@@ -659,6 +656,19 @@ void DeviceContextVkImpl::PrepareForDispatchCompute()
#endif
}
+void DeviceContextVkImpl::PrepareForRayTracing()
+{
+ EnsureVkCmdBuffer();
+
+ if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ {
+ if (!m_DescrSetBindInfo.DynamicDescriptorsBound || m_DescrSetBindInfo.DynamicBuffersPresent)
+ {
+ m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
+ }
+ }
+}
+
void DeviceContextVkImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
{
if (!DvpVerifyDispatchArguments(Attribs))
@@ -2390,7 +2400,9 @@ void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& Textur
// to make sure that all UAV writes are complete and visible.
auto OldLayout = ResourceStateToVkImageLayout(OldState);
auto NewLayout = ResourceStateToVkImageLayout(NewState);
- m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange);
+ 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)
{
TextureVk.SetState(NewState);
@@ -2479,7 +2491,7 @@ 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)
+ if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS || NewState == RESOURCE_STATE_BUILD_AS_WRITE)
{
DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
@@ -2488,7 +2500,9 @@ void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE
auto vkBuff = BufferVk.GetVkBuffer();
auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
- m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags, OldStages, NewStages);
if (UpdateBufferState)
{
BufferVk.SetState(NewState);
@@ -2522,6 +2536,142 @@ void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl&
#endif
}
+void DeviceContextVkImpl::TransitionBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState)
+{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+ if (OldState == RESOURCE_STATE_UNKNOWN)
+ {
+ if (BLAS.IsInKnownState())
+ {
+ OldState = BLAS.GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of BLAS '", BLAS.GetDesc().Name, "' because the BLAS state is unknown and is not explicitly specified");
+ return;
+ }
+ }
+ else
+ {
+ if (BLAS.IsInKnownState() && BLAS.GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(BLAS.GetState()), " of BLAS '",
+ BLAS.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((OldState & NewState) != NewState)
+ {
+ EnsureVkCmdBuffer();
+ auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
+ auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages);
+ if (UpdateInternalState)
+ {
+ BLAS.SetState(NewState);
+ }
+ }
+}
+
+void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE OldState,
+ 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)
+ {
+ if (TLAS.IsInKnownState())
+ {
+ OldState = TLAS.GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of TLAS '", TLAS.GetDesc().Name, "' because the TLAS state is unknown and is not explicitly specified");
+ return;
+ }
+ }
+ else
+ {
+ if (TLAS.IsInKnownState() && TLAS.GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(TLAS.GetState()), " of TLAS '",
+ TLAS.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((OldState & NewState) != NewState)
+ {
+ EnsureVkCmdBuffer();
+ auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
+ auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages);
+ if (UpdateInternalState)
+ {
+ TLAS.SetState(NewState);
+ }
+ }
+}
+
+void DeviceContextVkImpl::TransitionOrVerifyBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ 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);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyBLASState(BLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
+void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ 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);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTLASState(TLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
VulkanDynamicAllocation DeviceContextVkImpl::AllocateDynamicSpace(Uint32 SizeInBytes, Uint32 Alignment)
{
auto DynAlloc = m_DynamicHeap.Allocate(SizeInBytes, Alignment);
@@ -2554,24 +2704,27 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra
}
VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
- if (Barrier.pTexture)
+ RefCntAutoPtr<TextureVkImpl> pTexture{Barrier.pResource, IID_TextureVk};
+ if (pTexture)
{
- auto* pTextureVkImpl = ValidatedCast<TextureVkImpl>(Barrier.pTexture);
-
VkImageSubresourceRange SubResRange;
SubResRange.aspectMask = 0;
SubResRange.baseMipLevel = Barrier.FirstMipLevel;
SubResRange.levelCount = (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS) ? VK_REMAINING_MIP_LEVELS : Barrier.MipLevelsCount;
SubResRange.baseArrayLayer = Barrier.FirstArraySlice;
SubResRange.layerCount = (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES) ? VK_REMAINING_ARRAY_LAYERS : Barrier.ArraySliceCount;
- TransitionTextureState(*pTextureVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
+ TransitionTextureState(*pTexture, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
+ continue;
}
- else
+
+ RefCntAutoPtr<BufferVkImpl> pBuffer{Barrier.pResource, IID_BufferVk};
+ if (pBuffer)
{
- VERIFY_EXPR(Barrier.pBuffer != nullptr);
- auto* pBufferVkImpl = ValidatedCast<BufferVkImpl>(Barrier.pBuffer);
- TransitionBufferState(*pBufferVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ TransitionBufferState(*pBuffer, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ continue;
}
+
+ UNEXPECTED("unsupported resource type");
}
}
@@ -2635,13 +2788,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
if (!TDeviceContextBase::BuildBLAS(Attribs, 0))
return;
-
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2649,6 +2799,12 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer);
auto& BLASDesc = pBLASVk->GetDesc();
+ EnsureVkCmdBuffer();
+
+ 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);
+
VkAccelerationStructureBuildGeometryInfoKHR Info = {};
std::vector<VkAccelerationStructureBuildOffsetInfoKHR> Offsets;
std::vector<VkAccelerationStructureGeometryKHR> Geometries;
@@ -2679,17 +2835,21 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
tri.pNext = nullptr;
- auto* pVB = ValidatedCast<IBufferVk>(src.pVertexBuffer);
+ auto* pVB = ValidatedCast<BufferVkImpl>(src.pVertexBuffer);
tri.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16);
tri.vertexStride = src.VertexStride;
tri.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + src.VertexOffset;
+ TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+
if (src.pIndexBuffer)
{
- auto* pIB = ValidatedCast<IBufferVk>(src.pIndexBuffer);
+ auto* pIB = ValidatedCast<BufferVkImpl>(src.pIndexBuffer);
tri.indexType = TypeToVkIndexType(src.IndexType);
tri.indexData.deviceAddress = pIB->GetVkDeviceAddress() + src.IndexOffset;
off.primitiveCount = src.IndexCount / 3;
+
+ TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
}
else
{
@@ -2700,11 +2860,18 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
if (src.pTransformBuffer)
{
- auto* pTB = ValidatedCast<IBufferVk>(src.pTransformBuffer);
+ VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms);
+
+ auto* pTB = ValidatedCast<BufferVkImpl>(src.pTransformBuffer);
tri.transformData.deviceAddress = pTB->GetVkDeviceAddress() + src.TransformBufferOffset;
+
+ TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
}
else
+ {
+ VERIFY_EXPR(!BLASDesc.pTriangles[j].AllowsTransforms);
tri.transformData.deviceAddress = 0;
+ }
off.firstVertex = 0;
off.primitiveOffset = 0;
@@ -2730,22 +2897,25 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
continue;
}
- auto* pBB = ValidatedCast<IBufferVk>(src.pBoxBuffer);
+ dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ dst.pNext = nullptr;
+ dst.flags = GeometryFlagsToVkGeometryFlags(src.Flags);
+ dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR;
+
+ auto* pBB = ValidatedCast<BufferVkImpl>(src.pBoxBuffer);
box.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR;
box.pNext = nullptr;
box.stride = src.BoxStride;
box.data.deviceAddress = pBB->GetVkDeviceAddress() + src.BoxOffset;
+ TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+
off.firstVertex = 0;
off.transformOffset = 0;
off.primitiveOffset = 0;
off.primitiveCount = src.BoxCount;
}
}
- else
- {
- UNEXPECTED("pTriangleData or pBoxData must not be null");
- }
VkAccelerationStructureGeometryKHR const* GeometriesPtr = Geometries.data();
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = Offsets.data();
@@ -2763,6 +2933,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
EnsureVkCmdBuffer();
m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
@@ -2770,23 +2941,27 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
if (!TDeviceContextBase::BuildTLAS(Attribs, 0))
return;
- static_assert(TLASInstanceDataSize == sizeof(VkAccelerationStructureInstanceKHR), "AZ TODO");
-
- // AZ TODO: transitions
+ static_assert(TLAS_INSTANCE_DATA_SIZE == sizeof(VkAccelerationStructureInstanceKHR), "Value in TLAS_INSTANCE_DATA_SIZE doesn't match the actual instance description size");
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
auto* pTLASVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pTLAS);
auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer);
- auto* pInstancesVk = ValidatedCast<BufferVkImpl>(Attribs.pInstancesBuffer);
+ auto* pInstancesVk = ValidatedCast<BufferVkImpl>(Attribs.pInstanceBuffer);
auto& TLASDesc = pTLASVk->GetDesc();
- pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount);
+ EnsureVkCmdBuffer();
+
+ 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);
+
+ pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance);
// copy instance data into instance buffer
{
@@ -2798,34 +2973,42 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
{
auto& src = Attribs.pInstances[i];
auto& dst = static_cast<VkAccelerationStructureInstanceKHR*>(pMappedInstances)[i];
- auto* pBLASVk = ValidatedCast<IBottomLevelASVk>(src.pBLAS);
+ auto* pBLASVk = ValidatedCast<BottomLevelASVkImpl>(src.pBLAS);
static_assert(sizeof(dst.transform) == sizeof(src.Transform), "size mismatch");
std::memcpy(&dst.transform, src.Transform, sizeof(dst.transform));
- dst.instanceCustomIndex = src.customId;
- dst.instanceShaderBindingTableRecordOffset = src.contributionToHitGroupIndex;
+ dst.instanceCustomIndex = src.CustomId;
+ dst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(src.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize
dst.mask = src.Mask;
dst.flags = InstanceFlagsToVkGeometryInstanceFlags(src.Flags);
dst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress();
+
+ TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
}
- UpdateBufferRegion(pInstancesVk, Attribs.InstancesBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode);
+ UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode);
}
+ TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
VkAccelerationStructureBuildGeometryInfoKHR Info = {};
VkAccelerationStructureBuildOffsetInfoKHR Offset = {};
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = &Offset;
- VkAccelerationStructureGeometryKHR Geometry = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
+ VkAccelerationStructureGeometryKHR Geometry = {};
VkAccelerationStructureGeometryKHR const* GeometriesPtr = &Geometry;
Offset.primitiveCount = Attribs.InstanceCount;
- Geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometry.pNext = nullptr;
+ Geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Geometry.flags = 0;
+
auto& inst = Geometry.geometry.instances;
inst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
+ inst.pNext = nullptr;
inst.arrayOfPointers = VK_FALSE;
- inst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstancesBufferOffset;
+ inst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstanceBufferOffset;
Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
Info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info
@@ -2838,8 +3021,8 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
Info.ppGeometries = &GeometriesPtr;
Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset;
- EnsureVkCmdBuffer();
m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
@@ -2847,12 +3030,10 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
if (!TDeviceContextBase::CopyBLAS(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2867,7 +3048,13 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode);
EnsureVkCmdBuffer();
+
+ const char* OpName = "Copy BottomLevelAS (DeviceContextVkImpl::CopyBLAS)";
+ TransitionOrVerifyBLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyBLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
m_CommandBuffer.CopyAccelerationStructure(Info);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
@@ -2875,11 +3062,11 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
if (!TDeviceContextBase::CopyTLAS(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
- auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE);
+ {
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ }
#endif
auto* pSrcVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pSrc);
@@ -2893,7 +3080,13 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode);
EnsureVkCmdBuffer();
+
+ const char* OpName = "Copy TopLevelAS (DeviceContextVkImpl::CopyTLAS)";
+ TransitionOrVerifyTLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyTLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
m_CommandBuffer.CopyAccelerationStructure(Info);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
@@ -2901,12 +3094,10 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
if (!TDeviceContextBase::TraceRays(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2916,12 +3107,12 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
VkStridedBufferRegionKHR CallableShaderBindingTable = {};
auto* pSBTVk = ValidatedCast<ShaderBindingTableVkImpl>(Attribs.pSBT);
+ pSBTVk->GetVkStridedBufferRegions(this, Attribs.TransitionMode, RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable);
- pSBTVk->GetVkStridedBufferRegions(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable);
-
- EnsureVkCmdBuffer();
+ PrepareForRayTracing();
m_CommandBuffer.TraceRays(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable,
Attribs.DimensionX, Attribs.DimensionY, Attribs.DimensionZ);
+ ++m_State.NumCommands;
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 8aaee7f7..548a9cf3 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -390,24 +390,32 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo&
#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ray tracing PSO '", CreateInfo.PSODesc.Name, "' is invalid: ", ##__VA_ARGS__)
ShaderGroups.reserve(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount);
- Uint32 GroupIndex = 0;
- Uint32 ShaderIndex = 0;
+ Uint32 GroupIndex = 0;
+ std::array<Uint32, 6> ShaderIndices = {};
std::unordered_map<const IShader*, Uint32> UniqueShaders;
- const auto ShaderToIndex = [&ShaderIndex, &UniqueShaders](const IShader* pShader) -> Uint32 {
+ const auto ShaderToIndex = [&ShaderIndices, &UniqueShaders](const IShader* pShader) -> Uint32 {
if (pShader != nullptr)
{
- auto Result = UniqueShaders.emplace(pShader, ShaderIndex);
+ Uint32& Index = ShaderIndices[GetShaderTypePipelineIndex(pShader->GetDesc().ShaderType, PIPELINE_TYPE_RAY_TRACING)];
+ auto Result = UniqueShaders.emplace(pShader, Index);
if (Result.second)
{
- ++ShaderIndex;
+ ++Index;
}
return Result.first->second;
}
return VK_SHADER_UNUSED_KHR;
};
+ Uint32 ShaderCount = 0;
+ for (auto& Stage : ShaderStages)
+ {
+ ShaderIndices[GetShaderTypePipelineIndex(Stage.Type, PIPELINE_TYPE_RAY_TRACING)] = ShaderCount;
+ ShaderCount += static_cast<Uint32>(Stage.Count());
+ }
+
for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i)
{
const auto& GeneralShader = CreateInfo.pGeneralShaders[i];
@@ -485,7 +493,7 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo&
++ShaderIndex2;
}
}
- VERIFY_EXPR(ShaderIndex == ShaderIndex2);
+ VERIFY_EXPR(UniqueShaders.size() == ShaderIndex2);
#endif
#undef LOG_PSO_ERROR_AND_THROW
}
diff --git a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
index fb09687b..ec94814e 100644
--- a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
@@ -97,7 +97,7 @@ QueryManagerVk::QueryManagerVk(RenderDeviceVkImpl* pRenderDeviceVk,
VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
- const auto EnabledShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
+ const auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
if (EnabledShaderStages & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)
{
QueryPoolCI.pipelineStatistics |=
diff --git a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
index 381ee631..a0801cb7 100644
--- a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
@@ -225,7 +225,7 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
{
auto& QueryData = *reinterpret_cast<QueryDataPipelineStatistics*>(pData);
- const auto EnabledShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
+ const auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
auto Idx = 0;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
index 36fa5af0..6f5091e0 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
@@ -27,6 +27,7 @@
#include "pch.h"
#include "ShaderBindingTableVkImpl.hpp"
+#include "BufferVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
namespace Diligent
@@ -40,10 +41,8 @@ ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters*
{
ValidateDesc(Desc);
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
-
- m_ShaderGroupHandleSize = Props.shaderGroupHandleSize;
- m_ShaderGroupBaseAlignment = Props.shaderGroupBaseAlignment;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
}
ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl()
@@ -52,12 +51,12 @@ ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl()
void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const
{
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
- if (Desc.ShaderRecordSize + Props.shaderGroupHandleSize > Props.maxShaderGroupStride)
+ 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: ", Props.maxShaderGroupStride - Props.shaderGroupHandleSize);
+ "' is invalid: ShaderRecordSize is too big, max size is: ", RTLimits.maxShaderGroupStride - RTLimits.shaderGroupHandleSize);
}
}
@@ -68,6 +67,12 @@ void ShaderBindingTableVkImpl::Verify() const
void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc)
{
+ m_RayGenShaderRecord.clear();
+ m_MissShadersRecord.clear();
+ m_CallableShadersRecord.clear();
+ m_HitGroupsRecord.clear();
+ m_Changed = true;
+
try
{
ValidateShaderBindingTableDesc(Desc);
@@ -75,116 +80,130 @@ void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc)
}
catch (const std::runtime_error&)
{
+ // AZ TODO
return;
}
m_Desc = Desc;
- // free memory
- decltype(m_ShaderRecords) temp{};
- std::swap(temp, m_ShaderRecords);
-
- m_MissShadersOffset = 0;
- m_HitGroupsOffset = 0;
- m_CallbaleShadersOffset = 0;
- m_MissShaderCount = 0;
- m_HitGroupCount = 0;
- m_CallableShaderCount = 0;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
}
void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance)
{
// AZ TODO
-}
-void ShaderBindingTableVkImpl::BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize)
-{
- // AZ TODO
+ m_Changed = true;
}
-void ShaderBindingTableVkImpl::BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize)
+void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs)
{
// AZ TODO
}
-void ShaderBindingTableVkImpl::BindHitGroup(ITopLevelAS* pTLAS,
- const char* InstanceName,
- const char* GeometryName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize)
+void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR& RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR& MissShaderBindingTable,
+ VkStridedBufferRegionKHR& HitShaderBindingTable,
+ VkStridedBufferRegionKHR& CallableShaderBindingTable)
{
- // AZ TODO
-}
+ const auto ShaderGroupBaseAlignment = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment;
-void ShaderBindingTableVkImpl::BindHitGroups(ITopLevelAS* pTLAS,
- const char* InstanceName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize)
-{
- // AZ TODO
-}
+ const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 {
+ return Align(static_cast<Uint32>(offset), ShaderGroupBaseAlignment);
+ };
-void ShaderBindingTableVkImpl::BindCallableShader(Uint32 Index,
- const char* ShaderName,
- const void* Data,
- Uint32 DataSize)
-{
- // AZ TODO
-}
+ const Uint32 RayGenOffset = 0;
+ const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size());
+ const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size());
+ const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size());
+ const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size());
-void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs)
-{
- // AZ TODO
-}
+ // recreate buffer
+ if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize)
+ {
+ m_pBuffer = nullptr;
-void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(VkStridedBufferRegionKHR& RaygenShaderBindingTable,
- VkStridedBufferRegionKHR& MissShaderBindingTable,
- VkStridedBufferRegionKHR& HitShaderBindingTable,
- VkStridedBufferRegionKHR& CallableShaderBindingTable)
-{
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ String BuffName = String{GetDesc().Name} + " - internal buffer";
+ BufferDesc BuffDesc;
+ BuffDesc.Name = BuffName.c_str();
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.BindFlags = BIND_RAY_TRACING;
+ BuffDesc.uiSizeInBytes = BufSize;
+
+ GetDevice()->CreateBuffer(BuffDesc, nullptr, &m_pBuffer);
+ VERIFY_EXPR(m_pBuffer != nullptr);
+ }
+
+ if (m_pBuffer == nullptr)
+ return; // something goes wrong
- const VkDeviceSize Stride = m_Desc.ShaderRecordSize + Props.shaderGroupHandleSize;
- VERIFY_EXPR(Stride <= Props.maxShaderGroupStride);
+ VkBuffer BuffHandle = m_pBuffer.RawPtr<BufferVkImpl>()->GetVkBuffer();
- RaygenShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- RaygenShaderBindingTable.offset = 0;
- RaygenShaderBindingTable.size = Stride;
- RaygenShaderBindingTable.stride = Stride;
+ if (m_RayGenShaderRecord.size())
+ {
+ RaygenShaderBindingTable.buffer = BuffHandle;
+ RaygenShaderBindingTable.offset = RayGenOffset;
+ RaygenShaderBindingTable.size = m_RayGenShaderRecord.size();
+ RaygenShaderBindingTable.stride = m_ShaderRecordStride;
+ }
+
+ if (m_MissShadersRecord.size())
+ {
+ MissShaderBindingTable.buffer = BuffHandle;
+ MissShaderBindingTable.offset = MissShaderOffset;
+ MissShaderBindingTable.size = m_MissShadersRecord.size();
+ MissShaderBindingTable.stride = m_ShaderRecordStride;
+ }
- if (m_MissShaderCount > 0)
+ if (m_HitGroupsRecord.size())
{
- MissShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- MissShaderBindingTable.offset = m_MissShadersOffset;
- MissShaderBindingTable.size = Stride * m_MissShaderCount;
- MissShaderBindingTable.stride = Stride;
+ HitShaderBindingTable.buffer = BuffHandle;
+ HitShaderBindingTable.offset = HitGroupOffset;
+ HitShaderBindingTable.size = m_HitGroupsRecord.size();
+ HitShaderBindingTable.stride = m_ShaderRecordStride;
}
- else
- MissShaderBindingTable = {};
- if (m_HitGroupCount > 0)
+ if (m_CallableShadersRecord.size())
{
- HitShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- HitShaderBindingTable.offset = m_HitGroupsOffset;
- HitShaderBindingTable.size = Stride * m_HitGroupCount;
- HitShaderBindingTable.stride = Stride;
+ CallableShaderBindingTable.buffer = BuffHandle;
+ CallableShaderBindingTable.offset = CallableShadersOffset;
+ CallableShaderBindingTable.size = m_CallableShadersRecord.size();
+ CallableShaderBindingTable.stride = m_ShaderRecordStride;
}
- else
- HitShaderBindingTable = {};
- if (m_CallableShaderCount > 0)
+ if (!m_Changed)
+ return;
+
+ m_Changed = false;
+
+ // update buffer data
+ if (m_RayGenShaderRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, RayGenOffset, static_cast<Uint32>(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode);
+
+ if (m_MissShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast<Uint32>(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode);
+
+ if (m_HitGroupsRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast<Uint32>(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode);
+
+ if (m_CallableShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast<Uint32>(m_CallableShadersRecord.size()), m_CallableShadersRecord.data(), TransitionMode);
+
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ StateTransitionDesc Barrier;
+ Barrier.pResource = m_pBuffer;
+ Barrier.NewState = RESOURCE_STATE_RAY_TRACING;
+ Barrier.UpdateResourceState = true;
+ pContext->TransitionResourceStates(1, &Barrier);
+ }
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
{
- CallableShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- CallableShaderBindingTable.offset = m_CallbaleShadersOffset;
- CallableShaderBindingTable.size = Stride * m_CallableShaderCount;
- CallableShaderBindingTable.stride = Stride;
+ VERIFY_EXPR(m_pBuffer->GetState() == RESOURCE_STATE_RAY_TRACING);
}
- else
- CallableShaderBindingTable = {};
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index 8a9da14e..8101fefc 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -33,6 +33,7 @@
#include "TextureViewVkImpl.hpp"
#include "TextureVkImpl.hpp"
#include "SamplerVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
namespace Diligent
@@ -323,31 +324,31 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
{
- //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);
- // if (VerifyOnly)
- // {
- // if (!IsInRequiredState)
- // {
- // LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
- // GetResourceStateString(RequiredState), ". Actual state: ",
- // GetResourceStateString(pTLASVk->GetState()),
- // ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
- // "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
- // "with IDeviceContext::TransitionResourceStates().");
- // }
- // }
- // else
- // {
- // if (!IsInRequiredState)
- // {
- // pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- // }
- // }
- //}
+ 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);
+ if (VerifyOnly)
+ {
+ if (!IsInRequiredState)
+ {
+ LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
+ GetResourceStateString(RequiredState), ". Actual state: ",
+ GetResourceStateString(pTLASVk->GetState()),
+ ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
+ "with IDeviceContext::TransitionResourceStates().");
+ }
+ }
+ else
+ {
+ if (!IsInRequiredState)
+ {
+ pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
+ }
+ }
+ }
}
break;
@@ -532,13 +533,13 @@ VkWriteDescriptorSetAccelerationStructureKHR ShaderResourceCacheVk::Resource::Ge
VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration structure resource is expected");
DEV_CHECK_ERR(pObject != nullptr, "Unable to get acceleration structure write info: cached object is null");
- //auto* pTLASVk = pObject.RawPtr<const TopLevelASVkImpl>();
+ auto* pTLASVk = pObject.RawPtr<const TopLevelASVkImpl>();
- VkWriteDescriptorSetAccelerationStructureKHR DescrAS = {};
- //DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
- //DescrAS.pNext = nullptr;
- //DescrAS.accelerationStructureCount = 1;
- //DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr();
+ VkWriteDescriptorSetAccelerationStructureKHR DescrAS;
+ DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
+ DescrAS.pNext = nullptr;
+ DescrAS.accelerationStructureCount = 1;
+ DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr();
return DescrAS;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 8a48c27c..45ed73de 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -39,6 +39,7 @@
#include "ShaderResourceVariableBase.hpp"
#include "StringTools.hpp"
#include "PipelineStateVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
namespace Diligent
{
@@ -97,7 +98,7 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) :
Type{Stage},
Shaders{{pShader}},
- SPIRVs{{pShader->GetSPIRV()}}
+ SPIRVs{{{pShader->GetSPIRV()}}}
{
}
@@ -1094,22 +1095,22 @@ void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObjec
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const
{
- // VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected");
- // RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
- //#ifdef DILIGENT_DEVELOPMENT
- // // AZ TODO
- //#endif
- // if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {}))
- // {
- // // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors
- // // are updated at once by CommitDynamicResources() when SRB is committed.
- // if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- // {
- // VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo();
- // UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo);
- // }
- // //
- // }
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected");
+ RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
+#ifdef DILIGENT_DEVELOPMENT
+ // AZ TODO
+#endif
+ if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {}))
+ {
+ // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
+ {
+ VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo();
+ UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo);
+ }
+ //
+ }
}
void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index ab53d639..27be99fc 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -423,12 +423,24 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
swapchain_ci.imageColorSpace = ColorSpace;
DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined");
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_RENDER_TARGET)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_SHADER_INPUT)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_COPY_SOURCE)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ static_assert(SWAP_CHAIN_USAGE_LAST == SWAP_CHAIN_USAGE_UNORDERED_ACCESS, "Please update this function to handle the new swapchain usage");
+
+ for (Uint32 UsageBit = 1; UsageBit <= m_SwapChainDesc.Usage; UsageBit <<= 1)
+ {
+ if ((m_SwapChainDesc.Usage & UsageBit) == 0)
+ continue;
+
+ switch (static_cast<SWAP_CHAIN_USAGE_FLAGS>(UsageBit))
+ {
+ // clang-format off
+ case SWAP_CHAIN_USAGE_RENDER_TARGET: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; break;
+ case SWAP_CHAIN_USAGE_SHADER_INPUT: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; break;
+ case SWAP_CHAIN_USAGE_COPY_SOURCE: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; break;
+ case SWAP_CHAIN_USAGE_UNORDERED_ACCESS: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_STORAGE_BIT; break;
+ default: UNEXPECTED("unknown swapchain usage flag");
+ // clang-format on
+ }
+ }
// vkCmdClearColorImage() command requires the image to use VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout
// that requires VK_IMAGE_USAGE_TRANSFER_DST_BIT to be set
@@ -639,9 +651,10 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
m_ImageAcquiredFenceSubmitted[m_SemaphoreIndex] = (res == VK_SUCCESS);
if (res == VK_SUCCESS)
{
- // Next command in the device context must wait for the next image to be acquired
- // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2)
- pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ // Next command in the device context must wait for the next image to be acquired.
+ // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2).
+ // Swapchain may be used as UAV in compute or ray tracing shader, so we must wait on all stages.
+ pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
if (!m_SwapChainImagesInitialized[m_BackBufferIndex])
{
// Vulkan validation layers do not like uninitialized memory.
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 488e4bf6..dca627d7 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -223,13 +223,13 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
// For either clear or copy command, dst layout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
VkImageSubresourceRange SubresRange;
- SubresRange.aspectMask = aspectMask;
- SubresRange.baseArrayLayer = 0;
- SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- SubresRange.baseMipLevel = 0;
- SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
- auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
- VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, ImageCI.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange, EnabledGraphicsShaderStages);
+ SubresRange.aspectMask = aspectMask;
+ SubresRange.baseArrayLayer = 0;
+ SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ SubresRange.baseMipLevel = 0;
+ SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
+ VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, ImageCI.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange, EnabledShaderStages);
SetState(RESOURCE_STATE_COPY_DEST);
const auto CurrentLayout = GetLayout();
VERIFY_EXPR(CurrentLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@@ -350,7 +350,7 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledGraphicsShaderStages);
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledShaderStages);
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
index 76248d41..ae10b74b 100644
--- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
@@ -76,14 +76,14 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Failed to find suitable memory type for TLAS '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
+ VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_MemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, 0);
+ auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, m_MemoryAlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory");
- m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanTLAS);
-
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo);
m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index 6358174c..40882b09 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1152,6 +1152,55 @@ VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[])
}
+static VkPipelineStageFlags ResourceStateFlagToVkPipelineStage(RESOURCE_STATE StateFlag, VkPipelineStageFlags ShaderStages)
+{
+ static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag");
+ VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
+ switch (StateFlag)
+ {
+ // clang-format off
+ case RESOURCE_STATE_UNDEFINED: return 0;
+ case RESOURCE_STATE_VERTEX_BUFFER: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ case RESOURCE_STATE_CONSTANT_BUFFER: return ShaderStages;
+ case RESOURCE_STATE_INDEX_BUFFER: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ case RESOURCE_STATE_RENDER_TARGET: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ case RESOURCE_STATE_UNORDERED_ACCESS: return ShaderStages;
+ case RESOURCE_STATE_DEPTH_WRITE: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ case RESOURCE_STATE_DEPTH_READ: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ case RESOURCE_STATE_SHADER_RESOURCE: return ShaderStages;
+ case RESOURCE_STATE_STREAM_OUT: return 0;
+ case RESOURCE_STATE_INDIRECT_ARGUMENT: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ case RESOURCE_STATE_COPY_DEST: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_COPY_SOURCE: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_RESOLVE_DEST: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_RESOLVE_SOURCE: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ case RESOURCE_STATE_PRESENT: return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ case RESOURCE_STATE_BUILD_AS_READ: return VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_WRITE: return VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ case RESOURCE_STATE_RAY_TRACING: return VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
+ // clang-format on
+
+ default:
+ UNEXPECTED("Unexpected resource state flag");
+ return 0;
+ }
+}
+
+VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages)
+{
+ VERIFY(Uint32{StateFlags} < (RESOURCE_STATE_MAX_BIT << 1), "Resource state flags are out of range");
+
+ VkPipelineStageFlags Stages = 0;
+ for (Uint32 Bit = 1; Bit <= StateFlags; Bit <<= 1)
+ {
+ if (StateFlags & Bit)
+ Stages |= ResourceStateFlagToVkPipelineStage(static_cast<RESOURCE_STATE>(Bit), ShaderStages);
+ }
+ return Stages;
+}
+
+
static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
{
// Currently not used:
@@ -1189,7 +1238,8 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_ACCESS_TRANSFER_READ_BIT;
case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
case RESOURCE_STATE_PRESENT: return 0;
- case RESOURCE_STATE_BUILD_AS: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_READ: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_WRITE: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
// clang-format on
@@ -1218,7 +1268,7 @@ public:
}
private:
- static constexpr const Uint32 MaxFlagBitPos = 18;
+ static constexpr const Uint32 MaxFlagBitPos = 19;
std::array<VkAccessFlags, MaxFlagBitPos + 1> FlagBitPosToVkAccessFlagsMap;
};
@@ -1239,7 +1289,7 @@ VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags)
return AccessFlags;
}
-RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
+static RESOURCE_STATE VkAccessFlagToResourceStates(VkAccessFlagBits AccessFlagBit)
{
VERIFY((AccessFlagBit & (AccessFlagBit - 1)) == 0, "Single access flag bit is expected");
@@ -1271,8 +1321,6 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
case VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV: return RESOURCE_STATE_UNKNOWN;
- case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: return RESOURCE_STATE_RAY_TRACING;
- case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: return RESOURCE_STATE_BUILD_AS;
// clang-format on
default:
UNEXPECTED("Unknown access flag");
@@ -1288,7 +1336,7 @@ public:
{
for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit)
{
- FlagBitPosToResourceState[bit] = VkAccessFlagsToResourceStates(static_cast<VkAccessFlagBits>(1 << bit));
+ FlagBitPosToResourceState[bit] = VkAccessFlagToResourceStates(static_cast<VkAccessFlagBits>(1 << bit));
}
}
@@ -1354,7 +1402,8 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case RESOURCE_STATE_PRESENT: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- case RESOURCE_STATE_BUILD_AS: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
+ case RESOURCE_STATE_BUILD_AS_READ: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
+ case RESOURCE_STATE_BUILD_AS_WRITE: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
case RESOURCE_STATE_RAY_TRACING: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
// clang-format on
@@ -1376,7 +1425,7 @@ RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout)
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return RESOURCE_STATE_DEPTH_WRITE;
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return RESOURCE_STATE_DEPTH_READ;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return RESOURCE_STATE_SHADER_RESOURCE;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return RESOURCE_STATE_COPY_SOURCE; // AZ TODO: check for resolve state
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return RESOURCE_STATE_COPY_SOURCE;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return RESOURCE_STATE_COPY_DEST;
case VK_IMAGE_LAYOUT_PREINITIALIZED: UNEXPECTED("This layout is not supported"); return RESOURCE_STATE_UNDEFINED;
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: UNEXPECTED("This layout is not supported"); return RESOURCE_STATE_UNDEFINED;
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
index 5a1894c0..ae460cde 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
@@ -79,7 +79,7 @@ VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize Si
"at least one bit set corresponding to a VkMemoryType with a propertyFlags that has both the "
"VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit AND the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set. (11.6)");
- auto MemAllocation = GlobalMemoryMgr.Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, true);
+ auto MemAllocation = GlobalMemoryMgr.Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, true, VkMemoryAllocateFlags{0});
auto AlignedOffset = (MemAllocation.UnalignedOffset + (MemReqs.alignment - 1)) & ~(MemReqs.alignment - 1);
auto err = LogicalDevice.BindBufferMemory(NewBuffer, MemAllocation.Page->GetVkMemory(), AlignedOffset);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
index 11444c33..4d47ca3e 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
@@ -32,7 +32,7 @@ namespace VulkanUtilities
{
static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags AccessFlags,
- const VkPipelineStageFlags EnabledGraphicsShaderStages)
+ const VkPipelineStageFlags EnabledShaderStages)
{
// 6.1.3
VkPipelineStageFlags Stages = 0;
@@ -65,7 +65,7 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
// Read access to a uniform buffer
case VK_ACCESS_UNIFORM_READ_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Read access to an input attachment within a render pass during fragment shading
@@ -75,12 +75,12 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
// Read access to a storage buffer, uniform texel buffer, storage texel buffer, sampled image, or storage image
case VK_ACCESS_SHADER_READ_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Write access to a storage buffer, storage texel buffer, or storage image
case VK_ACCESS_SHADER_WRITE_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Read access to a color attachment, such as via blending, logic operations, or via certain subpass load operations
@@ -134,6 +134,16 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
case VK_ACCESS_MEMORY_WRITE_BIT:
break;
+ // AZ TODO: comment
+ case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR:
+ Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
+ break;
+
+ // AZ TODO: comment
+ case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR:
+ Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ break;
+
default:
UNEXPECTED("Unknown memory access flag");
}
@@ -223,8 +233,12 @@ static VkPipelineStageFlags AccessMaskFromImageLayout(VkImageLayout Layout,
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
break;
+ // When transitioning the image to VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ // there is no need to delay subsequent processing, or perform any visibility operations (as vkQueuePresentKHR
+ // performs automatic visibility operations). To achieve this, the dstAccessMask member of the VkImageMemoryBarrier
+ // should be set to 0, and the dstStageMask parameter should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT.
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- AccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ AccessMask = 0;
break;
default:
@@ -240,7 +254,7 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
VkImageLayout OldLayout,
VkImageLayout NewLayout,
const VkImageSubresourceRange& SubresRange,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
@@ -268,7 +282,7 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
}
else if (ImgBarrier.srcAccessMask != 0)
{
- SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledGraphicsShaderStages);
+ SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledShaderStages);
}
else
{
@@ -282,11 +296,11 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
{
if (NewLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
{
- DestStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ DestStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
else if (ImgBarrier.dstAccessMask != 0)
{
- DestStages = PipelineStageFromAccessFlags(ImgBarrier.dstAccessMask, EnabledGraphicsShaderStages);
+ DestStages = PipelineStageFromAccessFlags(ImgBarrier.dstAccessMask, EnabledShaderStages);
}
else
{
@@ -327,7 +341,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
VkBuffer Buffer,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
@@ -344,7 +358,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
if (SrcStages == 0)
{
if (BuffBarrier.srcAccessMask != 0)
- SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask, EnabledGraphicsShaderStages);
+ SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask, EnabledShaderStages);
else
{
// An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
@@ -356,7 +370,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
if (DestStages == 0)
{
VERIFY(BuffBarrier.dstAccessMask != 0, "Dst access mask must not be zero");
- DestStages = PipelineStageFromAccessFlags(BuffBarrier.dstAccessMask, EnabledGraphicsShaderStages);
+ DestStages = PipelineStageFromAccessFlags(BuffBarrier.dstAccessMask, EnabledShaderStages);
}
vkCmdPipelineBarrier(CmdBuffer,
@@ -371,6 +385,55 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
nullptr);
}
+void VulkanCommandBuffer::ASMemoryBarrier(VkCommandBuffer CmdBuffer,
+ VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags EnabledShaderStages,
+ VkPipelineStageFlags SrcStages,
+ VkPipelineStageFlags DestStages)
+{
+ VkMemoryBarrier Barrier = {};
+ Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ Barrier.pNext = nullptr;
+ Barrier.srcAccessMask = srcAccessMask;
+ Barrier.dstAccessMask = dstAccessMask;
+
+ if (SrcStages == 0)
+ {
+ if (Barrier.srcAccessMask != 0)
+ SrcStages = PipelineStageFromAccessFlags(Barrier.srcAccessMask, EnabledShaderStages);
+ else
+ {
+ // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
+ // mask will effectively not wait for any prior commands to complete. (6.1.2)
+ SrcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+ }
+
+ if (DestStages == 0)
+ {
+ VERIFY(Barrier.dstAccessMask != 0, "Dst access mask must not be zero");
+ DestStages = PipelineStageFromAccessFlags(Barrier.dstAccessMask, EnabledShaderStages);
+ }
+
+ // Other stages are not valid for acceleration structures
+ constexpr VkPipelineStageFlags StagesMask = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+
+ SrcStages &= StagesMask;
+ DestStages &= StagesMask;
+
+ vkCmdPipelineBarrier(CmdBuffer,
+ SrcStages, // must not be 0
+ DestStages, // must not be 0
+ 0, // a bitmask specifying how execution and memory dependencies are formed
+ 1, // memoryBarrierCount
+ &Barrier, // pMemoryBarriers
+ 0,
+ nullptr,
+ 0,
+ nullptr);
+}
+
void VulkanCommandBuffer::FlushBarriers()
{
}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
index 358bdec5..7639c309 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -64,15 +64,19 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe
// https://github.com/zeux/volk#optimizing-device-calls
volkLoadDevice(m_VkDevice);
- if (PhysicalDevice.GetExtFeatures().RayTracingNV)
+ if (m_EnabledExtFeatures.RayTracingNV)
EnableRayTracingKHRviaNV();
#endif
- m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ m_EnabledShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (DeviceCI.pEnabledFeatures->geometryShader)
- m_EnabledGraphicsShaderStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (DeviceCI.pEnabledFeatures->tessellationShader)
- m_EnabledGraphicsShaderStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
+ if (m_EnabledExtFeatures.MeshShader.meshShader != VK_FALSE && m_EnabledExtFeatures.MeshShader.taskShader != VK_FALSE)
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV | VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV;
+ if (m_EnabledExtFeatures.RayTracing.rayTracing != VK_FALSE)
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
}
VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex)
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
index f9cdcdea..2e2cdd31 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
@@ -40,10 +40,11 @@ VulkanMemoryAllocation::~VulkanMemoryAllocation()
}
}
-VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
- VkDeviceSize PageSize,
- uint32_t MemoryTypeIndex,
- bool IsHostVisible) noexcept :
+VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
+ VkDeviceSize PageSize,
+ uint32_t MemoryTypeIndex,
+ bool IsHostVisible,
+ VkMemoryAllocateFlags AllocateFlags) noexcept :
// clang-format off
m_ParentMemoryMgr{ParentMemoryMgr},
m_AllocationMgr {static_cast<AllocationsMgrOffsetType>(PageSize), ParentMemoryMgr.m_Allocator}
@@ -53,13 +54,22 @@ VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
"PageSize (", PageSize, ") exceeds maximum allowed value ",
std::numeric_limits<AllocationsMgrOffsetType>::max());
- VkMemoryAllocateInfo MemAlloc = {};
+ VkMemoryAllocateInfo MemAlloc = {};
+ VkMemoryAllocateFlagsInfo MemFlagInfo = {};
MemAlloc.pNext = nullptr;
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = PageSize;
MemAlloc.memoryTypeIndex = MemoryTypeIndex;
+ if (AllocateFlags)
+ {
+ MemAlloc.pNext = &MemFlagInfo;
+ MemFlagInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
+ MemFlagInfo.pNext = nullptr;
+ MemFlagInfo.flags = AllocateFlags;
+ }
+
auto MemoryName = Diligent::FormatString("Device memory page. Size: ", Diligent::FormatMemorySize(PageSize, 2), ", type: ", MemoryTypeIndex);
m_VkMemory = ParentMemoryMgr.m_LogicalDevice.AllocateDeviceMemory(MemAlloc, MemoryName.c_str());
@@ -116,7 +126,7 @@ void VulkanMemoryPage::Free(VulkanMemoryAllocation&& Allocation)
Allocation = VulkanMemoryAllocation{};
}
-VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps)
+VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps, VkMemoryAllocateFlags AllocateFlags)
{
// memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource.
// Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the
@@ -145,10 +155,10 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements&
}
bool HostVisible = (MemoryProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
- return Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, HostVisible);
+ return Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, HostVisible, AllocateFlags);
}
-VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible)
+VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible, VkMemoryAllocateFlags AllocateFlags)
{
VulkanMemoryAllocation Allocation;
@@ -159,7 +169,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
// even though on integrated GPUs same pages can be used for both GPU-only and staging
// allocations. Staging allocations are short-living and will be released when upload is
// complete, while GPU-only allocations are expected to be long-living.
- MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible};
+ MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible, AllocateFlags};
std::lock_guard<std::mutex> Lock{m_PagesMtx};
auto range = m_Pages.equal_range(PageIdx);
@@ -180,7 +190,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
m_CurrAllocatedSize[stat_ind] += PageSize;
m_PeakAllocatedSize[stat_ind] = std::max(m_PeakAllocatedSize[stat_ind], m_CurrAllocatedSize[stat_ind]);
- auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible});
+ auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible, AllocateFlags});
LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': created new ", (HostVisible ? "host-visible" : "device-local"),
" page. (", Diligent::FormatMemorySize(PageSize, 2), ", type idx: ", MemoryTypeIndex,
"). Current allocated size: ", Diligent::FormatMemorySize(m_CurrAllocatedSize[stat_ind], 2));
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
index f7a6b8f6..5b5434d5 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
@@ -56,18 +56,18 @@ PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr;
PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr;
PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr;
-VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device,
- const VkBufferCreateInfo* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkBuffer* pBuffer)
+VKAPI_ATTR VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device,
+ const VkBufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkBuffer* pBuffer)
{
const_cast<VkBufferCreateInfo*>(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
}
-void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
- VkBuffer buffer,
- const VkAllocationCallbacks* pAllocator)
+VKAPI_ATTR void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
+ VkBuffer buffer,
+ const VkAllocationCallbacks* pAllocator)
{
Origin_vkDestroyBuffer(device, buffer, pAllocator);
@@ -81,8 +81,8 @@ void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
}
}
-VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device,
- const VkBufferDeviceAddressInfo* pInfo)
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -134,10 +134,10 @@ BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr)
}
-VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device,
- const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkAccelerationStructureKHR* pAccelerationStructure)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device,
+ const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureKHR* pAccelerationStructure)
{
VERIFY_EXPR(pCreateInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR);
VERIFY_EXPR(pCreateInfo->pNext == nullptr);
@@ -154,7 +154,9 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR)
{
- CreateInfo.info.instanceCount = pCreateInfo->maxGeometryCount;
+ VERIFY_EXPR(pCreateInfo->maxGeometryCount == 1);
+
+ CreateInfo.info.instanceCount = pCreateInfo->pGeometryInfos->maxPrimitiveCount;
}
else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR)
{
@@ -183,7 +185,6 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
{
dst.geometry.triangles.vertexData = VK_NULL_HANDLE;
dst.geometry.triangles.vertexOffset = 0;
- dst.geometry.triangles.vertexCount = src.maxVertexCount;
dst.geometry.triangles.vertexStride = 0;
dst.geometry.triangles.vertexFormat = src.vertexFormat;
dst.geometry.triangles.indexData = VK_NULL_HANDLE;
@@ -200,7 +201,8 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
}
else
{
- dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3;
+ dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3;
+ dst.geometry.triangles.vertexCount = std::max(src.maxPrimitiveCount * 6, src.maxVertexCount);
}
}
else if (dst.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR)
@@ -224,11 +226,12 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast<VkAccelerationStructureNV*>(pAccelerationStructure));
}
-void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device,
- const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
- VkMemoryRequirements2* pMemoryRequirements)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR);
+ VERIFY_EXPR(pMemoryRequirements->sType == VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2);
VERIFY_EXPR(pInfo->pNext == nullptr);
VERIFY_EXPR(pInfo->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR);
@@ -241,16 +244,16 @@ void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevic
return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements);
}
-VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device,
- uint32_t bindInfoCount,
- const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos)
{
VERIFY_EXPR(pBindInfos->sType == VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV);
return vkBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos);
}
-VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device,
- const VkAccelerationStructureDeviceAddressInfoKHR* pInfo)
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device,
+ const VkAccelerationStructureDeviceAddressInfoKHR* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -260,10 +263,10 @@ VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(V
return result;
}
-void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer,
- uint32_t infoCount,
- const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
- const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ uint32_t infoCount,
+ const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
+ const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
{
std::vector<VkGeometryNV> Geometries;
@@ -321,6 +324,12 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
dst.flags = src.flags;
dst.geometryType = src.geometryType;
+ dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
+ dst.geometry.triangles.pNext = nullptr;
+
+ dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
+ dst.geometry.aabbs.pNext = nullptr;
+
if (dst.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR)
{
VERIFY_EXPR(src.geometry.triangles.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR);
@@ -331,8 +340,6 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
BufferAndOffset IB = DeviceAddressToBuffer(src.geometry.triangles.indexData);
BufferAndOffset TB = DeviceAddressToBuffer(src.geometry.triangles.transformData);
- dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
- dst.geometry.triangles.pNext = nullptr;
dst.geometry.triangles.vertexData = VB.Buffer;
dst.geometry.triangles.vertexOffset = VB.Offset;
dst.geometry.triangles.vertexCount = 0;
@@ -353,7 +360,8 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
else
{
dst.geometry.triangles.indexOffset += off.primitiveOffset;
- dst.geometry.triangles.indexCount = off.primitiveCount * 3;
+ dst.geometry.triangles.indexCount = off.primitiveCount * 3;
+ dst.geometry.triangles.vertexCount = off.primitiveCount * 6;
}
}
else
@@ -364,8 +372,6 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
BufferAndOffset Data = DeviceAddressToBuffer(src.geometry.aabbs.data);
- dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
- dst.geometry.aabbs.pNext = nullptr;
dst.geometry.aabbs.aabbData = Data.Buffer;
dst.geometry.aabbs.numAABBs = off.primitiveCount;
dst.geometry.aabbs.stride = static_cast<uint32_t>(src.geometry.aabbs.stride);
@@ -389,8 +395,8 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
}
}
-void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
- const VkCopyAccelerationStructureInfoKHR* pInfo)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ const VkCopyAccelerationStructureInfoKHR* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -398,14 +404,14 @@ void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer
vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode);
}
-void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
- const VkStridedBufferRegionKHR* pRaygenShaderBindingTable,
- const VkStridedBufferRegionKHR* pMissShaderBindingTable,
- const VkStridedBufferRegionKHR* pHitShaderBindingTable,
- const VkStridedBufferRegionKHR* pCallableShaderBindingTable,
- uint32_t width,
- uint32_t height,
- uint32_t depth)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
+ const VkStridedBufferRegionKHR* pRaygenShaderBindingTable,
+ const VkStridedBufferRegionKHR* pMissShaderBindingTable,
+ const VkStridedBufferRegionKHR* pHitShaderBindingTable,
+ const VkStridedBufferRegionKHR* pCallableShaderBindingTable,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth)
{
vkCmdTraceRaysNV(commandBuffer,
pRaygenShaderBindingTable->buffer, pRaygenShaderBindingTable->offset,
@@ -415,22 +421,28 @@ void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer comma
width, height, depth);
}
-VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device,
- VkPipeline pipeline,
- uint32_t firstGroup,
- uint32_t groupCount,
- size_t dataSize,
- void* pData)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData)
{
return vkGetRayTracingShaderGroupHandlesNV(device, pipeline, firstGroup, groupCount, dataSize, pData);
}
-VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device,
- VkPipelineCache pipelineCache,
- uint32_t createInfoCount,
- const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
- const VkAllocationCallbacks* pAllocator,
- VkPipeline* pPipelines)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator)
+{
+ return vkDestroyAccelerationStructureNV(device, accelerationStructure, pAllocator);
+}
+
+
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines)
{
std::vector<VkRayTracingPipelineCreateInfoNV> Infos;
std::vector<VkRayTracingShaderGroupCreateInfoNV> Groups;
@@ -506,6 +518,7 @@ void EnableRayTracingKHRviaNV()
vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR;
vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR;
vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR;
+ vkDestroyAccelerationStructureKHR = &Redirect_vkDestroyAccelerationStructureKHR;
Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR;
Origin_vkCreateBuffer = vkCreateBuffer;