diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index a59b7707..42fd0a9c 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -176,7 +176,9 @@ namespace dxvk { VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore)) + if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_bindSemaphore) + || m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_postSemaphore) + || m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore)) throw DxvkError("DxvkCommandList: Failed to create semaphore"); VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; @@ -196,14 +198,15 @@ namespace dxvk { DxvkCommandList::~DxvkCommandList() { this->reset(); + m_vkd->vkDestroySemaphore(m_vkd->device(), m_bindSemaphore, nullptr); + m_vkd->vkDestroySemaphore(m_vkd->device(), m_postSemaphore, nullptr); m_vkd->vkDestroySemaphore(m_vkd->device(), m_sdmaSemaphore, nullptr); + m_vkd->vkDestroyFence(m_vkd->device(), m_fence, nullptr); } - VkResult DxvkCommandList::submit( - VkSemaphore semaphore, - uint64_t& semaphoreValue) { + VkResult DxvkCommandList::submit() { VkResult status = VK_SUCCESS; const auto& graphics = m_device->queues().graphics; @@ -222,44 +225,37 @@ namespace dxvk { ? &m_cmdSparseBinds[cmd.sparseCmd] : nullptr; - if (sparseBind) { - // Sparse bindig needs to serialize command execution, so wait - // for any prior submissions, then block any subsequent ones - sparseBind->waitSemaphore(semaphore, semaphoreValue); - sparseBind->signalSemaphore(semaphore, ++semaphoreValue); - - m_commandSubmission.waitSemaphore(semaphore, semaphoreValue, - VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); - } - if (isFirst) { // Wait for per-command list semaphores on first submission for (const auto& entry : m_waitSemaphores) { - if (sparseBind) { - sparseBind->waitSemaphore( - entry.fence->handle(), - entry.value); - } else { - m_commandSubmission.waitSemaphore( - entry.fence->handle(), - entry.value, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); - } + m_commandSubmission.waitSemaphore(entry.fence->handle(), + entry.value, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); } } - // Execute sparse bind if (sparseBind) { + // Sparse binding needs to serialize command execution, so wait + // for any prior submissions, then block any subsequent ones + m_commandSubmission.signalSemaphore(m_bindSemaphore, 0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); + + if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle))) + return status; + + sparseBind->waitSemaphore(m_bindSemaphore, 0); + sparseBind->signalSemaphore(m_postSemaphore, 0); + if ((status = sparseBind->submit(m_device, sparse.queueHandle))) return status; + + m_commandSubmission.waitSemaphore(m_postSemaphore, 0, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); } // Submit transfer commands as necessary if (cmd.usedFlags.test(DxvkCmdBuffer::SdmaBuffer)) m_commandSubmission.executeCommandBuffer(cmd.sdmaBuffer); - // If we had either a transfer command or a semaphore wait, - // submit to the transfer queue so that all subsequent commands - // get stalled appropriately. + // If we had either a transfer command or a semaphore wait, submit to the + // transfer queue so that all subsequent commands get stalled as necessary. if (m_device->hasDedicatedTransferQueue() && !m_commandSubmission.isEmpty()) { m_commandSubmission.signalSemaphore(m_sdmaSemaphore, 0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); @@ -283,15 +279,10 @@ namespace dxvk { if (cmd.usedFlags.test(DxvkCmdBuffer::ExecBuffer)) m_commandSubmission.executeCommandBuffer(cmd.execBuffer); - // Signal global timeline semaphore at the end of every submission - m_commandSubmission.signalSemaphore(semaphore, - ++semaphoreValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - if (isLast) { // Signal per-command list semaphores on the final submission for (const auto& entry : m_signalSemaphores) { - m_commandSubmission.signalSemaphore( - entry.fence->handle(), + m_commandSubmission.signalSemaphore(entry.fence->handle(), entry.value, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); } diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 9edd768a..988c9e4a 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -198,18 +198,9 @@ namespace dxvk { /** * \brief Submits command list - * - * \param [in] semaphore Global timeline semaphore - * \param [in,out] semaphoreValue Semaphore value. On input, - * this is the last signaled value of the semaphore so that - * synchronization can take place as needed. On ouput, this - * will contain the new value the semaphore gets signaled - * to by this submission. * \returns Submission status */ - VkResult submit( - VkSemaphore semaphore, - uint64_t& semaphoreValue); + VkResult submit(); /** * \brief Stat counters @@ -1029,6 +1020,8 @@ namespace dxvk { Rc m_graphicsPool; Rc m_transferPool; + VkSemaphore m_bindSemaphore = VK_NULL_HANDLE; + VkSemaphore m_postSemaphore = VK_NULL_HANDLE; VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE; VkFence m_fence = VK_NULL_HANDLE; diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp index 520a901e..1939817c 100644 --- a/src/dxvk/dxvk_queue.cpp +++ b/src/dxvk/dxvk_queue.cpp @@ -7,15 +7,7 @@ namespace dxvk { : m_device(device), m_submitThread([this] () { submitCmdLists(); }), m_finishThread([this] () { finishCmdLists(); }) { - auto vk = m_device->vkd(); - VkSemaphoreTypeCreateInfo typeInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; - typeInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; - - VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &typeInfo }; - - if (vk->vkCreateSemaphore(vk->device(), &info, nullptr, &m_semaphore)) - throw DxvkError("Failed to create global timeline semaphore"); } @@ -31,8 +23,6 @@ namespace dxvk { m_submitThread.join(); m_finishThread.join(); - - vk->vkDestroySemaphore(vk->device(), m_semaphore, nullptr); } @@ -116,7 +106,7 @@ namespace dxvk { std::lock_guard lock(m_mutexQueue); if (entry.submit.cmdList != nullptr) - status = entry.submit.cmdList->submit(m_semaphore, m_semaphoreValue); + status = entry.submit.cmdList->submit(); else if (entry.present.presenter != nullptr) status = entry.present.presenter->presentImage(); } else { diff --git a/src/dxvk/dxvk_queue.h b/src/dxvk/dxvk_queue.h index 8f589b55..ecde61a0 100644 --- a/src/dxvk/dxvk_queue.h +++ b/src/dxvk/dxvk_queue.h @@ -183,9 +183,6 @@ namespace dxvk { std::atomic m_pending = { 0u }; std::atomic m_gpuIdle = { 0ull }; - VkSemaphore m_semaphore = VK_NULL_HANDLE; - uint64_t m_semaphoreValue = 0ull; - dxvk::mutex m_mutex; dxvk::mutex m_mutexQueue;