diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index b0f4b0fe5..0b6ff1fe7 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -225,6 +225,9 @@ namespace dxvk { } // Execute transfer command buffer, if any + if (cmd.usedFlags.test(DxvkCmdBuffer::SdmaBarriers)) + m_commandSubmission.executeCommandBuffer(cmd.cmdBuffers[uint32_t(DxvkCmdBuffer::SdmaBarriers)]); + if (cmd.usedFlags.test(DxvkCmdBuffer::SdmaBuffer)) m_commandSubmission.executeCommandBuffer(cmd.cmdBuffers[uint32_t(DxvkCmdBuffer::SdmaBuffer)]); @@ -249,6 +252,9 @@ namespace dxvk { } // Submit graphics commands + if (cmd.usedFlags.test(DxvkCmdBuffer::InitBarriers)) + m_commandSubmission.executeCommandBuffer(cmd.cmdBuffers[uint32_t(DxvkCmdBuffer::InitBarriers)]); + if (cmd.usedFlags.test(DxvkCmdBuffer::InitBuffer)) m_commandSubmission.executeCommandBuffer(cmd.cmdBuffers[uint32_t(DxvkCmdBuffer::InitBuffer)]); @@ -391,7 +397,7 @@ namespace dxvk { VkCommandBuffer DxvkCommandList::allocateCommandBuffer(DxvkCmdBuffer type) { - return type == DxvkCmdBuffer::SdmaBuffer + return type == DxvkCmdBuffer::SdmaBuffer || type == DxvkCmdBuffer::SdmaBarriers ? m_transferPool->getCommandBuffer() : m_graphicsPool->getCommandBuffer(); } diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 169e536fa..b4975bb2d 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -47,7 +47,9 @@ namespace dxvk { enum class DxvkCmdBuffer : uint32_t { ExecBuffer, InitBuffer, + InitBarriers, SdmaBuffer, + SdmaBarriers, Count }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 45d1ced33..2a6c5e12e 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -10,7 +10,9 @@ namespace dxvk { DxvkContext::DxvkContext(const Rc& device) : m_device (device), m_common (&device->m_objects), + m_sdmaAcquires(DxvkCmdBuffer::SdmaBarriers), m_sdmaBarriers(DxvkCmdBuffer::SdmaBuffer), + m_initAcquires(DxvkCmdBuffer::InitBarriers), m_initBarriers(DxvkCmdBuffer::InitBuffer), m_execBarriers(DxvkCmdBuffer::ExecBuffer), m_queryManager(m_common->queryPool()) { @@ -6737,7 +6739,9 @@ namespace dxvk { this->spillRenderPass(true); this->flushSharedImages(); + m_sdmaAcquires.finalize(m_cmd); m_sdmaBarriers.finalize(m_cmd); + m_initAcquires.finalize(m_cmd); m_initBarriers.finalize(m_cmd); m_execBarriers.finalize(m_cmd); @@ -6762,12 +6766,29 @@ namespace dxvk { if (m_imageLayoutTransitions.empty()) return; - VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; - depInfo.imageMemoryBarrierCount = m_imageLayoutTransitions.size(); - depInfo.pImageMemoryBarriers = m_imageLayoutTransitions.data(); + if (cmdBuffer == DxvkCmdBuffer::ExecBuffer) { + VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + depInfo.imageMemoryBarrierCount = m_imageLayoutTransitions.size(); + depInfo.pImageMemoryBarriers = m_imageLayoutTransitions.data(); - m_cmd->cmdPipelineBarrier(cmdBuffer, &depInfo); - m_cmd->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1u); + m_cmd->cmdPipelineBarrier(cmdBuffer, &depInfo); + m_cmd->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1u); + } else { + // If we're recording into an out-of-order command buffer, batch + // layout transitions into a dedicated command buffer in order to + // avoid pipeline stalls. + DxvkCmdBuffer barrierBuffer = cmdBuffer; + + if (cmdBuffer == DxvkCmdBuffer::InitBuffer) + barrierBuffer = DxvkCmdBuffer::InitBarriers; + if (cmdBuffer == DxvkCmdBuffer::SdmaBuffer) + barrierBuffer = DxvkCmdBuffer::SdmaBarriers; + + auto& batch = getBarrierBatch(barrierBuffer); + + for (const auto& barrier : m_imageLayoutTransitions) + batch.addImageBarrier(barrier); + } m_imageLayoutTransitions.clear(); } @@ -7143,12 +7164,14 @@ namespace dxvk { DxvkBarrierBatch& DxvkContext::getBarrierBatch( DxvkCmdBuffer cmdBuffer) { - if (cmdBuffer == DxvkCmdBuffer::ExecBuffer) - return m_execBarriers; - - return cmdBuffer == DxvkCmdBuffer::InitBuffer - ? m_initBarriers - : m_sdmaBarriers; + switch (cmdBuffer) { + default: + case DxvkCmdBuffer::ExecBuffer: return m_execBarriers; + case DxvkCmdBuffer::InitBuffer: return m_initBarriers; + case DxvkCmdBuffer::InitBarriers: return m_initAcquires; + case DxvkCmdBuffer::SdmaBuffer: return m_sdmaBarriers; + case DxvkCmdBuffer::SdmaBarriers: return m_sdmaAcquires; + } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index e8c8832b0..c70c6b4d7 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1398,7 +1398,9 @@ namespace dxvk { Rc m_descriptorPool; Rc m_descriptorManager; + DxvkBarrierBatch m_sdmaAcquires; DxvkBarrierBatch m_sdmaBarriers; + DxvkBarrierBatch m_initAcquires; DxvkBarrierBatch m_initBarriers; DxvkBarrierBatch m_execBarriers; DxvkBarrierTracker m_barrierTracker;