diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-08 19:56:56 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:31:34 +0000 |
| commit | 9220e5a6b5e8449786acb996204b140305df94fc (patch) | |
| tree | b1977c0108e1f6804ff5e9ba7ebe173a8c09f5e1 /Graphics/GraphicsEngineD3D12 | |
| parent | Reworked PipelineResourceSignatureTest.VulkanDescriptorIndexing to validate r... (diff) | |
| parent | Updated readme (diff) | |
| download | DiligentCore-9220e5a6b5e8449786acb996204b140305df94fc.tar.gz DiligentCore-9220e5a6b5e8449786acb996204b140305df94fc.zip | |
Merged master
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
7 files changed, 119 insertions, 50 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..39ac2431 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; @@ -345,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/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..1cd2f766 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" @@ -770,25 +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->CloseAndExecuteCommandContext(m_CommandQueueId, std::move(m_CurrCmdCtx), true, &m_PendingFences); - 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 @@ -2032,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)); @@ -2041,36 +2071,33 @@ 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; } - // First execute commands in this context - Flush(true); - InvalidateState(); + if (NumCommandLists == 0) + return; + DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero"); + + Flush(true, NumCommandLists, ppCommandLists); - 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; + InvalidateState(); } 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); @@ -2079,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); } 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) |
