summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-07 21:59:11 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-02-07 21:59:11 +0000
commitcfc713b96b3aef8726ffe1f0d0af0e572d5ce84b (patch)
treee982610d8a0d9ca230c86eadc0e87ea41039e0b9 /Graphics/GraphicsEngineD3D12
parentReworked ExecuteCommandList(s) to take multiple command lists instead of one (diff)
downloadDiligentCore-cfc713b96b3aef8726ffe1f0d0af0e572d5ce84b.tar.gz
DiligentCore-cfc713b96b3aef8726ffe1f0d0af0e572d5ce84b.zip
DeviceContextD3D12Impl: reworked flush to also execute deferred command lists to avoid redundant submit
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp79
2 files changed, 44 insertions, 39 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
index 15c85492..39ac2431 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
@@ -346,7 +346,9 @@ private:
void CommitScissorRects(class GraphicsContext& GraphCtx, bool ScissorEnable);
void TransitionSubpassAttachments(Uint32 NextSubpass);
void CommitSubpassRenderTargets();
- void Flush(bool RequestNewCmdCtx);
+ void Flush(bool RequestNewCmdCtx,
+ Uint32 NumCommandLists = 0,
+ ICommandList* const* ppCommandLists = nullptr);
__forceinline void RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl);
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index b7415753..1cd2f766 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -773,26 +773,52 @@ void DeviceContextD3D12Impl::RequestCommandContext(RenderDeviceD3D12Impl* pDevic
m_CurrCmdCtx->SetDynamicGPUDescriptorAllocators(m_DynamicGPUDescriptorAllocator);
}
-void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx)
+void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx,
+ Uint32 NumCommandLists,
+ ICommandList* const* ppCommandLists)
{
+ VERIFY(!m_bIsDeferred || NumCommandLists == 0 && ppCommandLists == nullptr, "Only immediate context can execute command lists");
+
+ if (m_ActiveQueriesCounter > 0)
+ {
+ LOG_ERROR_MESSAGE("Flushing device context that has ", m_ActiveQueriesCounter,
+ " active queries. Direct3D12 requires that queries are begun and ended in the same command list");
+ }
+
+ // TODO: use small_vector
+ std::vector<RenderDeviceD3D12Impl::PooledCommandContext> Contexts;
+ Contexts.reserve(NumCommandLists + 1);
+
+ // First, execute current context
if (m_CurrCmdCtx)
{
VERIFY(!m_bIsDeferred, "Deferred contexts cannot execute command lists directly");
if (m_State.NumCommands != 0)
- {
- m_CurrCmdCtx->FlushResourceBarriers();
- m_pDevice->CloseAndExecuteCommandContexts(m_CommandQueueId, 1, &m_CurrCmdCtx, true, &m_PendingFences);
- VERIFY(!m_CurrCmdCtx, "Context must be disposed by CloseAndExecuteCommandContexts");
- m_PendingFences.clear();
- }
+ Contexts.emplace_back(std::move(m_CurrCmdCtx));
else
m_pDevice->DisposeCommandContext(std::move(m_CurrCmdCtx));
}
- if (m_ActiveQueriesCounter > 0)
+ // Next, add extra command lists from deferred contexts
+ for (Uint32 i = 0; i < NumCommandLists; ++i)
{
- LOG_ERROR_MESSAGE("Flushing device context that has ", m_ActiveQueriesCounter,
- " active queries. Direct3D12 requires that queries are begun and ended in the same command list");
+ auto* const pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(ppCommandLists[i]);
+
+ RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtx;
+ Contexts.emplace_back(pCmdListD3D12->Close(pDeferredCtx));
+ // Set the bit in the deferred context cmd queue mask corresponding to the cmd queue of this context
+ pDeferredCtx->m_SubmittedBuffersCmdQueueMask.fetch_or(Uint64{1} << m_CommandQueueId);
+ }
+
+ if (!Contexts.empty())
+ {
+ m_pDevice->CloseAndExecuteCommandContexts(m_CommandQueueId, static_cast<Uint32>(Contexts.size()), Contexts.data(), true, &m_PendingFences);
+ m_PendingFences.clear();
+
+#ifdef DILIGENT_DEBUG
+ for (Uint32 i = 0; i < NumCommandLists; ++i)
+ VERIFY(!Contexts[i], "All contexts must be disposed by CloseAndExecuteCommandContexts");
+#endif
}
// If there is no command list to submit, but there are pending fences, we need to signal them now
@@ -2036,7 +2062,7 @@ void DeviceContextD3D12Impl::GenerateMips(ITextureView* pTexView)
void DeviceContextD3D12Impl::FinishCommandList(ICommandList** ppCommandList)
{
- VERIFY(m_pActiveRenderPass == nullptr, "Finishing command list inside an active render pass.");
+ DEV_CHECK_ERR(m_pActiveRenderPass == nullptr, "Finishing command list inside an active render pass.");
CommandListD3D12Impl* pCmdListD3D12(NEW_RC_OBJ(m_CmdListAllocator, "CommandListD3D12Impl instance", CommandListD3D12Impl)(m_pDevice, this, std::move(m_CurrCmdCtx)));
pCmdListD3D12->QueryInterface(IID_CommandList, reinterpret_cast<IObject**>(ppCommandList));
@@ -2058,43 +2084,20 @@ void DeviceContextD3D12Impl::ExecuteCommandLists(Uint32 NumCommand
return;
DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero");
- // First execute commands in this context
- Flush(true);
+ Flush(true, NumCommandLists, ppCommandLists);
InvalidateState();
-
- VERIFY_EXPR(m_PendingFences.empty());
-
- // TODO: use small_vector
- std::vector<RenderDeviceD3D12Impl::PooledCommandContext> Contexts;
- Contexts.reserve(NumCommandLists);
- for (Uint32 i = 0; i < NumCommandLists; ++i)
- {
- auto* const pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(ppCommandLists[i]);
-
- RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtx;
- Contexts.emplace_back(pCmdListD3D12->Close(pDeferredCtx));
- // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
- pDeferredCtx->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
- }
-
- m_pDevice->CloseAndExecuteCommandContexts(m_CommandQueueId, NumCommandLists, Contexts.data(), true, nullptr);
-
-#ifdef DILIGENT_DEBUG
- for (Uint32 i = 0; i < NumCommandLists; ++i)
- VERIFY(!Contexts[i], "All contexts must be disposed by CloseAndExecuteCommandContexts");
-#endif
}
void DeviceContextD3D12Impl::SignalFence(IFence* pFence, Uint64 Value)
{
- VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
+ DEV_CHECK_ERR(!m_bIsDeferred, "Fence can only be signaled from immediate context");
m_PendingFences.emplace_back(Value, pFence);
}
void DeviceContextD3D12Impl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
{
- VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ DEV_CHECK_ERR(!m_bIsDeferred, "Fence can only be waited from immediate context");
if (FlushContext)
Flush();
auto* pFenceD3D12 = ValidatedCast<FenceD3D12Impl>(pFence);
@@ -2103,7 +2106,7 @@ void DeviceContextD3D12Impl::WaitForFence(IFence* pFence, Uint64 Value, bool Flu
void DeviceContextD3D12Impl::WaitForIdle()
{
- VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
+ DEV_CHECK_ERR(!m_bIsDeferred, "Only immediate contexts can be idled");
Flush();
m_pDevice->IdleCommandQueue(m_CommandQueueId, true);
}