From c6c5bb5ed3d4e3296e6f65e4072db5cf8bf2452c Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 7 Feb 2021 12:50:39 -0800 Subject: Reworked ExecuteCommandList(s) to take multiple command lists instead of one --- .../include/DeviceContextVkImpl.hpp | 5 +- .../include/RenderDeviceVkImpl.hpp | 12 +++-- .../src/DeviceContextVkImpl.cpp | 53 ++++++++++++++++------ .../src/RenderDeviceVkImpl.cpp | 4 +- 4 files changed, 52 insertions(+), 22 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index d9a2c2f2..a385f8aa 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -233,8 +233,9 @@ public: /// Implementation of IDeviceContext::FinishCommandList() in Vulkan backend. virtual void DILIGENT_CALL_TYPE FinishCommandList(class ICommandList** ppCommandList) override final; - /// Implementation of IDeviceContext::ExecuteCommandList() in Vulkan backend. - virtual void DILIGENT_CALL_TYPE ExecuteCommandList(class ICommandList* pCommandList) override final; + /// Implementation of IDeviceContext::ExecuteCommandLists() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE ExecuteCommandLists(Uint32 NumCommandLists, + ICommandList* const* ppCommandLists) override final; /// Implementation of IDeviceContext::SignalFence() in Vulkan backend. virtual void DILIGENT_CALL_TYPE SignalFence(IFence* pFence, Uint64 Value) override final; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 37052725..60b8ebf1 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -230,12 +230,18 @@ private: virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; - // Submits command buffer for execution to the command queue - // Returns the submitted command buffer number and the fence value + // Submits command buffer(s) for execution to the command queue and + // returns the submitted command buffer(s) number and the fence value. + // If SubmitInfo contains multiple command buffers, they all are treated + // like one and sumbitted atomically. // Parameters: // * SubmittedCmdBuffNumber - submitted command buffer number // * SubmittedFenceValue - fence value associated with the submitted command buffer - void SubmitCommandBuffer(Uint32 QueueIndex, const VkSubmitInfo& SubmitInfo, Uint64& SubmittedCmdBuffNumber, Uint64& SubmittedFenceValue, std::vector>>* pFences); + void SubmitCommandBuffer(Uint32 QueueIndex, + const VkSubmitInfo& SubmitInfo, + Uint64& SubmittedCmdBuffNumber, + Uint64& SubmittedFenceValue, + std::vector>>* pFences); std::shared_ptr m_VulkanInstance; std::unique_ptr m_PhysicalDevice; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 8516a174..3259e07e 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -26,7 +26,10 @@ */ #include "pch.h" + #include +#include + #include "RenderDeviceVkImpl.hpp" #include "DeviceContextVkImpl.hpp" #include "PipelineStateVkImpl.hpp" @@ -2098,7 +2101,8 @@ void DeviceContextVkImpl::FinishCommandList(class ICommandList** ppCommandList) InvalidateState(); } -void DeviceContextVkImpl::ExecuteCommandList(class ICommandList* pCommandList) +void DeviceContextVkImpl::ExecuteCommandLists(Uint32 NumCommandLists, + ICommandList* const* ppCommandLists) { if (m_bIsDeferred) { @@ -2106,31 +2110,50 @@ void DeviceContextVkImpl::ExecuteCommandList(class ICommandList* pCommandList) return; } + if (NumCommandLists == 0) + return; + DEV_CHECK_ERR(ppCommandLists != nullptr, "ppCommandLists must not be null when NumCommandLists is not zero"); + Flush(); InvalidateState(); - CommandListVkImpl* pCmdListVk = ValidatedCast(pCommandList); - VkCommandBuffer vkCmdBuff = VK_NULL_HANDLE; + // TODO: replace with small_vector + std::vector vkCmdBuffs; + std::vector> DeferredCtxs; + vkCmdBuffs.reserve(NumCommandLists); + DeferredCtxs.reserve(NumCommandLists); + for (Uint32 i = 0; i < NumCommandLists; ++i) + { + auto* pCmdListVk = ValidatedCast(ppCommandLists[i]); + DEV_CHECK_ERR(pCmdListVk != nullptr, "Command list must not be null"); + VkCommandBuffer vkCmdBuff = VK_NULL_HANDLE; + RefCntAutoPtr pDeferredCtx; + pCmdListVk->Close(vkCmdBuff, pDeferredCtx); + VERIFY(vkCmdBuff != VK_NULL_HANDLE, "Trying to execute empty command buffer"); + VERIFY_EXPR(pDeferredCtx); + vkCmdBuffs.emplace_back(vkCmdBuff); + DeferredCtxs.emplace_back(std::move(pDeferredCtx)); + } - RefCntAutoPtr pDeferredCtx; - pCmdListVk->Close(vkCmdBuff, pDeferredCtx); - VERIFY(vkCmdBuff != VK_NULL_HANDLE, "Trying to execute empty command buffer"); - VERIFY_EXPR(pDeferredCtx); VkSubmitInfo SubmitInfo = {}; SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; SubmitInfo.pNext = nullptr; - SubmitInfo.commandBufferCount = 1; - SubmitInfo.pCommandBuffers = &vkCmdBuff; + SubmitInfo.commandBufferCount = NumCommandLists; + SubmitInfo.pCommandBuffers = vkCmdBuffs.data(); VERIFY_EXPR(m_PendingFences.empty()); - auto pDeferredCtxVkImpl = pDeferredCtx.RawPtr(); auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, nullptr); - // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context - pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId; - // It is OK to dispose command buffer from another thread. We are not going to - // record any commands and only need to add the buffer to the queue - pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, vkCmdBuff, SubmittedFenceValue); + + for (Uint32 i = 0; i < NumCommandLists; ++i) + { + auto pDeferredCtxVkImpl = DeferredCtxs[i].RawPtr(); + // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context + pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId; + // It is OK to dispose command buffer from another thread. We are not going to + // record any commands and only need to add the buffer to the queue + pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, std::move(vkCmdBuffs[i]), SubmittedFenceValue); + } } void DeviceContextVkImpl::SignalFence(IFence* pFence, Uint64 Value) diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 90c1a88e..b09d8068 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -399,7 +399,7 @@ void RenderDeviceVkImpl::SubmitCommandBuffer(Uint32 ) { // Submit the command list to the queue - auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, SubmitInfo, true); + auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, true, SubmitInfo); SubmittedFenceValue = CmbBuffInfo.FenceValue; SubmittedCmdBuffNumber = CmbBuffInfo.CmdBufferNumber; if (pFences != nullptr) @@ -443,7 +443,7 @@ void RenderDeviceVkImpl::FlushStaleResources(Uint32 CmdQueueIndex) // Submit empty command buffer to the queue. This will effectively signal the fence and // discard all resources VkSubmitInfo DummySumbitInfo = {}; - TRenderDeviceBase::SubmitCommandBuffer(0, DummySumbitInfo, true); + TRenderDeviceBase::SubmitCommandBuffer(0, true, DummySumbitInfo); } void RenderDeviceVkImpl::ReleaseStaleResources(bool ForceRelease) -- cgit v1.2.3