diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-07 20:50:39 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-02-07 20:50:39 +0000 |
| commit | c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c (patch) | |
| tree | e8848a7e01b2f576c11e9f9acfee6eca9fcdd681 /Graphics/GraphicsEngineD3D12 | |
| parent | Swap chain Vk: improved presentation mode selection (fixed https://github.com... (diff) | |
| download | DiligentCore-c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c.tar.gz DiligentCore-c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c.zip | |
Reworked ExecuteCommandList(s) to take multiple command lists instead of one
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
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) |
