diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-11-21 06:01:03 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-11-21 06:01:03 +0000 |
| commit | 47eb24bb2abc8741667ae0fc7423515c93057e37 (patch) | |
| tree | 609daaa99f5a8cedb3473e192df9ce78fc81fa9b /Graphics | |
| parent | Implemented explicit state transitions in D3D11 backend (closed https://githu... (diff) | |
| download | DiligentCore-47eb24bb2abc8741667ae0fc7423515c93057e37.tar.gz DiligentCore-47eb24bb2abc8741667ae0fc7423515c93057e37.zip | |
Added explicit control of vertex buffer, index buffer and indirect draw arguments buffer transitions to the API
Diffstat (limited to 'Graphics')
7 files changed, 301 insertions, 62 deletions
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 6c5b0d85..62adfd72 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -51,6 +51,25 @@ namespace Diligent static constexpr INTERFACE_ID IID_DeviceContext = { 0xdc92711b, 0xa1be, 0x4319, { 0xb2, 0xbd, 0xc6, 0x62, 0xd1, 0xcc, 0x19, 0xe4 } }; +/// Draw command flags +enum DRAW_FLAGS : Uint8 +{ + /// Perform no state transitions + DRAW_FLAG_NONE = 0x00, + + /// Transition vertex buffers to RESOURCE_STATE_VERTEX_BUFFER state (see Diligent::RESOURCE_STATE). + /// Vertex buffers in unknown state will not be transitioned. + DRAW_FLAG_TRANSITION_VERTEX_BUFFERS = 0x01, + + /// Transition index buffer to RESOURCE_STATE_INDEX_BUFFER state (see Diligent::RESOURCE_STATE). + /// If the index buffer is in unknown state, this flag has no effect. + DRAW_FLAG_TRANSITION_INDEX_BUFFER = 0x02, + + /// Transition indirect draw arguments buffer to RESOURCE_STATE_INDIRECT_ARGUMENT state (see Diligent::RESOURCE_STATE). + /// If the buffer is in unknown state, this flag has no effect. + DRAW_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER = 0x04 +}; + /// Defines the draw command attributes /// This structure is used by IRenderDevice::Draw() @@ -72,6 +91,9 @@ struct DrawAttribs /// Allowed values: VT_UINT16 and VT_UINT32. Ignored if DrawAttribs::IsIndexed is False. VALUE_TYPE IndexType = VT_UNDEFINED; + /// Additional flags controlling the draw command behavior, see Diligent::DRAW_FLAGS. + Uint8 Flags = DRAW_FLAG_NONE; + /// Number of instances to draw. If more than one instance is specified, /// instanced draw call will be performed. Uint32 NumInstances = 1; @@ -111,6 +133,7 @@ struct DrawAttribs /// NumVertices | 0 /// IsIndexed | False /// IndexType | VT_UNDEFINED + /// Flags | DRAW_FLAG_NONE /// NumInstances | 1 /// BaseVertex | 0 /// IndirectDrawArgsOffset | 0 @@ -129,6 +152,18 @@ enum CLEAR_DEPTH_STENCIL_FLAGS : Int32 CLEAR_STENCIL_FLAG = 0x02 ///< Clear stencil part of the buffer }; + +/// Dispatch compute command flags +enum DISPATCH_FLAGS : Uint8 +{ + /// Perform no state transitions + DISPATCH_FLAG_FLAG_NONE = 0x00, + + /// Transition indirect dispatch arguments buffer to RESOURCE_STATE_INDIRECT_ARGUMENT state (see Diligent::RESOURCE_STATE). + /// If the buffer is in unknown state, this flag has no effect. + DISPATCH_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER = 0x01 +}; + /// Describes dispatch command arguments. /// [Dispatch]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476405(v=vs.85).aspx @@ -149,6 +184,9 @@ struct DispatchComputeAttribs /// of the buffer to the dispatch command arguments. Ignored otherwise Uint32 DispatchArgsByteOffset; + /// Flags controlling the dispatch command behavior, see Diligent::DISPATCH_FLAGS. + Uint8 Flags = DISPATCH_FLAG_FLAG_NONE; + /// Initializes the structure to perform non-indirect dispatch command /// \param [in] GroupsX - Number of groups dispatched in X direction. Default value is 1. diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h index a858d543..661dd405 100755 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h @@ -117,10 +117,10 @@ public: private:
/// Commits d3d11 index buffer to the d3d11 device context.
- void CommitD3D11IndexBuffer(VALUE_TYPE IndexType);
+ void CommitD3D11IndexBuffer(VALUE_TYPE IndexType, bool TransitionBuffer);
/// Commits d3d11 vertex buffers to the d3d11 device context.
- void CommitD3D11VertexBuffers(class PipelineStateD3D11Impl* pPipelineStateD3D11);
+ void CommitD3D11VertexBuffers(class PipelineStateD3D11Impl* pPipelineStateD3D11, bool TransitionBuffers);
/// Helper template function used to facilitate resource unbinding
template<typename TD3D11ResourceViewType,
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index dee55fc8..b240fa1f 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -653,7 +653,7 @@ namespace Diligent }
}
- void DeviceContextD3D11Impl::CommitD3D11IndexBuffer(VALUE_TYPE IndexType)
+ void DeviceContextD3D11Impl::CommitD3D11IndexBuffer(VALUE_TYPE IndexType, bool TransitionBuffer)
{
if( !m_pIndexBuffer )
{
@@ -662,11 +662,25 @@ namespace Diligent }
BufferD3D11Impl* pBuffD3D11 = m_pIndexBuffer.RawPtr<BufferD3D11Impl>();
- if( pBuffD3D11->IsInKnownState() && pBuffD3D11->CheckState(RESOURCE_STATE_UNORDERED_ACCESS) )
+ if (TransitionBuffer)
{
- UnbindResourceFromUAV(pBuffD3D11, pBuffD3D11->m_pd3d11Buffer);
- pBuffD3D11->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ if( pBuffD3D11->IsInKnownState() && pBuffD3D11->CheckState(RESOURCE_STATE_UNORDERED_ACCESS) )
+ {
+ UnbindResourceFromUAV(pBuffD3D11, pBuffD3D11->m_pd3d11Buffer);
+ pBuffD3D11->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+#ifdef DEVELOPMENT
+ else
+ {
+ if( pBuffD3D11->IsInKnownState() && pBuffD3D11->CheckState(RESOURCE_STATE_UNORDERED_ACCESS) )
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11->GetDesc().Name, "' used as index buffer is in RESOURCE_STATE_UNORDERED_ACCESS state."
+ " Use DRAW_FLAG_TRANSITION_INDEX_BUFFER flag or explicitly transition the buffer to RESOURCE_STATE_INDEX_BUFFER state.");
+
+ }
}
+#endif
if( m_CommittedD3D11IndexBuffer != pBuffD3D11->m_pd3d11Buffer ||
m_CommittedIBFormat != IndexType ||
@@ -693,7 +707,7 @@ namespace Diligent m_bCommittedD3D11IBUpToDate = true;
}
- void DeviceContextD3D11Impl::CommitD3D11VertexBuffers(PipelineStateD3D11Impl* pPipelineStateD3D11)
+ void DeviceContextD3D11Impl::CommitD3D11VertexBuffers(PipelineStateD3D11Impl* pPipelineStateD3D11, bool TransitionBuffers)
{
VERIFY( m_NumVertexStreams <= MaxBufferSlots, "Too many buffers are being set" );
UINT NumBuffersToSet = std::max(m_NumVertexStreams, m_NumCommittedD3D11VBs );
@@ -709,11 +723,24 @@ namespace Diligent auto Stride = Strides[Slot];
auto Offset = CurrStream.Offset;
- if(pBuffD3D11Impl != nullptr && pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ if (TransitionBuffers)
{
- UnbindResourceFromUAV(pBuffD3D11Impl, pd3d11Buffer);
- pBuffD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ if (pBuffD3D11Impl != nullptr && pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ UnbindResourceFromUAV(pBuffD3D11Impl, pd3d11Buffer);
+ pBuffD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
}
+#ifdef DEVELOPMENT
+ else
+ {
+ if (pBuffD3D11Impl != nullptr && pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11Impl->GetDesc().Name, "' used as vertex buffer at slot ", Slot, " is in RESOURCE_STATE_UNORDERED_ACCESS state. "
+ "Use DRAW_FLAG_TRANSITION_VERTEX_BUFFER flag or explicitly transition the buffer to RESOURCE_STATE_VERTEX_BUFFER state.");
+ }
+ }
+#endif
// It is safe to perform raw pointer check because device context keeps
// all buffers alive.
@@ -761,7 +788,7 @@ namespace Diligent if( pd3d11InputLayout != nullptr && !m_bCommittedD3D11VBsUpToDate )
{
VERIFY( m_NumVertexStreams >= m_pPipelineState->GetNumBufferSlotsUsed(), "Currently bound pipeline state \"", m_pPipelineState->GetDesc().Name, "\" expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
- CommitD3D11VertexBuffers(m_pPipelineState);
+ CommitD3D11VertexBuffers(m_pPipelineState, drawAttribs.Flags & DRAW_FLAG_TRANSITION_VERTEX_BUFFERS);
}
if( drawAttribs.IsIndexed )
@@ -770,7 +797,7 @@ namespace Diligent m_bCommittedD3D11IBUpToDate = false;
if(!m_bCommittedD3D11IBUpToDate)
{
- CommitD3D11IndexBuffer(drawAttribs.IndexType);
+ CommitD3D11IndexBuffer(drawAttribs.IndexType, drawAttribs.Flags & DRAW_FLAG_TRANSITION_INDEX_BUFFER);
}
}
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h index c8e63264..f0bc93b5 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h @@ -161,8 +161,8 @@ public: Int64 GetCurrentFrameNumber()const {return m_ContextFrameNumber; } private: - void CommitD3D12IndexBuffer(VALUE_TYPE IndexType); - void CommitD3D12VertexBuffers(class GraphicsContext &GraphCtx); + void CommitD3D12IndexBuffer(VALUE_TYPE IndexType, bool TransitionBuffer); + void CommitD3D12VertexBuffers(class GraphicsContext &GraphCtx, bool TransitionBuffers); void TransitionD3D12VertexBuffers(class GraphicsContext &GraphCtx); void CommitRenderTargets(); void CommitViewports(); diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 76e37ff5..494986d3 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -257,7 +257,7 @@ namespace Diligent } } - void DeviceContextD3D12Impl::CommitD3D12IndexBuffer(VALUE_TYPE IndexType) + void DeviceContextD3D12Impl::CommitD3D12IndexBuffer(VALUE_TYPE IndexType, bool TransitionBuffer) { VERIFY( m_pIndexBuffer != nullptr, "Index buffer is not set up for indexed draw command" ); @@ -287,8 +287,24 @@ namespace Diligent pBuffD3D12->DvpVerifyDynamicAllocation(this); #endif auto& GraphicsCtx = GetCmdContext().AsGraphicsContext(); - if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) - GraphicsCtx.TransitionResource(pBuffD3D12, RESOURCE_STATE_INDEX_BUFFER); + + if (TransitionBuffer) + { + if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + GraphicsCtx.TransitionResource(pBuffD3D12, RESOURCE_STATE_INDEX_BUFFER); + } +#ifdef DEVELOPMENT + else + { + if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBuffD3D12->GetDesc().Name, "' used as index buffer must be in RESOURCE_STATE_INDEX_BUFFER " + "state. Actual buffer state: ", GetResourceStateString(pBuffD3D12->GetState()), + ". Use DRAW_FLAG_TRANSITION_INDEX_BUFFER flag or explicitly transition the buffer to the required state."); + + } + } +#endif size_t BuffDataStartByteOffset; auto *pd3d12Buff = pBuffD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this); @@ -311,7 +327,7 @@ namespace Diligent void DeviceContextD3D12Impl::TransitionD3D12VertexBuffers(GraphicsContext& GraphCtx) { - for( UINT Buff = 0; Buff < m_NumVertexStreams; ++Buff ) + for( Uint32 Buff = 0; Buff < m_NumVertexStreams; ++Buff ) { auto& CurrStream = m_VertexStreams[Buff]; auto* pBufferD3D12 = CurrStream.pBuffer.RawPtr(); @@ -320,7 +336,7 @@ namespace Diligent } } - void DeviceContextD3D12Impl::CommitD3D12VertexBuffers(GraphicsContext& GraphCtx) + void DeviceContextD3D12Impl::CommitD3D12VertexBuffers(GraphicsContext& GraphCtx, bool TransitionBuffers) { // Do not initialize array with zeroes for performance reasons D3D12_VERTEX_BUFFER_VIEW VBViews[MaxBufferSlots];// = {} @@ -342,8 +358,22 @@ namespace Diligent #endif } - if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) - GraphCtx.TransitionResource(pBufferD3D12, RESOURCE_STATE_VERTEX_BUFFER); + if (TransitionBuffers) + { + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + GraphCtx.TransitionResource(pBufferD3D12, RESOURCE_STATE_VERTEX_BUFFER); + } +#ifdef DEVELOPMENT + else + { + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' used as vertex buffer at slot ", Buff, " must be in " + "RESOURCE_STATE_VERTEX_BUFFER state. Actual buffer state: ", GetResourceStateString(pBufferD3D12->GetState()), + ". Use DRAW_FLAG_TRANSITION_VERTEX_BUFFERS flag or explicitly transition the buffer to the required state."); + } + } +#endif // Device context keeps strong references to all vertex buffers. // When a buffer is unbound, a reference to D3D12 resource is added to the context, @@ -382,20 +412,61 @@ namespace Diligent if( m_State.CommittedIBFormat != drawAttribs.IndexType ) m_State.bCommittedD3D12IBUpToDate = false; + bool TransitionIndexBuffer = (drawAttribs.Flags & DRAW_FLAG_TRANSITION_INDEX_BUFFER) != 0; if (m_State.bCommittedD3D12IBUpToDate) { BufferD3D12Impl *pBuffD3D12 = static_cast<BufferD3D12Impl *>(m_pIndexBuffer.RawPtr()); - if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) - GraphCtx.TransitionResource(pBuffD3D12, RESOURCE_STATE_INDEX_BUFFER); + if(TransitionIndexBuffer) + { + if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + GraphCtx.TransitionResource(pBuffD3D12, RESOURCE_STATE_INDEX_BUFFER); + } +#ifdef DEVELOPMENT + else + { + if (pBuffD3D12->IsInKnownState() && !pBuffD3D12->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBuffD3D12->GetDesc().Name, "' used as index buffer must be in RESOURCE_STATE_INDEX_BUFFER " + "state. Actual buffer state: ", GetResourceStateString(pBuffD3D12->GetState()), + ". Use DRAW_FLAG_TRANSITION_INDEX_BUFFER flag or explicitly transition the buffer to the required state."); + } + } +#endif } else - CommitD3D12IndexBuffer(drawAttribs.IndexType); + { + CommitD3D12IndexBuffer(drawAttribs.IndexType, TransitionIndexBuffer); + } } + bool TransitionVertexBuffers = (drawAttribs.Flags & DRAW_FLAG_TRANSITION_VERTEX_BUFFERS) != 0; if (m_State.bCommittedD3D12VBsUpToDate) - TransitionD3D12VertexBuffers(GraphCtx); + { + if (TransitionVertexBuffers) + { + TransitionD3D12VertexBuffers(GraphCtx); + } +#ifdef DEVELOPMENT + else + { + for( Uint32 Buff = 0; Buff < m_NumVertexStreams; ++Buff ) + { + auto& CurrStream = m_VertexStreams[Buff]; + auto* pBufferD3D12 = CurrStream.pBuffer.RawPtr(); + if (pBufferD3D12 != nullptr && pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' used as vertex buffer at slot ", Buff, " must be in " + "RESOURCE_STATE_VERTEX_BUFFER state. Actual buffer state: ", GetResourceStateString(pBufferD3D12->GetState()), + ". Use DRAW_FLAG_TRANSITION_VERTEX_BUFFERS flag or explicitly transition the buffer to the required state."); + } + } + } +#endif + } else - CommitD3D12VertexBuffers(GraphCtx); + { + CommitD3D12VertexBuffers(GraphCtx, TransitionVertexBuffers); + } GraphCtx.SetRootSignature( m_pPipelineState->GetD3D12RootSignature() ); @@ -420,8 +491,23 @@ namespace Diligent pIndirectDrawAttribsD3D12->DvpVerifyDynamicAllocation(this); #endif - if (pIndirectDrawAttribsD3D12->IsInKnownState() && !pIndirectDrawAttribsD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) - GraphCtx.TransitionResource(pIndirectDrawAttribsD3D12, RESOURCE_STATE_INDIRECT_ARGUMENT); + if (drawAttribs.Flags & DRAW_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER) + { + if (pIndirectDrawAttribsD3D12->IsInKnownState() && !pIndirectDrawAttribsD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + GraphCtx.TransitionResource(pIndirectDrawAttribsD3D12, RESOURCE_STATE_INDIRECT_ARGUMENT); + } +#ifdef DEVELOPMENT + else + { + if (pIndirectDrawAttribsD3D12->IsInKnownState() && !pIndirectDrawAttribsD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + { + LOG_ERROR_MESSAGE("Buffer '", pIndirectDrawAttribsD3D12->GetDesc().Name, "' used as indirect draw arguments buffer must be in RESOURCE_STATE_INDIRECT_ARGUMENT " + "state. Actual buffer state: ", GetResourceStateString(pIndirectDrawAttribsD3D12->GetState()), + ". Use DRAW_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER flag or explicitly transition the buffer to the required state."); + } + } +#endif + size_t BuffDataStartByteOffset; ID3D12Resource *pd3d12ArgsBuff = pIndirectDrawAttribsD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this); GraphCtx.ExecuteIndirect(drawAttribs.IsIndexed ? m_pDrawIndexedIndirectSignature : m_pDrawIndirectSignature, pd3d12ArgsBuff, drawAttribs.IndirectDrawArgsOffset + BuffDataStartByteOffset); @@ -467,8 +553,23 @@ namespace Diligent pBufferD3D12->DvpVerifyDynamicAllocation(this); #endif - if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) - ComputeCtx.TransitionResource(pBufferD3D12, RESOURCE_STATE_INDIRECT_ARGUMENT); + if (DispatchAttrs.Flags & DISPATCH_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER) + { + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + ComputeCtx.TransitionResource(pBufferD3D12, RESOURCE_STATE_INDIRECT_ARGUMENT); + } +#ifdef DEVELOPMENT + else + { + if (pBufferD3D12->IsInKnownState() && !pBufferD3D12->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferD3D12->GetDesc().Name, "' used as indirect dispatch arguments buffer must be in RESOURCE_STATE_INDIRECT_ARGUMENT " + "state. Actual buffer state: ", GetResourceStateString(pBufferD3D12->GetState()), + ". Use DISPATCH_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER flag or explicitly transition the buffer to the required state."); + } + } +#endif + size_t BuffDataStartByteOffset; ID3D12Resource *pd3d12ArgsBuff = pBufferD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this); ComputeCtx.ExecuteIndirect(m_pDispatchIndirectSignature, pd3d12ArgsBuff, DispatchAttrs.DispatchArgsByteOffset + BuffDataStartByteOffset); diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h index e75c7deb..0dc9371a 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h @@ -198,7 +198,7 @@ public: private: void CommitRenderPassAndFramebuffer(); - void CommitVkVertexBuffers(); + void CommitVkVertexBuffers(bool TransitionBuffers); void TransitionVkVertexBuffers(); void CommitViewports(); void CommitScissorRects(); diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 5e2402f7..e8316daf 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -306,7 +306,7 @@ namespace Diligent } } - void DeviceContextVkImpl::CommitVkVertexBuffers() + void DeviceContextVkImpl::CommitVkVertexBuffers(bool TransitionBuffers) { #ifdef DEVELOPMENT if (m_NumVertexStreams < m_pPipelineState->GetNumBufferSlotsUsed()) @@ -329,15 +329,31 @@ namespace Diligent pBufferVk->DvpVerifyDynamicAllocation(this); #endif } - if (pBufferVk->IsInKnownState()) + + if (TransitionBuffers) { - if (!pBufferVk->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + if (pBufferVk->IsInKnownState()) { - TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_VERTEX_BUFFER, true); + if (!pBufferVk->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + { + TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_VERTEX_BUFFER, true); + } + VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)); } - VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)); } - +#ifdef DEVELOPMENT + else + { + if (pBufferVk->IsInKnownState() && !pBufferVk->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferVk->GetDesc().Name, "' used as vertex buffer at slot ", slot, " must be in " + "RESOURCE_STATE_VERTEX_BUFFER state. Actual buffer state: ", GetResourceStateString(pBufferVk->GetState()), + ". Use DRAW_FLAG_TRANSITION_VERTEX_BUFFERS flag or explicitly transition the buffer to the required state."); + + } + } +#endif + // Device context keeps strong references to all vertex buffers. vkVertexBuffers[slot] = pBufferVk->GetVkBuffer(); @@ -400,7 +416,7 @@ namespace Diligent LOG_ERROR_MESSAGE(ss.str()); } - void DeviceContextVkImpl::Draw( DrawAttribs &drawAttribs ) + void DeviceContextVkImpl::Draw( DrawAttribs& drawAttribs ) { #ifdef DEVELOPMENT if (!DvpVerifyDrawArguments(drawAttribs)) @@ -420,25 +436,62 @@ namespace Diligent #endif BufferVkImpl *pBuffVk = m_pIndexBuffer.RawPtr<BufferVkImpl>(); - if (pBuffVk->IsInKnownState()) + if (drawAttribs.Flags & DRAW_FLAG_TRANSITION_INDEX_BUFFER) + { + if (pBuffVk->IsInKnownState()) + { + if (!pBuffVk->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + { + TransitionBufferState(*pBuffVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDEX_BUFFER, true); + } + VERIFY_EXPR(pBuffVk->CheckAccessFlags(VK_ACCESS_INDEX_READ_BIT)); + } + } +#ifdef DEVELOPMENT + else { - if (!pBuffVk->CheckState(RESOURCE_STATE_INDEX_BUFFER)) + if (pBuffVk->IsInKnownState() && !pBuffVk->CheckState(RESOURCE_STATE_INDEX_BUFFER)) { - TransitionBufferState(*pBuffVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDEX_BUFFER, true); + LOG_ERROR_MESSAGE("Buffer '", pBuffVk->GetDesc().Name, "' used as index buffer must be in RESOURCE_STATE_INDEX_BUFFER " + "state. Actual buffer state: ", GetResourceStateString(pBuffVk->GetState()), + ". Use DRAW_FLAG_TRANSITION_INDEX_BUFFER flag or explicitly transition the buffer to the required state."); } - VERIFY_EXPR(pBuffVk->CheckAccessFlags(VK_ACCESS_INDEX_READ_BIT)); } +#endif DEV_CHECK_ERR(drawAttribs.IndexType == VT_UINT16 || drawAttribs.IndexType == VT_UINT32, "Unsupported index format. Only R16_UINT and R32_UINT are allowed."); VkIndexType vkIndexType = drawAttribs.IndexType == VT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32; m_CommandBuffer.BindIndexBuffer(pBuffVk->GetVkBuffer(), m_IndexDataStartOffset + pBuffVk->GetDynamicOffset(m_ContextId, this), vkIndexType); } + auto TransitionVertexBuffers = (drawAttribs.Flags & DRAW_FLAG_TRANSITION_VERTEX_BUFFERS) != 0; if (m_State.CommittedVBsUpToDate) - TransitionVkVertexBuffers(); + { + if (TransitionVertexBuffers) + { + TransitionVkVertexBuffers(); + } +#ifdef DEVELOPMENT + else + { + for (Uint32 slot = 0; slot < m_NumVertexStreams; ++slot ) + { + auto& CurrStream = m_VertexStreams[slot]; + auto* pBufferVk = CurrStream.pBuffer.RawPtr(); + if (pBufferVk != nullptr && pBufferVk->IsInKnownState() && !pBufferVk->CheckState(RESOURCE_STATE_VERTEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferVk->GetDesc().Name, "' used as vertex buffer at slot ", slot, " must be in " + "RESOURCE_STATE_VERTEX_BUFFER state. Actual buffer state: ", GetResourceStateString(pBufferVk->GetState()), + ". Use DRAW_FLAG_TRANSITION_VERTEX_BUFFERS flag or explicitly transition the buffer to the required state."); + } + } + } +#endif + } else - CommitVkVertexBuffers(); - + { + CommitVkVertexBuffers(TransitionVertexBuffers); + } if (m_DescrSetBindInfo.DynamicOffsetCount != 0) m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(this, m_DescrSetBindInfo); #if 0 @@ -455,14 +508,28 @@ namespace Diligent if (pIndirectDrawAttribsVk != nullptr) { // Buffer memory barries must be executed outside of render pass - if (pIndirectDrawAttribsVk->IsInKnownState()) + if(drawAttribs.Flags & DRAW_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER) + { + if (pIndirectDrawAttribsVk->IsInKnownState()) + { + if (!pIndirectDrawAttribsVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + { + TransitionBufferState(*pIndirectDrawAttribsVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDIRECT_ARGUMENT, true); + } + VERIFY_EXPR(pIndirectDrawAttribsVk->CheckAccessFlags(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)); + } + } +#ifdef DEVELOPMENT + else { - if (!pIndirectDrawAttribsVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + if (pIndirectDrawAttribsVk->IsInKnownState() && !pIndirectDrawAttribsVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) { - TransitionBufferState(*pIndirectDrawAttribsVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDIRECT_ARGUMENT, true); + LOG_ERROR_MESSAGE("Buffer '", pIndirectDrawAttribsVk->GetDesc().Name, "' used as indirect draw arguments buffer must be in RESOURCE_STATE_INDIRECT_ARGUMENT " + "state. Actual buffer state: ", GetResourceStateString(pIndirectDrawAttribsVk->GetState()), + ". Use DRAW_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER flag or explicitly transition the buffer to the required state."); } - VERIFY_EXPR(pIndirectDrawAttribsVk->CheckAccessFlags(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)); } +#endif } #ifdef DEVELOPMENT @@ -480,14 +547,6 @@ namespace Diligent if (pIndirectDrawAttribsVk->GetDesc().Usage == USAGE_DYNAMIC) pIndirectDrawAttribsVk->DvpVerifyDynamicAllocation(this); #endif - if (pIndirectDrawAttribsVk->IsInKnownState()) - { - if (!pIndirectDrawAttribsVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) - { - TransitionBufferState(*pIndirectDrawAttribsVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDIRECT_ARGUMENT, true); - } - VERIFY_EXPR(pIndirectDrawAttribsVk->CheckAccessFlags(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)); - } if ( drawAttribs.IsIndexed ) m_CommandBuffer.DrawIndexedIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + drawAttribs.IndirectDrawArgsOffset, 1, 0); @@ -539,15 +598,29 @@ namespace Diligent pBufferVk->DvpVerifyDynamicAllocation(this); #endif - // Buffer memory barries must be executed outside of render pass - if (pBufferVk->IsInKnownState()) + if(DispatchAttrs.Flags & DISPATCH_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER) { - if (!pBufferVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + // Buffer memory barries must be executed outside of render pass + if (pBufferVk->IsInKnownState()) { - TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDIRECT_ARGUMENT, true); + if (!pBufferVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + { + TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_INDIRECT_ARGUMENT, true); + } + VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)); } - VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)); } +#ifdef DEVELOPMENT + else + { + if (pBufferVk->IsInKnownState() && !pBufferVk->CheckState(RESOURCE_STATE_INDIRECT_ARGUMENT)) + { + LOG_ERROR_MESSAGE("Buffer '", pBufferVk->GetDesc().Name, "' used as indirect dispatch arguments buffer must be in RESOURCE_STATE_INDIRECT_ARGUMENT " + "state. Actual buffer state: ", GetResourceStateString(pBufferVk->GetState()), + ". Use DISPATCH_FLAG_TRANSITION_INDIRECT_ARGS_BUFFER flag or explicitly transition the buffer to the required state."); + } + } +#endif m_CommandBuffer.DispatchIndirect(pBufferVk->GetVkBuffer(), pBufferVk->GetDynamicOffset(m_ContextId, this) + DispatchAttrs.DispatchArgsByteOffset); } |
