summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-11-07 02:59:30 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-11-07 02:59:30 +0000
commit9e1f494d613fad30f63adbd5735ff42bc87fc1f4 (patch)
tree571c72b4ff65e31019b4dbc5f71dff0129b0fc0b /Graphics/GraphicsEngine
parentUpdated ResourceMappingImpl (diff)
downloadDiligentCore-9e1f494d613fad30f63adbd5735ff42bc87fc1f4.tar.gz
DiligentCore-9e1f494d613fad30f63adbd5735ff42bc87fc1f4.zip
Device context: refactored command parameters validation
Diffstat (limited to 'Graphics/GraphicsEngine')
-rw-r--r--Graphics/GraphicsEngine/CMakeLists.txt1
-rw-r--r--Graphics/GraphicsEngine/include/BottomLevelASBase.hpp2
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp1457
-rw-r--r--Graphics/GraphicsEngine/include/FramebufferBase.hpp2
-rw-r--r--Graphics/GraphicsEngine/interface/BottomLevelAS.h1
-rw-r--r--Graphics/GraphicsEngine/src/DeviceContextBase.cpp704
-rw-r--r--Graphics/GraphicsEngine/src/FramebufferBase.cpp2
7 files changed, 1090 insertions, 1079 deletions
diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt
index ebb14167..604f3442 100644
--- a/Graphics/GraphicsEngine/CMakeLists.txt
+++ b/Graphics/GraphicsEngine/CMakeLists.txt
@@ -70,6 +70,7 @@ set(SOURCE
src/BottomLevelASBase.cpp
src/BufferBase.cpp
src/DefaultShaderSourceStreamFactory.cpp
+ src/DeviceContextBase.cpp
src/EngineMemory.cpp
src/FramebufferBase.cpp
src/PipelineStateBase.cpp
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
index 2f4a26d0..3ec0efd2 100644
--- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
+++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp
@@ -93,8 +93,6 @@ public:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase)
- static constexpr Uint32 InvalidGeometryIndex = ~0u;
-
virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final
{
VERIFY_EXPR(Name != nullptr && Name[0] != '\0');
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index ee9a2dd4..1df4682d 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -45,6 +45,36 @@
namespace Diligent
{
+// clang-format off
+bool VerifyDrawAttribs (const DrawAttribs& Attribs);
+bool VerifyDrawIndexedAttribs (const DrawIndexedAttribs& Attribs);
+bool VerifyDrawIndirectAttribs (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
+bool VerifyDrawIndexedIndirectAttribs(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
+
+bool VerifyDispatchComputeAttribs (const DispatchComputeAttribs& Attribs);
+bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
+// clang-format on
+
+bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs);
+bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
+
+bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs,
+ const TextureDesc& SrcTexDesc,
+ const TextureDesc& DstTexDesc);
+
+bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs);
+bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier);
+
+bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs);
+bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs);
+bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs);
+bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs);
+bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs);
+bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs);
+bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs);
+
+
+
/// Describes input vertex stream
template <typename BufferImplType>
struct VertexStreamInfo
@@ -53,7 +83,9 @@ struct VertexStreamInfo
/// Strong reference to the buffer object
RefCntAutoPtr<BufferImplType> pBuffer;
- Uint32 Offset = 0; ///< Offset in bytes
+
+ /// Offset in bytes
+ Uint32 Offset = 0;
};
/// Base implementation of the device context.
@@ -62,7 +94,7 @@ struct VertexStreamInfo
/// \tparam ImplementationTraits - implementation traits that define specific implementation details
/// (texture implemenation type, buffer implementation type, etc.)
/// \remarks Device context keeps strong references to all objects currently bound to
-/// the pipeline: buffers, states, samplers, shaders, etc.
+/// the pipeline: buffers, tetxures, states, SRBs, etc.
/// The context also keeps strong references to the device and
/// the swap chain.
template <typename BaseInterface, typename ImplementationTraits>
@@ -81,9 +113,9 @@ public:
using BottomLevelASType = typename ImplementationTraits::BottomLevelASType;
using TopLevelASType = typename ImplementationTraits::TopLevelASType;
- /// \param pRefCounters - reference counters object that controls the lifetime of this device context.
+ /// \param pRefCounters - reference counters object that controls the lifetime of this device context.
/// \param pRenderDevice - render device.
- /// \param bIsDeferred - flag indicating if this instance is a deferred context
+ /// \param bIsDeferred - flag indicating if this instance is a deferred context
DeviceContextBase(IReferenceCounters* pRefCounters, DeviceImplType* pRenderDevice, bool bIsDeferred) :
// clang-format off
TObjectBase {pRefCounters },
@@ -116,7 +148,9 @@ public:
int);
/// Base implementation of IDeviceContext::SetIndexBuffer(); caches the strong reference to the index buffer
- inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0;
+ inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer,
+ Uint32 ByteOffset,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0;
/// Caches the viewports
inline void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight);
@@ -243,22 +277,22 @@ protected:
#ifdef DILIGENT_DEVELOPMENT
// clang-format off
- bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const;
- bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const;
- bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const;
- bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
- bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
- bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
-
- bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const;
- bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
-
- 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 DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
- bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const;
+ bool DvpVerifyDrawArguments (const DrawAttribs& Attribs) const;
+ bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs) const;
+ bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs) const;
+ bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
+ bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
+ bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
+
+ bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs) const;
+ bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
+
+ bool DvpVerifyRenderTargets() const;
+ bool 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 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;}
@@ -270,8 +304,8 @@ protected:
bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;}
bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
- void DvpVerifyRenderTargets()const {}
- void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {}
+ bool DvpVerifyRenderTargets()const {return true;}
+ bool DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)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;}
@@ -368,13 +402,13 @@ protected:
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetVertexBuffers(Uint32 StartSlot,
- Uint32 NumBuffersSet,
- IBuffer** ppBuffers,
- Uint32* pOffsets,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
- SET_VERTEX_BUFFERS_FLAGS Flags)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetVertexBuffers(
+ Uint32 StartSlot,
+ Uint32 NumBuffersSet,
+ IBuffer** ppBuffers,
+ Uint32* pOffsets,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
+ SET_VERTEX_BUFFERS_FLAGS Flags)
{
#ifdef DILIGENT_DEVELOPMENT
if (StartSlot >= MAX_BUFFER_SLOTS)
@@ -429,15 +463,18 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetPipelineState(
+ PipelineStateImplType* pPipelineState,
+ int /*Dummy*/)
{
m_pPipelineState = pPipelineState;
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int)
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::CommitShaderResources(
+ IShaderResourceBinding* pShaderResourceBinding,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
+ int)
{
#ifdef DILIGENT_DEVELOPMENT
VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION),
@@ -459,6 +496,7 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
}
}
#endif
+
return true;
}
@@ -472,8 +510,10 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::InvalidateSt
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetIndexBuffer(
+ IBuffer* pIndexBuffer,
+ Uint32 ByteOffset,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
{
m_pIndexBuffer = ValidatedCast<BufferImplType>(pIndexBuffer);
m_IndexDataStartOffset = ByteOffset;
@@ -538,8 +578,11 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::SetStencilRe
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetViewports(
+ Uint32 NumViewports,
+ const Viewport* pViewports,
+ Uint32& RTWidth,
+ Uint32& RTHeight)
{
if (RTWidth == 0 || RTHeight == 0)
{
@@ -578,8 +621,11 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::GetViewports
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::SetScissorRects(
+ Uint32 NumRects,
+ const Rect* pRects,
+ Uint32& RTWidth,
+ Uint32& RTHeight)
{
if (RTWidth == 0 || RTHeight == 0)
{
@@ -599,8 +645,10 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil)
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::SetRenderTargets(
+ Uint32 NumRenderTargets,
+ ITextureView* ppRenderTargets[],
+ ITextureView* pDepthStencil)
{
if (NumRenderTargets == 0 && pDepthStencil == nullptr)
{
@@ -752,8 +800,10 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::SetSubpassRe
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::GetRenderTargets(
+ Uint32& NumRenderTargets,
+ ITextureView** ppRTVs,
+ ITextureView** ppDSV)
{
NumRenderTargets = m_NumBoundRenderTargets;
@@ -931,33 +981,8 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::BeginRenderP
{
VERIFY(m_pActiveRenderPass == nullptr, "Attempting to begin render pass while another render pass ('", m_pActiveRenderPass->GetDesc().Name, "') is active.");
VERIFY(m_pBoundFramebuffer == nullptr, "Attempting to begin render pass while another framebuffer ('", m_pBoundFramebuffer->GetDesc().Name, "') is bound.");
- VERIFY(Attribs.pRenderPass != nullptr, "Render pass must not be null");
- VERIFY(Attribs.pFramebuffer != nullptr, "Framebuffer must not be null");
-#ifdef DILIGENT_DEBUG
- {
- const auto& RPDesc = Attribs.pRenderPass->GetDesc();
-
- Uint32 NumRequiredClearValues = 0;
- for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i)
- {
- const auto& Attchmnt = RPDesc.pAttachments[i];
- if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR)
- NumRequiredClearValues = i + 1;
- const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format);
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
- {
- if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR)
- NumRequiredClearValues = i + 1;
- }
- }
- VERIFY(Attribs.ClearValueCount >= NumRequiredClearValues,
- "Begin render pass operation requiers at least ", NumRequiredClearValues,
- " clear values, but only ", Attribs.ClearValueCount, " are given.");
- VERIFY(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr,
- "pClearValues must not be null when ClearValueCount is not zero");
- }
-#endif
+ VerifyBeginRenderPassAttribs(Attribs);
// Reset current render targets (in Vulkan backend, this may end current render pass).
ResetRenderTargets();
@@ -998,6 +1023,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::BeginRenderP
m_pBoundFramebuffer = pNewFramebuffer;
m_SubpassIndex = 0;
m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode;
+
UpdateAttachmentStates(m_SubpassIndex);
SetSubpassRenderTargets();
}
@@ -1212,8 +1238,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::EndQuery(IQu
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UpdateBuffer(
+ IBuffer* pBuffer,
+ Uint32 Offset,
+ Uint32 Size,
+ const void* pData,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
{
VERIFY(pBuffer != nullptr, "Buffer must not be null");
VERIFY(m_pActiveRenderPass == nullptr, "UpdateBuffer command must be used outside of render pass.");
@@ -1228,14 +1258,14 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- CopyBuffer(IBuffer* pSrcBuffer,
- Uint32 SrcOffset,
- RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
- IBuffer* pDstBuffer,
- Uint32 DstOffset,
- Uint32 Size,
- RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBuffer(
+ IBuffer* pSrcBuffer,
+ Uint32 SrcOffset,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
+ IBuffer* pDstBuffer,
+ Uint32 DstOffset,
+ Uint32 Size,
+ RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
{
VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null");
VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null");
@@ -1251,8 +1281,11 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::MapBuffer(
+ IBuffer* pBuffer,
+ MAP_TYPE MapType,
+ MAP_FLAGS MapFlags,
+ PVoid& pMappedData)
{
VERIFY(pBuffer, "pBuffer must not be null");
@@ -1306,8 +1339,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
{
VERIFY(pBuffer, "pBuffer must not be null");
#ifdef DILIGENT_DEBUG
@@ -1322,41 +1354,50 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UpdateTexture(
+ ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox,
+ const TextureSubResData& SubresData,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
+ RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
{
VERIFY(pTexture != nullptr, "pTexture must not be null");
VERIFY(m_pActiveRenderPass == nullptr, "UpdateTexture command must be used outside of render pass.");
+
ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- CopyTexture(const CopyTextureAttribs& CopyAttribs)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTexture(const CopyTextureAttribs& CopyAttribs)
{
VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null");
VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null");
VERIFY(m_pActiveRenderPass == nullptr, "CopyTexture command must be used outside of render pass.");
+
ValidateCopyTextureParams(CopyAttribs);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- MapTextureSubresource(ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 ArraySlice,
- MAP_TYPE MapType,
- MAP_FLAGS MapFlags,
- const Box* pMapRegion,
- MappedTextureSubresource& MappedData)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::MapTextureSubresource(
+ ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 ArraySlice,
+ MAP_TYPE MapType,
+ MAP_FLAGS MapFlags,
+ const Box* pMapRegion,
+ MappedTextureSubresource& MappedData)
{
VERIFY(pTexture, "pTexture must not be null");
ValidateMapTextureParams(pTexture->GetDesc(), MipLevel, ArraySlice, MapType, MapFlags, pMapRegion);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UnmapTextureSubresource(
+ ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 ArraySlice)
{
VERIFY(pTexture, "pTexture must not be null");
DEV_CHECK_ERR(MipLevel < pTexture->GetDesc().MipLevels, "Mip level is out of range");
@@ -1364,8 +1405,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- GenerateMips(ITextureView* pTexView)
+inline void DeviceContextBase<BaseInterface, ImplementationTraits>::GenerateMips(ITextureView* pTexView)
{
VERIFY(pTexView != nullptr, "pTexView must not be null");
VERIFY(m_pActiveRenderPass == nullptr, "GenerateMips command must be used outside of render pass.");
@@ -1382,252 +1422,344 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
template <typename BaseInterface, typename ImplementationTraits>
-void DeviceContextBase<BaseInterface, ImplementationTraits>::
- ResolveTextureSubresource(ITexture* pSrcTexture,
- ITexture* pDstTexture,
- const ResolveTextureSubresourceAttribs& ResolveAttribs)
+void DeviceContextBase<BaseInterface, ImplementationTraits>::ResolveTextureSubresource(
+ ITexture* pSrcTexture,
+ ITexture* pDstTexture,
+ const ResolveTextureSubresourceAttribs& ResolveAttribs)
{
#ifdef DILIGENT_DEVELOPMENT
+ VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass.");
+
VERIFY_EXPR(pSrcTexture != nullptr && pDstTexture != nullptr);
const auto& SrcTexDesc = pSrcTexture->GetDesc();
const auto& DstTexDesc = pDstTexture->GetDesc();
- DEV_CHECK_ERR(SrcTexDesc.SampleCount > 1,
- "Source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled");
- DEV_CHECK_ERR(DstTexDesc.SampleCount == 1,
- "Destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled");
- auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel);
- auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel);
- DEV_CHECK_ERR(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight,
- "The size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight,
- ") of the source subresource of a resolve operation (texture '",
- SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice,
- ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight,
- ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ",
- ResolveAttribs.DstSlice, ")");
-
- const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
- const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
- const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format);
- if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless)
- {
- DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format,
- "Source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name,
- ") texture formats of a resolve operation must match exaclty or be compatible typeless formats");
- DEV_CHECK_ERR(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation");
- }
- if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless)
- {
- DEV_CHECK_ERR(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN,
- "Format of a resolve operation must not be unknown when both src and dst texture formats are typeless");
- }
- if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless)
- {
- DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless,
- "Format of a resolve operation must not be typeless when one of the texture formats is typeless");
- }
- VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass.");
+
+ VerifyResolveTextureSubresourceAttribs(ResolveAttribs, SrcTexDesc, DstTexDesc);
#endif
}
-#ifdef DILIGENT_DEVELOPMENT
+
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawArguments(const DrawAttribs& Attribs) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BuildBLASAttribs& Attribs, int) const
{
- if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
- return true;
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device");
+ return false;
+ }
- if (!m_pPipelineState)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound.");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass");
return false;
}
- if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
+ return VerifyBuildBLASAttribs(Attribs);
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const BuildTLASAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
{
- LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device");
return false;
}
- if (Attribs.NumVertices == 0)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_WARNING_MESSAGE("Draw command arguments are invalid: number of vertices to draw is zero.");
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass");
+ return false;
}
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyBuildTLASAttribs(Attribs))
+ return false;
+
+ for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
+ {
+ if (!ValidatedCast<BottomLevelASType>(Attribs.pInstances[i].pBLAS)->ValidateContent())
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid");
+ return false;
+ }
+ }
+#endif
+
return true;
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) const
{
- if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
- return true;
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device");
+ return false;
+ }
- if (!m_pPipelineState)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound.");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass");
return false;
}
- if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyCopyBLASAttribs(Attribs))
+ return false;
+
+ if (!ValidatedCast<BottomLevelASType>(Attribs.pSrc)->ValidateContent())
{
- LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '",
- m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid");
return false;
}
+#endif
- if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32)
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
{
- LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: IndexType (",
- GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device");
return false;
}
- if (!m_pIndexBuffer)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound.");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass");
return false;
}
- if (Attribs.NumIndices == 0)
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyCopyTLASAttribs(Attribs))
+ return false;
+
+ if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->ValidateContent())
{
- LOG_WARNING_MESSAGE("DrawIndexed command arguments are invalid: number of indices to draw is zero.");
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid");
+ return false;
}
+#endif
return true;
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const
{
- if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
- return true;
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device");
+ return false;
+ }
- if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device");
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass");
return false;
}
- if (!m_pPipelineState)
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyWriteBLASCompactedSizeAttribs(m_pDevice, Attribs))
+ return false;
+#endif
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
{
- LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound.");
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device");
return false;
}
- if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_MESH)
+ if (m_pActiveRenderPass != nullptr)
{
- LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: pipeline state '",
- m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline.");
+ LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass");
+ return false;
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyWriteTLASCompactedSizeAttribs(m_pDevice, Attribs))
+ return false;
+#endif
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) const
+{
+ if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device");
return false;
}
- if (Attribs.ThreadGroupCount == 0)
+ if (!m_pPipelineState)
{
- LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero.");
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound.");
+ return false;
}
- if (Attribs.ThreadGroupCount > m_pDevice->GetProperties().MaxDrawMeshTasksCount)
+ if (!m_pPipelineState->GetDesc().IsRayTracingPipeline())
{
- LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetProperties().MaxDrawMeshTasksCount);
+ LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline.");
+ return false;
}
+#ifdef DILIGENT_DEVELOPMENT
+ if (!VerifyTraceRaysAttribs(Attribs))
+ return false;
+#endif
+
return true;
}
+
+
+
+#ifdef DILIGENT_DEVELOPMENT
+
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawArguments(const DrawAttribs& Attribs) const
{
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
return true;
if (!m_pPipelineState)
{
- LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound.");
+ LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound.");
return false;
}
if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
{
+ LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
+ return false;
+ }
- LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '",
+ return VerifyDrawAttribs(Attribs);
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const
+{
+ if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
+ return true;
+
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound.");
+ return false;
+ }
+
+ if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
+ {
+ LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
return false;
}
- if (pAttribsBuffer != nullptr)
+ if (!m_pIndexBuffer)
{
- if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
- {
- LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer '",
- pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
- return false;
- }
+ LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound.");
+ return false;
}
- else
+
+ return VerifyDrawIndexedAttribs(Attribs);
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const
+{
+ if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
+ return true;
+
+ if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
{
- LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer is null.");
+ LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device");
return false;
}
- if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ if (!m_pPipelineState)
{
- LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. "
- "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first.");
+ LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound.");
return false;
}
- return true;
+ if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_MESH)
+ {
+ LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: pipeline state '",
+ m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline.");
+ return false;
+ }
+
+ return VerifyDrawMeshAttribs(m_pDevice->GetProperties().MaxDrawMeshTasksCount, Attribs);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndirectArguments(
+ const DrawIndirectAttribs& Attribs,
+ const IBuffer* pAttribsBuffer) const
{
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
return true;
if (!m_pPipelineState)
{
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound.");
+ LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound.");
return false;
}
if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
{
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '",
+
+ LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
return false;
}
- if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32)
+ if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: IndexType (",
- GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
+ LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. "
+ "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first.");
return false;
}
- if (!m_pIndexBuffer)
+ return VerifyDrawIndirectAttribs(Attribs, pAttribsBuffer);
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawIndexedIndirectArguments(
+ const DrawIndexedIndirectAttribs& Attribs,
+ const IBuffer* pAttribsBuffer) const
+{
+ if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
+ return true;
+
+ if (!m_pPipelineState)
{
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound.");
+ LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound.");
return false;
}
- if (pAttribsBuffer != nullptr)
+ if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS)
{
- if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
- {
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer '",
- pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
- return false;
- }
+ LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '",
+ m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline.");
+ return false;
}
- else
+
+ if (!m_pIndexBuffer)
{
- LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer is null.");
+ LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound.");
return false;
}
@@ -1638,12 +1770,13 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- return true;
+ return VerifyDrawIndexedIndirectAttribs(Attribs, pAttribsBuffer);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDrawMeshIndirectArguments(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDrawMeshIndirectArguments(
+ const DrawMeshIndirectAttribs& Attribs,
+ const IBuffer* pAttribsBuffer) const
{
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
return true;
@@ -1667,39 +1800,23 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- if (pAttribsBuffer != nullptr)
- {
- if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
- {
- LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer '",
- pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
- return false;
- }
- }
- else
- {
- LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer is null.");
- return false;
- }
-
- return true;
+ return VerifyDrawMeshIndirectAttribs(Attribs, pAttribsBuffer);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyRenderTargets() const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyRenderTargets() const
{
if (!m_pPipelineState)
{
LOG_ERROR_MESSAGE("No pipeline state is bound");
- return;
+ return false;
}
const auto& PSODesc = m_pPipelineState->GetDesc();
if (!PSODesc.IsAnyGraphicsPipeline())
{
LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline");
- return;
+ return false;
}
TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN};
@@ -1741,13 +1858,14 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
"' (", GetTextureFormatAttribs(PSOFmt).Name, ").");
}
}
+
+ return true;
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const
{
if (!m_pPipelineState)
{
@@ -1768,21 +1886,13 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- if (Attribs.ThreadGroupCountX == 0)
- LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero.");
-
- if (Attribs.ThreadGroupCountY == 0)
- LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountY is zero.");
-
- if (Attribs.ThreadGroupCountZ == 0)
- LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountZ is zero.");
-
- return true;
+ return VerifyDispatchComputeAttribs(Attribs);
}
template <typename BaseInterface, typename ImplementationTraits>
-inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyDispatchIndirectArguments(
+ const DispatchComputeIndirectAttribs& Attribs,
+ const IBuffer* pAttribsBuffer) const
{
if (!m_pPipelineState)
{
@@ -1803,114 +1913,21 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- if (pAttribsBuffer != nullptr)
- {
- if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
- {
- LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer '",
- pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
- return false;
- }
- }
- else
- {
- LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer is null.");
- return false;
- }
-
- return true;
+ return VerifyDispatchComputeIndirectAttribs(Attribs, pAttribsBuffer);
}
template <typename BaseInterface, typename ImplementationTraits>
-void DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const
{
- 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 (RefCntAutoPtr<ITexture> pTexture{Barrier.pResource, IID_Texture})
- {
- 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 : 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");
- DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'");
-
- DEV_CHECK_ERR(Barrier.FirstMipLevel < TexDesc.MipLevels, "First mip level (", Barrier.FirstMipLevel,
- ") specified by the barrier is out of range. Texture '",
- TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
- DEV_CHECK_ERR(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels,
- "Mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1,
- " specified by the barrier is out of range. Texture '",
- TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
-
- DEV_CHECK_ERR(Barrier.FirstArraySlice < TexDesc.ArraySize, "First array slice (", Barrier.FirstArraySlice,
- ") specified by the barrier is out of range. Array size of texture '",
- TexDesc.Name, "' is ", TexDesc.ArraySize);
- DEV_CHECK_ERR(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize,
- "Array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1,
- " specified by the barrier is out of range. Array size of texture '",
- TexDesc.Name, "' is ", TexDesc.ArraySize);
-
- auto DevType = m_pDevice->GetDeviceCaps().DevType;
- if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN)
- {
- DEV_CHECK_ERR(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels),
- "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
- DEV_CHECK_ERR(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize),
- "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
- }
- }
- else if (RefCntAutoPtr<IBuffer> pBuffer{Barrier.pResource, IID_Buffer})
- {
- 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 : 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 if (RefCntAutoPtr<IBottomLevelAS> pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS})
- {
- const auto& BLASDesc = pBottomLevelAS->GetDesc();
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState();
- DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
- DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE,
- "Invlaid new state specified for BLAS '", BLASDesc.Name, "'");
- DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS");
- }
- else if (RefCntAutoPtr<ITopLevelAS> pTopLevelAS{Barrier.pResource, IID_TopLevelAS})
- {
- const auto& TLASDesc = pTopLevelAS->GetDesc();
- OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState();
- DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
- DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING,
- "Invlaid new state specified for TLAS '", TLASDesc.Name, "'");
- DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for TLAS");
- }
- else
- {
- UNEXPECTED("unsupported resource type");
- }
-
- if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
- {
- DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE");
- }
-
- if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
- {
- DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
- }
+ return VerifyStateTransitionDesc(m_pDevice, Barrier);
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyTextureState(
+ const TextureImplType& Texture,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName) const
{
if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState))
{
@@ -1924,8 +1941,10 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyBufferState(const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyBufferState(
+ const BufferImplType& Buffer,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName) const
{
if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState))
{
@@ -1939,8 +1958,10 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyBLASState(const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyBLASState(
+ const BottomLevelASType& BLAS,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName) const
{
if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState))
{
@@ -1954,8 +1975,10 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::
- DvpVerifyTLASState(const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const
+bool DeviceContextBase<BaseInterface, ImplementationTraits>::DvpVerifyTLASState(
+ const TopLevelASType& TLAS,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName) const
{
if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState))
{
@@ -1967,723 +1990,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return true;
}
-#endif // DILIGENT_DEVELOPMENT
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BuildBLASAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass");
- return false;
- }
-
- if (Attribs.pBLAS == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBLAS must not be null");
- return false;
- }
-
- if (Attribs.pScratchBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer must not be null");
- return false;
- }
-
- if (!((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined");
- return false;
- }
-
- if (Attribs.pBoxData == nullptr && Attribs.BoxDataCount > 0)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData is null but BoxDataCount is not 0");
- return false;
- }
-
- if (Attribs.pTriangleData == nullptr && Attribs.TriangleDataCount > 0)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData is null but TriangleDataCount is not 0");
- return false;
- }
-
- const auto& BLASDesc = Attribs.pBLAS->GetDesc();
-
- if (Attribs.BoxDataCount > BLASDesc.BoxCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount");
- return false;
- }
-
- if (Attribs.TriangleDataCount > BLASDesc.TriangleCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount");
- return false;
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
- {
- const auto& tri = Attribs.pTriangleData[i];
- const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount;
- const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount;
- const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName);
-
- if (GeomIndex == BottomLevelASType::InvalidGeometryIndex)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].GeometryName not found in BLAS description");
- return false;
- }
-
- const auto& TriDesc = BLASDesc.pTriangles[GeomIndex];
-
- if (tri.VertexValueType != VT_UNDEFINED && tri.VertexValueType != TriDesc.VertexValueType)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description");
- return false;
- }
-
- if (tri.VertexComponentCount != 0 && tri.VertexComponentCount != TriDesc.VertexComponentCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 0 or match the VertexComponentCount in geometry description");
- return false;
- }
-
- if (tri.VertexCount > TriDesc.MaxVertexCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must not be greater then MaxVertexCount(", TriDesc.MaxVertexCount, ")");
- 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 ((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 (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 && tri.IndexType != TriDesc.IndexType)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must match the IndexType in geometry description");
- return false;
- }
-
- if (tri.PrimitiveCount > TriDesc.MaxPrimitiveCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].PrimitiveCount must not be greater then MaxPrimitiveCount(", TriDesc.MaxPrimitiveCount, ")");
- return false;
- }
-
- if (TriDesc.IndexType != VT_UNDEFINED)
- {
- if (tri.pIndexBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null");
- return false;
- }
-
- 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.PrimitiveCount * 3 * 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
- {
- if (tri.VertexCount != tri.PrimitiveCount * 3)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must equal to (PrimitiveCount * 3)");
- return false;
- }
-
- VERIFY(tri.pIndexBuffer == nullptr,
- "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED");
- }
-
- if (tri.pTransformBuffer != nullptr)
- {
- 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;
- }
-
- if (!TriDesc.AllowsTransforms)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "] use transform buffer but AllowsTransforms is false");
- return false;
- }
- }
- }
-
- for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
- {
- const auto& box = Attribs.pBoxData[i];
- const Uint32 BoxSize = sizeof(float) * 6;
- const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName);
-
- if (GeomIndex == BottomLevelASType::InvalidGeometryIndex)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].GeometryName not found in BLAS description");
- return false;
- }
-
- const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex];
-
- if (box.BoxCount > BoxDesc.MaxBoxCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxCount must not be greated then MaxBoxCount (", BoxDesc.MaxBoxCount, ")");
- return false;
- }
-
- 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 ((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;
- }
- }
-#endif // DILIGENT_DEVELOPMENT
-
- const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc();
-
- if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ScratchBufferOffset is greater than buffer size");
- return false;
- }
-
- if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pBLAS->GetScratchBufferSizes().Build)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get required size for scratch buffer");
- return false;
- }
-
- if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
- return false;
- }
-
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const BuildTLASAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass");
- return false;
- }
-
- if (Attribs.pTLAS == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pTLAS must not be null");
- return false;
- }
-
- if (Attribs.pScratchBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must not be null");
- return false;
- }
-
- if (Attribs.pInstances == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances must not be null");
- return false;
- }
-
- if (Attribs.pInstanceBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must not be null");
- return false;
- }
-
- if (Attribs.HitShadersPerInstance == 0)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0");
- return false;
- }
-
- const auto& TLASDesc = Attribs.pTLAS->GetDesc();
-
- if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceCount must be less than or equal to Attribs.pTLAS->GetDesc().MaxInstanceCount");
- return false;
- }
-
- const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
- const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE;
-
-#ifdef DILIGENT_DEVELOPMENT
- Uint32 AutoOffsetCounter = 0;
-
- // calculate instance data size
- for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
- {
- VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used");
-
- VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
- (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0,
- "Only the lower 24 bits are used");
-
- if (Attribs.pInstances[i].InstanceName == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].InstanceName must not be null");
- return false;
- }
-
- if (Attribs.pInstances[i].pBLAS == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null");
- return false;
- }
-
- if (!ValidatedCast<BottomLevelASType>(Attribs.pInstances[i].pBLAS)->ValidateContent())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid");
- return false;
- }
-
- if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
- ++AutoOffsetCounter;
-
-
- if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i,
- "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO "
- "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED");
- return false;
- }
- }
-
- 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;
- }
-#endif // DILIGENT_DEVELOPMENT
-
- if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceBufferOffset is greater than buffer size");
- return false;
- }
-
- if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset < InstDataSize)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer size is too small, ...");
- return false;
- }
-
- if ((InstDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must be created with BIND_RAY_TRACING flag");
- return false;
- }
-
- const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc();
-
- if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ScratchBufferOffset is greater than buffer size");
- return false;
- }
-
- if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pTLAS->GetScratchBufferSizes().Build)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get required size for scratch buffer");
- return false;
- }
-
- if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag");
- return false;
- }
-
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device");
- return false;
- }
-
- if (Attribs.pSrc == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null");
- return false;
- }
-
- if (Attribs.pDst == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must not be null");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass");
- return false;
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if (!ValidatedCast<BottomLevelASType>(Attribs.pSrc)->ValidateContent())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid");
- return false;
- }
-
- if (Attribs.Mode == COPY_AS_MODE_CLONE)
- {
- auto& SrcDesc = Attribs.pSrc->GetDesc();
- auto& DstDesc = Attribs.pDst->GetDesc();
-
- if (SrcDesc.TriangleCount != DstDesc.TriangleCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different TriangleCount, pDst must have been created with the same parameters as pSrc");
- return false;
- }
-
- if (SrcDesc.BoxCount != DstDesc.BoxCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different BoxCount, pDst must have been created with the same parameters as pSrc");
- return false;
- }
-
- if (SrcDesc.Flags != DstDesc.Flags)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different Flags, pDst must have been created with the same parameters as pSrc");
- return false;
- }
-
- for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i)
- {
- auto& SrcTri = SrcDesc.pTriangles[i];
- auto& DstTri = DstDesc.pTriangles[i];
-
- // clang-format off
- if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount ||
- SrcTri.VertexValueType != DstTri.VertexValueType ||
- SrcTri.VertexComponentCount != DstTri.VertexComponentCount ||
- SrcTri.MaxPrimitiveCount != DstTri.MaxPrimitiveCount ||
- SrcTri.IndexType != DstTri.IndexType ||
- SrcTri.AllowsTransforms != DstTri.AllowsTransforms)
- // clang-format on
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different triangle descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc");
- return false;
- }
- }
-
- for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i)
- {
- if (SrcDesc.pBoxes[i].MaxBoxCount != DstDesc.pBoxes[i].MaxBoxCount)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different box descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc");
- return false;
- }
- }
- }
- else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
- {
- auto& SrcDesc = Attribs.pSrc->GetDesc();
- auto& DstDesc = Attribs.pDst->GetDesc();
-
- if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
- return false;
- }
-
- if (DstDesc.CompactedSize == 0)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must be create with defined CompactedSize");
- return false;
- }
- }
- else
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode");
- return false;
- }
-#endif // DILIGENT_DEVELOPMENT
-
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device");
- return false;
- }
-
- if (Attribs.pSrc == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null");
- return false;
- }
-
- if (Attribs.pDst == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must not be null");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass");
- return false;
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->ValidateContent())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid");
- return false;
- }
-
- if (Attribs.Mode == COPY_AS_MODE_CLONE)
- {
- auto& SrcDesc = Attribs.pSrc->GetDesc();
- auto& DstDesc = Attribs.pDst->GetDesc();
-
- if (SrcDesc.MaxInstanceCount != DstDesc.MaxInstanceCount ||
- SrcDesc.Flags != DstDesc.Flags)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc");
- return false;
- }
- }
- else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
- {
- auto& SrcDesc = Attribs.pSrc->GetDesc();
- auto& DstDesc = Attribs.pDst->GetDesc();
-
- if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
- return false;
- }
-
- if (DstDesc.CompactedSize == 0)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must be create with defined CompactedSize");
- return false;
- }
- }
- else
- {
- LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode");
- return false;
- }
-#endif // DILIGENT_DEVELOPMENT
-
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device");
- return false;
- }
-
- if (Attribs.pBLAS == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must not be null");
- return false;
- }
- if (!(Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
- return false;
- }
-
- if (Attribs.pDestBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must not be null");
- return false;
- }
- if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer is too small");
- return false;
- }
- if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 &&
- !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass");
- return false;
- }
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device");
- return false;
- }
-
- if (Attribs.pTLAS == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must not be null");
- return false;
- }
- if (!(Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
- return false;
- }
-
- if (Attribs.pDestBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must not be null");
- return false;
- }
- if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer is too small");
- return false;
- }
- if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 &&
- !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag");
- return false;
- }
-
- if (m_pActiveRenderPass != nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass");
- return false;
- }
- return true;
-}
-
-template <typename BaseInterface, typename ImplementationTraits>
-bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) const
-{
- if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device");
- return false;
- }
-
- if (Attribs.pSBT == nullptr)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null");
- return false;
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if (!Attribs.pSBT->Verify())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT content is not valid");
- return false;
- }
#endif // DILIGENT_DEVELOPMENT
- if (!m_pPipelineState)
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound.");
- return false;
- }
-
- if (!m_pPipelineState->GetDesc().IsRayTracingPipeline())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline.");
- return false;
- }
-
- if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState.RawPtr())
- {
- LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name,
- "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable");
- return false;
- }
-
- if (Attribs.DimensionX == 0)
- LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionX is zero.");
-
- if (Attribs.DimensionY == 0)
- LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionY is zero.");
-
- if (Attribs.DimensionZ == 0)
- LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionZ is zero.");
-
- return true;
-}
-
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/FramebufferBase.hpp b/Graphics/GraphicsEngine/include/FramebufferBase.hpp
index ca386375..0cd484dc 100644
--- a/Graphics/GraphicsEngine/include/FramebufferBase.hpp
+++ b/Graphics/GraphicsEngine/include/FramebufferBase.hpp
@@ -39,7 +39,7 @@
namespace Diligent
{
-void ValidateFramebufferDesc(const FramebufferDesc& Desc);
+void ValidateFramebufferDesc(const FramebufferDesc& Desc) noexcept(false);
/// Template class implementing base functionality for the framebuffer object.
diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
index cfabc1d5..bd80e3e4 100644
--- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h
+++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h
@@ -178,6 +178,7 @@ struct ScratchBufferSizes
};
typedef struct ScratchBufferSizes ScratchBufferSizes;
+static const Uint32 InvalidGeometryIndex = ~0u;
#define DILIGENT_INTERFACE_NAME IBottomLevelAS
#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h"
diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp
new file mode 100644
index 00000000..a526bd37
--- /dev/null
+++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp
@@ -0,0 +1,704 @@
+/*
+ * 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 "DeviceContextBase.hpp"
+#include "GraphicsAccessories.hpp"
+
+namespace Diligent
+{
+
+#if DILIGENT_DEBUG
+
+# define CHECK_PARAMETER(Expr, ...) \
+ do \
+ { \
+ VERIFY(Expr, __VA_ARGS__); \
+ if (!(Expr)) return false; \
+ } while (false)
+
+#else
+
+# define CHECK_PARAMETER(Expr, ...) \
+ do \
+ { \
+ if (!(Expr)) \
+ { \
+ LOG_ERROR_MESSAGE(__VA_ARGS__); \
+ return false; \
+ } \
+ } while (false)
+
+#endif
+
+bool VerifyDrawAttribs(const DrawAttribs& Attribs)
+{
+#define CHECK_DRAW_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_ATTRIBS(Attribs.NumVertices != 0, "NumVertices must not be zero.");
+
+#undef CHECK_DRAW_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDrawIndexedAttribs(const DrawIndexedAttribs& Attribs)
+{
+#define CHECK_DRAW_INDEXED_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indexed attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_INDEXED_ATTRIBS(Attribs.IndexType == VT_UINT16 || Attribs.IndexType == VT_UINT32,
+ "IndexType (", GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
+
+ CHECK_DRAW_INDEXED_ATTRIBS(Attribs.NumIndices != 0, "NumIndices must not be zero.");
+
+#undef CHECK_DRAW_INDEXED_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs)
+{
+#define CHECK_DRAW_MESH_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCount != 0, "ThreadGroupCount must not be zero.");
+ CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCount <= MaxDrawMeshTasksCount,
+ "ThreadGroupCount (", Attribs.ThreadGroupCount, ") must not exceed ", MaxDrawMeshTasksCount);
+
+#undef CHECK_DRAW_MESH_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDrawIndirectAttribs(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)
+{
+#define CHECK_DRAW_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indirect attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not be null.");
+ CHECK_DRAW_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
+ "indirect draw arguments buffer '", pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
+
+#undef CHECK_DRAW_INDIRECT_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDrawIndexedIndirectAttribs(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)
+{
+#define CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indexed indirect attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not null.");
+ CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(Attribs.IndexType == VT_UINT16 || Attribs.IndexType == VT_UINT32,
+ "IndexType (", GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32.");
+ CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
+ "indirect draw arguments buffer '",
+ pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
+
+#undef CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)
+{
+#define CHECK_DRAW_MESH_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh indirect attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DRAW_MESH_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not be null.");
+ CHECK_DRAW_MESH_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
+ "indirect draw arguments buffer '", pAttribsBuffer->GetDesc().Name,
+ "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
+
+#undef CHECK_DRAW_MESH_INDIRECT_ATTRIBS
+
+ return true;
+}
+
+
+bool VerifyDispatchComputeAttribs(const DispatchComputeAttribs& Attribs)
+{
+#define CHECK_DISPATCH_COMPUTE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Dispatch compute attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountX != 0, "ThreadGroupCountX must no be zero.");
+ CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountY != 0, "ThreadGroupCountY must no be zero.");
+ CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountZ != 0, "ThreadGroupCountZ must no be zero.");
+
+#undef CHECK_DISPATCH_COMPUTE_ATTRIBS
+
+ return true;
+}
+
+bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)
+{
+#define CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Dispatch compute indirect attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect dispatch arguments buffer must not be null.");
+ CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
+ "indirect dispatch arguments buffer '",
+ pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
+
+#undef CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS
+
+ return true;
+}
+
+bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs,
+ const TextureDesc& SrcTexDesc,
+ const TextureDesc& DstTexDesc)
+{
+#define CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Resolve texture subresource attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcTexDesc.SampleCount > 1, "source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled");
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(DstTexDesc.SampleCount == 1, "destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled");
+
+ auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel);
+ auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel);
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight,
+ "the size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight,
+ ") of the source subresource of a resolve operation (texture '",
+ SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice,
+ ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight,
+ ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ",
+ ResolveAttribs.DstSlice, ")");
+
+ const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
+ const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
+ const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format);
+ if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless)
+ {
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcTexDesc.Format == DstTexDesc.Format,
+ "source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name,
+ ") texture formats of a resolve operation must match exaclty or be compatible typeless formats");
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation");
+ }
+ if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless)
+ {
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN,
+ "format of a resolve operation must not be unknown when both src and dst texture formats are typeless");
+ }
+ if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless)
+ {
+ CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(!ResolveFmtAttribs.IsTypeless,
+ "format of a resolve operation must not be typeless when one of the texture formats is typeless");
+ }
+#undef CHECK_RESOLVE_TEX_SUBRES_ATTRIBS
+
+ return true;
+}
+
+bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs)
+{
+#define CHECK_BEGIN_RENDER_PASS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Begin render pass attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.pRenderPass != nullptr, "pRenderPass pass must not be null");
+ CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.pFramebuffer != nullptr, "pFramebuffer must not be null");
+
+ const auto& RPDesc = Attribs.pRenderPass->GetDesc();
+
+ Uint32 NumRequiredClearValues = 0;
+ for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i)
+ {
+ const auto& Attchmnt = RPDesc.pAttachments[i];
+ if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR)
+ NumRequiredClearValues = i + 1;
+
+ const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR)
+ NumRequiredClearValues = i + 1;
+ }
+ }
+
+ CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.ClearValueCount >= NumRequiredClearValues,
+ "at least ", NumRequiredClearValues, " clear values are required, but only ",
+ Uint32{Attribs.ClearValueCount}, " are provided.");
+ CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr,
+ "pClearValues must not be null when ClearValueCount (", Attribs.ClearValueCount, ") is not zero");
+
+#undef CHECK_BEGIN_RENDER_PASS_ATTRIBS
+
+ return true;
+}
+
+bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier)
+{
+#define CHECK_STATE_TRANSITION_DESC(Expr, ...) CHECK_PARAMETER(Expr, "State transition parameters are invalid: ", __VA_ARGS__)
+
+ CHECK_STATE_TRANSITION_DESC(Barrier.pResource != nullptr, "pResource must not be null");
+ CHECK_STATE_TRANSITION_DESC(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "NewState state can't be UNKNOWN");
+
+ RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
+
+ if (RefCntAutoPtr<ITexture> pTexture{Barrier.pResource, IID_Texture})
+ {
+ const auto& TexDesc = pTexture->GetDesc();
+
+ CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(Barrier.NewState, true), "invlaid new state specified for texture '", TexDesc.Name, "'");
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState();
+ CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN,
+ "the state of texture '", TexDesc.Name,
+ "' is unknown to the engine and is not explicitly specified in the barrier");
+ CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(OldState, true), "invlaid old state specified for texture '", TexDesc.Name, "'");
+
+ CHECK_STATE_TRANSITION_DESC(Barrier.FirstMipLevel < TexDesc.MipLevels, "first mip level (", Barrier.FirstMipLevel,
+ ") specified by the barrier is out of range. Texture '",
+ TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
+ CHECK_STATE_TRANSITION_DESC(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels,
+ "mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1,
+ " specified by the barrier is out of range. Texture '",
+ TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)");
+
+ CHECK_STATE_TRANSITION_DESC(Barrier.FirstArraySlice < TexDesc.ArraySize, "first array slice (", Barrier.FirstArraySlice,
+ ") specified by the barrier is out of range. Array size of texture '",
+ TexDesc.Name, "' is ", TexDesc.ArraySize);
+ CHECK_STATE_TRANSITION_DESC(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize,
+ "array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1,
+ " specified by the barrier is out of range. Array size of texture '",
+ TexDesc.Name, "' is ", TexDesc.ArraySize);
+
+ auto DevType = pDevice->GetDeviceCaps().DevType;
+ if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN)
+ {
+ CHECK_STATE_TRANSITION_DESC(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels),
+ "failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
+ CHECK_STATE_TRANSITION_DESC(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize),
+ "failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device");
+ }
+ }
+ else if (RefCntAutoPtr<IBuffer> pBuffer{Barrier.pResource, IID_Buffer})
+ {
+ const auto& BuffDesc = pBuffer->GetDesc();
+ CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(Barrier.NewState, false), "invlaid new state specified for buffer '", BuffDesc.Name, "'");
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState();
+ CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
+ CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(OldState, false), "invlaid old state specified for buffer '", BuffDesc.Name, "'");
+ }
+ else if (RefCntAutoPtr<IBottomLevelAS> pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS})
+ {
+ const auto& BLASDesc = pBottomLevelAS->GetDesc();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState();
+ CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
+ CHECK_STATE_TRANSITION_DESC(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE,
+ "invlaid new state specified for BLAS '", BLASDesc.Name, "'");
+ CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "split barriers are not supported for BLAS");
+ }
+ else if (RefCntAutoPtr<ITopLevelAS> pTopLevelAS{Barrier.pResource, IID_TopLevelAS})
+ {
+ const auto& TLASDesc = pTopLevelAS->GetDesc();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState();
+ CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
+ CHECK_STATE_TRANSITION_DESC(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING,
+ "invlaid new state specified for TLAS '", TLASDesc.Name, "'");
+ CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "split barriers are not supported for TLAS");
+ }
+ else
+ {
+ UNEXPECTED("unsupported resource type");
+ }
+
+ if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ {
+ CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "for UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE");
+ }
+
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ CHECK_STATE_TRANSITION_DESC(!Barrier.UpdateResourceState, "resource state can't be updated in begin-split barrier");
+ }
+
+#undef CHECK_STATE_TRANSITION_DESC
+
+ return true;
+}
+
+
+bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs)
+{
+#define CHECK_BUILD_BLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build BLAS attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.pBLAS != nullptr, "pBLAS must not be null");
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.pScratchBuffer != nullptr, "pScratchBuffer must not be null");
+ CHECK_BUILD_BLAS_ATTRIBS((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr), "exactly one of pTriangles and pBoxes must be defined");
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.pBoxData != nullptr || Attribs.BoxDataCount == 0, "pBoxData is null, but BoxDataCount is not 0");
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.pTriangleData != nullptr || Attribs.TriangleDataCount == 0, "pTriangleData is null, but TriangleDataCount is not 0");
+
+ const auto& BLASDesc = Attribs.pBLAS->GetDesc();
+
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.BoxDataCount <= BLASDesc.BoxCount, "BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount");
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.TriangleDataCount <= BLASDesc.TriangleCount, "TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount");
+
+ for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i)
+ {
+ const auto& tri = Attribs.pTriangleData[i];
+ const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount;
+ const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount;
+ const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName);
+
+ CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex,
+ "pTriangleData[", i, "].GeometryName (", tri.GeometryName, ") is not found in BLAS description");
+
+ const auto& TriDesc = BLASDesc.pTriangles[GeomIndex];
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexValueType == VT_UNDEFINED || tri.VertexValueType == TriDesc.VertexValueType,
+ "pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexComponentCount == 0 || tri.VertexComponentCount == TriDesc.VertexComponentCount,
+ "pTriangleData[", i, "].VertexComponentCount (", tri.VertexComponentCount, ") must be 0 or match the VertexComponentCount (",
+ TriDesc.VertexComponentCount, ") in geometry description");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexCount <= TriDesc.MaxVertexCount,
+ "pTriangleData[", i, "].VertexCount (", tri.VertexCount, ") must not be greater than MaxVertexCount(", TriDesc.MaxVertexCount, ")");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexStride >= VertexSize,
+ "pTriangleData[", i, "].VertexStride (", tri.VertexStride, ") must be at least ", VertexSize, " bytes");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.pVertexBuffer != nullptr, "pTriangleData[", i, "].pVertexBuffer must not be null");
+
+ CHECK_BUILD_BLAS_ATTRIBS((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pTriangleData[", i, "].pVertexBuffer was not created with BIND_RAY_TRACING flag");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexOffset + VertexDataSize <= tri.pVertexBuffer->GetDesc().uiSizeInBytes,
+ "pTriangleData[", i, "].pVertexBuffer is too small for the specified VertexStride (", tri.VertexStride, ") and VertexCount (",
+ tri.VertexCount, "): at least ", tri.VertexOffset + VertexDataSize, " bytes are required");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.IndexType == VT_UNDEFINED || tri.IndexType == TriDesc.IndexType,
+ "pTriangleData[", i, "].IndexType (", GetValueTypeString(tri.IndexType), ") must match the IndexType (",
+ TriDesc.IndexType, ") in geometry description");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.PrimitiveCount <= TriDesc.MaxPrimitiveCount,
+ "pTriangleData[", i, "].PrimitiveCount (", tri.PrimitiveCount, ") must not be greater than MaxPrimitiveCount (",
+ TriDesc.MaxPrimitiveCount, ")");
+
+ if (TriDesc.IndexType != VT_UNDEFINED)
+ {
+ CHECK_BUILD_BLAS_ATTRIBS(tri.pIndexBuffer != nullptr, "pTriangleData[", i, "].pIndexBuffer must not be null");
+
+ CHECK_BUILD_BLAS_ATTRIBS((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pTriangleData[", i, "].pIndexBuffer was not created with BIND_RAY_TRACING flag");
+
+ const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType);
+ CHECK_BUILD_BLAS_ATTRIBS(tri.IndexOffset + IndexDataSize <= tri.pIndexBuffer->GetDesc().uiSizeInBytes,
+ "pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount: at least",
+ tri.IndexOffset + IndexDataSize, " bytes are required");
+ }
+ else
+ {
+ CHECK_BUILD_BLAS_ATTRIBS(tri.VertexCount == tri.PrimitiveCount * 3,
+ "pTriangleData[", i, "].VertexCount (", tri.VertexCount, ") must equal to PrimitiveCount * 3 (",
+ tri.PrimitiveCount * 3, ")");
+
+ CHECK_BUILD_BLAS_ATTRIBS(tri.pIndexBuffer == nullptr, "pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED");
+ }
+
+ if (tri.pTransformBuffer != nullptr)
+ {
+ CHECK_BUILD_BLAS_ATTRIBS((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pTriangleData[", i, "].pTransformBuffer was not created with BIND_RAY_TRACING flag");
+
+ CHECK_BUILD_BLAS_ATTRIBS(TriDesc.AllowsTransforms, "pTriangleData[", i, "] uses transform buffer, but AllowsTransforms is false");
+ }
+ }
+
+ for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i)
+ {
+ const auto& box = Attribs.pBoxData[i];
+ const Uint32 BoxSize = sizeof(float) * 6;
+ const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName);
+
+ CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex,
+ "pBoxData[", i, "].GeometryName (", box.GeometryName, ") is not found in BLAS description");
+
+ const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex];
+
+ CHECK_BUILD_BLAS_ATTRIBS(box.BoxCount <= BoxDesc.MaxBoxCount,
+ "pBoxData[", i, "].BoxCount (", box.BoxCount, ") must not be greated than MaxBoxCount (", BoxDesc.MaxBoxCount, ")");
+
+ CHECK_BUILD_BLAS_ATTRIBS(box.BoxStride >= BoxSize,
+ "pBoxData[", i, "].BoxStride (", box.BoxStride, ") must be at least ", BoxSize, " bytes");
+
+ CHECK_BUILD_BLAS_ATTRIBS(box.pBoxBuffer != nullptr, "pBoxData[", i, "].pBoxBuffer must not be null");
+
+ CHECK_BUILD_BLAS_ATTRIBS((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pBoxData[", i, "].pBoxBuffer was not created with BIND_RAY_TRACING flag");
+ }
+
+ const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc();
+
+ CHECK_BUILD_BLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes,
+ "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")");
+
+ CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Build,
+ "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get the required size for the scratch buffer");
+
+ CHECK_BUILD_BLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pScratchBuffer was not created with BIND_RAY_TRACING flag");
+
+#undef CHECK_BUILD_BLAS_ATTRIBS
+
+ return true;
+}
+
+
+bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs)
+{
+#define CHECK_BUILD_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build TLAS attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pTLAS != nullptr, "pTLAS must not be null");
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pScratchBuffer != nullptr, "pScratchBuffer must not be null");
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances != nullptr, "pInstances must not be null");
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstanceBuffer != nullptr, "pInstanceBuffer must not be null");
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.HitShadersPerInstance != 0, "HitShadersPerInstance must be greater than 0");
+
+ const auto& TLASDesc = Attribs.pTLAS->GetDesc();
+
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.InstanceCount <= TLASDesc.MaxInstanceCount,
+ "InstanceCount (", Attribs.InstanceCount, ") must be less than or equal to pTLAS->GetDesc().MaxInstanceCount (",
+ TLASDesc.MaxInstanceCount, ")");
+
+ const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc();
+ const auto InstDataSize = size_t{Attribs.InstanceCount} * size_t{TLAS_INSTANCE_DATA_SIZE};
+
+ Uint32 AutoOffsetCounter = 0;
+
+ // Calculate instance data size
+ for (Uint32 i = 0; i < Attribs.InstanceCount; ++i)
+ {
+ VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used");
+
+ VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO ||
+ (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0,
+ "Only the lower 24 bits are used");
+
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].InstanceName != nullptr, "pInstances[", i, "].InstanceName must not be null");
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null");
+
+ if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO)
+ ++AutoOffsetCounter;
+
+ CHECK_BUILD_TLAS_ATTRIBS(TLASDesc.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO,
+ "pInstances[", i,
+ "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO "
+ "if TLAS is created with BindingMode that is not SHADER_BINDING_USER_DEFINED");
+ }
+
+ CHECK_BUILD_TLAS_ATTRIBS(AutoOffsetCounter == 0 || AutoOffsetCounter == Attribs.InstanceCount,
+ "all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO, or none of them should");
+
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.InstanceBufferOffset <= InstDesc.uiSizeInBytes,
+ "InstanceBufferOffset (", Attribs.InstanceBufferOffset, ") is greater than the buffer size (", InstDesc.uiSizeInBytes, ")");
+
+ CHECK_BUILD_TLAS_ATTRIBS(InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset >= InstDataSize,
+ "pInstanceBuffer size (", InstDesc.uiSizeInBytes, ") is too small: at least ",
+ InstDataSize + Attribs.InstanceBufferOffset, " bytes are required");
+
+ CHECK_BUILD_TLAS_ATTRIBS((InstDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pInstanceBuffer was not created with BIND_RAY_TRACING flag");
+
+ const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc();
+
+ CHECK_BUILD_TLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes,
+ "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")");
+
+ CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Build,
+ "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get the required size for scratch buffer");
+
+ CHECK_BUILD_TLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING,
+ "pScratchBuffer was not created with BIND_RAY_TRACING flag");
+#undef CHECK_BUILD_TLAS_ATTRIBS
+
+ return true;
+}
+
+
+bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs)
+{
+#define CHECK_COPY_BLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Copy BLAS attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_COPY_BLAS_ATTRIBS(Attribs.pSrc != nullptr, "pSrc must not be null");
+ CHECK_COPY_BLAS_ATTRIBS(Attribs.pDst != nullptr, "pDst must not be null");
+
+ if (Attribs.Mode == COPY_AS_MODE_CLONE)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ CHECK_COPY_BLAS_ATTRIBS(SrcDesc.TriangleCount == DstDesc.TriangleCount,
+ "Src BLAS triangle count (", SrcDesc.TriangleCount, ") must be equal to the dst BLAS triangle count (", DstDesc.TriangleCount, ")");
+
+ CHECK_COPY_BLAS_ATTRIBS(SrcDesc.BoxCount == DstDesc.BoxCount,
+ "Src BLAS box count (", SrcDesc.BoxCount, ") must be equal to the dst BLAS box count (", DstDesc.BoxCount, ")");
+
+ CHECK_COPY_BLAS_ATTRIBS(SrcDesc.Flags == DstDesc.Flags,
+ "Source and destination BLASes must have been created with the same flags");
+
+ for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i)
+ {
+ auto& SrcTri = SrcDesc.pTriangles[i];
+ auto& DstTri = DstDesc.pTriangles[i];
+
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxVertexCount == DstTri.MaxVertexCount,
+ "MaxVertexCount value (", SrcTri.MaxVertexCount, ") in source triangle description at index ", i,
+ " does not match MaxVertexCount value (", DstTri.MaxVertexCount, ") in the destination description");
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexValueType == DstTri.VertexValueType,
+ "VertexValueType value (", GetValueTypeString(SrcTri.VertexValueType), ") in source triangle description at index ", i,
+ " does not match VertexValueType value (", GetValueTypeString(DstTri.VertexValueType), ") in destination description");
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexComponentCount == DstTri.VertexComponentCount,
+ "VertexComponentCount value (", Uint32{SrcTri.VertexComponentCount}, ") in source triangle description at index ", i,
+ " does not match VertexComponentCount value (", Uint32{DstTri.VertexComponentCount}, ") in destination description");
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxPrimitiveCount == DstTri.MaxPrimitiveCount,
+ "MaxPrimitiveCount value (", SrcTri.MaxPrimitiveCount, ") in source triangle description at index ", i,
+ " does not match MaxPrimitiveCount value (", DstTri.MaxPrimitiveCount, ") in destination description");
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.IndexType == DstTri.IndexType,
+ "IndexType value (", GetValueTypeString(SrcTri.IndexType), ") in source triangle description at index ", i,
+ " does not match IndexType value (", GetValueTypeString(DstTri.IndexType), ") in destination description");
+ CHECK_COPY_BLAS_ATTRIBS(SrcTri.AllowsTransforms == DstTri.AllowsTransforms,
+ "AllowsTransforms value (", (SrcTri.AllowsTransforms ? "true" : "false"), ") in source triangle description at index ", i,
+ " does not match AllowsTransforms value (", (DstTri.AllowsTransforms ? "true" : "false"), ") in destination description");
+ }
+
+ for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i)
+ {
+ CHECK_COPY_BLAS_ATTRIBS(SrcDesc.pBoxes[i].MaxBoxCount == DstDesc.pBoxes[i].MaxBoxCount,
+ "MaxBoxCountt value (", SrcDesc.pBoxes[i].MaxBoxCount, ") in source box description at index ", i,
+ " does not match MaxBoxCount value (", DstDesc.pBoxes[i].MaxBoxCount, ") in destination description");
+ }
+ }
+ else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ CHECK_COPY_BLAS_ATTRIBS((SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, "must be have been create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ CHECK_COPY_BLAS_ATTRIBS(DstDesc.CompactedSize != 0, "pDst must have been create with non-zero CompactedSize");
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode");
+ return false;
+ }
+
+#undef CHECK_COPY_BLAS_ATTRIBS
+
+ return true;
+}
+
+
+bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs)
+{
+#define CHECK_COPY_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Copy TLAS attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_COPY_TLAS_ATTRIBS(Attribs.pSrc != nullptr, "pSrc must not be null");
+ CHECK_COPY_TLAS_ATTRIBS(Attribs.pDst != nullptr, "pDst must not be null");
+
+ if (Attribs.Mode == COPY_AS_MODE_CLONE)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ CHECK_COPY_TLAS_ATTRIBS(SrcDesc.MaxInstanceCount == DstDesc.MaxInstanceCount || SrcDesc.Flags == DstDesc.Flags,
+ "pDst must have been created with the same parameters as pSrc");
+ }
+ else if (Attribs.Mode == COPY_AS_MODE_COMPACT)
+ {
+ auto& SrcDesc = Attribs.pSrc->GetDesc();
+ auto& DstDesc = Attribs.pDst->GetDesc();
+
+ CHECK_COPY_TLAS_ATTRIBS((SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, "pSrc was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+ CHECK_COPY_TLAS_ATTRIBS(DstDesc.CompactedSize != 0, "pDst must have been create with non-zero CompactedSize");
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode");
+ return false;
+ }
+#undef CHECK_COPY_TLAS_ATTRIBS
+
+ return true;
+}
+
+bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs)
+{
+#define CHECK_WRITE_BLAS_SIZE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Write compacted BLAS size attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.pBLAS != nullptr, "pBLAS must not be null");
+ CHECK_WRITE_BLAS_SIZE_ATTRIBS((Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION,
+ "pBLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+
+ CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null");
+ CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes,
+ "pDestBuffer is too small");
+
+ if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12)
+ {
+ CHECK_WRITE_BLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS,
+ "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag in Direct3D12");
+ }
+
+#undef CHECK_WRITE_BLAS_SIZE_ATTRIBS
+
+ return true;
+}
+
+bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs)
+{
+#define CHECK_WRITE_TLAS_SIZE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Write compacted TLAS size attribs are invalid: ", __VA_ARGS__)
+
+ CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.pTLAS != nullptr, "pTLAS must not be null");
+ CHECK_WRITE_TLAS_SIZE_ATTRIBS((Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION,
+ "pTLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag");
+
+ CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null");
+ CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes, "pDestBuffer is too small");
+
+ if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12)
+ {
+ CHECK_WRITE_TLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS,
+ "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag");
+ }
+
+#undef CHECK_WRITE_TLAS_SIZE_ATTRIBS
+
+ return true;
+}
+
+bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs)
+{
+#define CHECK_TRACE_RAYS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Trace rays attribs are invalid: ", __VA_ARGS__)
+ CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT != nullptr, "pSBT must not be null");
+
+#ifdef DILIGENT_DEVELOPMENT
+ CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT->Verify(), "pSBT content is not valid");
+#endif // DILIGENT_DEVELOPMENT
+
+ CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionX != 0, "DimensionX must not be zero.");
+ CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionY != 0, "DimensionY must not be zero.");
+ CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionZ != 0, "DimensionZ must not be zero.");
+
+#undef CHECK_TRACE_RAYS_ATTRIBS
+
+ return true;
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/src/FramebufferBase.cpp b/Graphics/GraphicsEngine/src/FramebufferBase.cpp
index 0434bf0a..1a173910 100644
--- a/Graphics/GraphicsEngine/src/FramebufferBase.cpp
+++ b/Graphics/GraphicsEngine/src/FramebufferBase.cpp
@@ -31,7 +31,7 @@
namespace Diligent
{
-void ValidateFramebufferDesc(const FramebufferDesc& Desc)
+void ValidateFramebufferDesc(const FramebufferDesc& Desc) noexcept(false)
{
#define LOG_FRAMEBUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of framebuffer '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)