summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-07 20:50:39 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-02-07 20:50:39 +0000
commitc6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c (patch)
treee8848a7e01b2f576c11e9f9acfee6eca9fcdd681 /Graphics/GraphicsEngineD3D12
parentSwap chain Vk: improved presentation mode selection (fixed https://github.com... (diff)
downloadDiligentCore-c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c.tar.gz
DiligentCore-c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c.zip
Reworked ExecuteCommandList(s) to take multiple command lists instead of one
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp3
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp5
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp9
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h11
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp16
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp40
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp46
7 files changed, 97 insertions, 33 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp
index 4211d384..20f81af3 100644
--- a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp
@@ -52,7 +52,8 @@ public:
virtual Uint64 DILIGENT_CALL_TYPE GetNextFenceValue() const override final { return m_NextFenceValue; }
// Implementation of ICommandQueueD3D12::Submit().
- virtual Uint64 DILIGENT_CALL_TYPE Submit(ID3D12GraphicsCommandList* commandList) override final;
+ virtual Uint64 DILIGENT_CALL_TYPE Submit(Uint32 NumCommandLists,
+ ID3D12CommandList* const* ppCommandLists) override final;
// Implementation of ICommandQueueD3D12::GetD3D12CommandQueue().
virtual ID3D12CommandQueue* DILIGENT_CALL_TYPE GetD3D12CommandQueue() override final { return m_pd3d12CmdQueue; }
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
index de33a7ff..15c85492 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
@@ -234,8 +234,9 @@ public:
/// Implementation of IDeviceContext::FinishCommandList() in Direct3D12 backend.
virtual void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final;
- /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D12 backend.
- virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final;
+ /// Implementation of IDeviceContext::ExecuteCommandLists() in Direct3D12 backend.
+ virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists,
+ ICommandList* const* ppCommandLists) override final;
/// Implementation of IDeviceContext::SignalFence() in Direct3D12 backend.
virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final;
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
index 984afd41..707e59c0 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp
@@ -174,10 +174,11 @@ public:
void CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx);
- Uint64 CloseAndExecuteCommandContext(Uint32 QueueIndex,
- PooledCommandContext&& Ctx,
- bool DiscardStaleObjects,
- std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences);
+ Uint64 CloseAndExecuteCommandContexts(Uint32 QueueIndex,
+ Uint32 NumContexts,
+ PooledCommandContext pContexts[],
+ bool DiscardStaleObjects,
+ std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences);
void SignalFences(Uint32 QueueIndex, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>& SignalFences);
diff --git a/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h b/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
index c9d09d34..9b1ff33a 100644
--- a/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/CommandQueueD3D12.h
@@ -53,11 +53,16 @@ DILIGENT_BEGIN_INTERFACE(ICommandQueueD3D12, IObject)
/// Returns the fence value that will be signaled next time
VIRTUAL Uint64 METHOD(GetNextFenceValue)(THIS) CONST PURE;
- /// Executes a given command list
+ /// Submits command lists for execution.
- /// \return Fence value associated with the executed command list
+ /// \param[in] NumCommandLists - The number of command lists to submit.
+ /// \param[in] ppCommandLists - A pointer to the array of NumCommandLists command
+ /// lists to submit.
+ ///
+ /// \return Fence value associated with the executed command lists.
VIRTUAL Uint64 METHOD(Submit)(THIS_
- ID3D12GraphicsCommandList* commandList) PURE;
+ Uint32 NumCommandLists,
+ ID3D12CommandList* const* ppCommandLists) PURE;
/// Returns D3D12 command queue. May return null if queue is anavailable
VIRTUAL ID3D12CommandQueue* METHOD(GetD3D12CommandQueue)(THIS) PURE;
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
index 25d8362c..cedf76f7 100644
--- a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp
@@ -51,7 +51,8 @@ CommandQueueD3D12Impl::~CommandQueueD3D12Impl()
CloseHandle(m_WaitForGPUEventHandle);
}
-Uint64 CommandQueueD3D12Impl::Submit(ID3D12GraphicsCommandList* commandList)
+Uint64 CommandQueueD3D12Impl::Submit(Uint32 NumCommandLists,
+ ID3D12CommandList* const* ppCommandLists)
{
std::lock_guard<std::mutex> Lock{m_QueueMtx};
@@ -59,10 +60,17 @@ Uint64 CommandQueueD3D12Impl::Submit(ID3D12GraphicsCommandList* commandList)
// Increment the value before submitting the list
Atomics::AtomicIncrement(m_NextFenceValue);
- if (commandList != nullptr)
+ // Render device submits null command list to signal the fence and
+ // discard all resources.
+ if (NumCommandLists != 0 && ppCommandLists != nullptr)
{
- ID3D12CommandList* const ppCmdLists[] = {commandList};
- m_pd3d12CmdQueue->ExecuteCommandLists(1, ppCmdLists);
+#ifdef DILIGENT_DEBUG
+ for (Uint32 i = 0; i < NumCommandLists; ++i)
+ {
+ VERIFY(ppCommandLists[i] != nullptr, "Command list must not be null");
+ }
+#endif
+ m_pd3d12CmdQueue->ExecuteCommandLists(NumCommandLists, ppCommandLists);
}
// Signal the fence. This must be done atomically with command list submission.
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index ec14d2f5..b7415753 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -26,7 +26,10 @@
*/
#include "pch.h"
+
#include <sstream>
+#include <vector>
+
#include "RenderDeviceD3D12Impl.hpp"
#include "DeviceContextD3D12Impl.hpp"
#include "PipelineStateD3D12Impl.hpp"
@@ -778,7 +781,8 @@ void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx)
if (m_State.NumCommands != 0)
{
m_CurrCmdCtx->FlushResourceBarriers();
- m_pDevice->CloseAndExecuteCommandContext(m_CommandQueueId, std::move(m_CurrCmdCtx), true, &m_PendingFences);
+ m_pDevice->CloseAndExecuteCommandContexts(m_CommandQueueId, 1, &m_CurrCmdCtx, true, &m_PendingFences);
+ VERIFY(!m_CurrCmdCtx, "Context must be disposed by CloseAndExecuteCommandContexts");
m_PendingFences.clear();
}
else
@@ -2041,25 +2045,45 @@ void DeviceContextD3D12Impl::FinishCommandList(ICommandList** ppCommandList)
InvalidateState();
}
-void DeviceContextD3D12Impl::ExecuteCommandList(ICommandList* pCommandList)
+void DeviceContextD3D12Impl::ExecuteCommandLists(Uint32 NumCommandLists,
+ ICommandList* const* ppCommandLists)
{
if (m_bIsDeferred)
{
LOG_ERROR_MESSAGE("Only immediate context can execute command list");
return;
}
+
+ if (NumCommandLists == 0)
+ return;
+ DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero");
+
// First execute commands in this context
Flush(true);
InvalidateState();
- CommandListD3D12Impl* pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(pCommandList);
VERIFY_EXPR(m_PendingFences.empty());
- RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtx;
- auto CmdContext = pCmdListD3D12->Close(pDeferredCtx);
- m_pDevice->CloseAndExecuteCommandContext(m_CommandQueueId, std::move(CmdContext), true, nullptr);
- // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
- pDeferredCtx->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
+
+ // 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)
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 14339102..8b22a8c3 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -26,7 +26,10 @@
*/
#include "pch.h"
+
#include <dxgi1_4.h>
+#include <vector>
+
#include "RenderDeviceD3D12Impl.hpp"
#include "PipelineStateD3D12Impl.hpp"
#include "ShaderD3D12Impl.hpp"
@@ -406,22 +409,41 @@ void RenderDeviceD3D12Impl::FreeCommandContext(PooledCommandContext&& Ctx)
void RenderDeviceD3D12Impl::CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx)
{
CComPtr<ID3D12CommandAllocator> pAllocator;
- ID3D12GraphicsCommandList* pCmdList = Ctx->Close(pAllocator);
- Uint64 FenceValue = 0;
+ ID3D12CommandList* const pCmdList = Ctx->Close(pAllocator);
+ VERIFY(pCmdList != nullptr, "Command list must not be null");
+ Uint64 FenceValue = 0;
// Execute command list directly through the queue to avoid interference with command list numbers in the queue
LockCmdQueueAndRun(CommandQueueIndex,
[&](ICommandQueueD3D12* pCmdQueue) //
{
- FenceValue = pCmdQueue->Submit(pCmdList);
+ FenceValue = pCmdQueue->Submit(1, &pCmdList);
});
m_CmdListManager.ReleaseAllocator(std::move(pAllocator), CommandQueueIndex, FenceValue);
FreeCommandContext(std::move(Ctx));
}
-Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(Uint32 QueueIndex, PooledCommandContext&& Ctx, bool DiscardStaleObjects, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences)
+Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContexts(Uint32 QueueIndex,
+ Uint32 NumContexts,
+ PooledCommandContext pContexts[],
+ bool DiscardStaleObjects,
+ std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences)
{
- CComPtr<ID3D12CommandAllocator> pAllocator;
- ID3D12GraphicsCommandList* pCmdList = Ctx->Close(pAllocator);
+ VERIFY_EXPR(NumContexts > 0 && pContexts != 0);
+
+ // TODO: use small_vector
+ std::vector<ID3D12CommandList*> d3d12CmdLists;
+ std::vector<CComPtr<ID3D12CommandAllocator>> CmdAllocators;
+ d3d12CmdLists.reserve(NumContexts);
+ CmdAllocators.reserve(NumContexts);
+
+ for (Uint32 i = 0; i < NumContexts; ++i)
+ {
+ auto& pCtx = pContexts[i];
+ VERIFY_EXPR(pCtx);
+ CComPtr<ID3D12CommandAllocator> pAllocator;
+ d3d12CmdLists.emplace_back(pCtx->Close(pAllocator));
+ CmdAllocators.emplace_back(std::move(pAllocator));
+ }
Uint64 FenceValue = 0;
{
@@ -443,14 +465,17 @@ Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(Uint32 QueueIndex, P
// | N+1, but resource it references | |
// | was added to the delete queue | |
// | with number N | |
- auto SubmittedCmdBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, pCmdList, true);
+ auto SubmittedCmdBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, true, NumContexts, d3d12CmdLists.data());
FenceValue = SubmittedCmdBuffInfo.FenceValue;
if (pSignalFences != nullptr)
SignalFences(QueueIndex, *pSignalFences);
}
- m_CmdListManager.ReleaseAllocator(std::move(pAllocator), QueueIndex, FenceValue);
- FreeCommandContext(std::move(Ctx));
+ for (Uint32 i = 0; i < NumContexts; ++i)
+ {
+ m_CmdListManager.ReleaseAllocator(std::move(CmdAllocators[i]), QueueIndex, FenceValue);
+ FreeCommandContext(std::move(pContexts[i]));
+ }
PurgeReleaseQueue(QueueIndex);
@@ -477,8 +502,7 @@ void RenderDeviceD3D12Impl::FlushStaleResources(Uint32 CmdQueueIndex)
{
// Submit empty command list to the queue. This will effectively signal the fence and
// discard all resources
- ID3D12GraphicsCommandList* pNullCmdList = nullptr;
- TRenderDeviceBase::SubmitCommandBuffer(CmdQueueIndex, pNullCmdList, true);
+ TRenderDeviceBase::SubmitCommandBuffer(CmdQueueIndex, true, 0, nullptr);
}
void RenderDeviceD3D12Impl::ReleaseStaleResources(bool ForceRelease)