From 4f3dcf2bc859d2a507fe2ef9d647671ca29fc9ad Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 28 Jun 2019 01:36:12 +0200 Subject: [PATCH] [dxvk] Add SDMA command buffer This new command buffer will be submitted to the transfer queue, if available, otherwise it will be the first buffer submitted to the graphics queue. --- src/dxvk/dxvk_cmdlist.cpp | 62 ++++++++++++++++++++++++++++++++------- src/dxvk/dxvk_cmdlist.h | 9 +++++- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 46faf996..131fd1e5 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -35,21 +35,41 @@ namespace dxvk { throw DxvkError("DxvkCommandList: Failed to create transfer command pool"); } - VkCommandBufferAllocateInfo cmdInfo; - cmdInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmdInfo.pNext = nullptr; - cmdInfo.commandPool = m_graphicsPool; - cmdInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmdInfo.commandBufferCount = 1; + VkCommandBufferAllocateInfo cmdInfoGfx; + cmdInfoGfx.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmdInfoGfx.pNext = nullptr; + cmdInfoGfx.commandPool = m_graphicsPool; + cmdInfoGfx.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdInfoGfx.commandBufferCount = 1; - if (m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfo, &m_execBuffer) != VK_SUCCESS - || m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfo, &m_initBuffer) != VK_SUCCESS) + VkCommandBufferAllocateInfo cmdInfoDma; + cmdInfoDma.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmdInfoDma.pNext = nullptr; + cmdInfoDma.commandPool = m_transferPool ? m_transferPool : m_graphicsPool; + cmdInfoDma.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdInfoDma.commandBufferCount = 1; + + if (m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoGfx, &m_execBuffer) != VK_SUCCESS + || m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoGfx, &m_initBuffer) != VK_SUCCESS + || m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoDma, &m_sdmaBuffer) != VK_SUCCESS) throw DxvkError("DxvkCommandList: Failed to allocate command buffer"); + + if (m_device->hasDedicatedTransferQueue()) { + VkSemaphoreCreateInfo semInfo; + semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semInfo.pNext = nullptr; + semInfo.flags = 0; + + if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semInfo, nullptr, &m_sdmaSemaphore) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to create semaphore"); + } } DxvkCommandList::~DxvkCommandList() { this->reset(); + + m_vkd->vkDestroySemaphore(m_vkd->device(), m_sdmaSemaphore, nullptr); m_vkd->vkDestroyCommandPool(m_vkd->device(), m_graphicsPool, nullptr); m_vkd->vkDestroyCommandPool(m_vkd->device(), m_transferPool, nullptr); @@ -62,8 +82,26 @@ namespace dxvk { VkSemaphore waitSemaphore, VkSemaphore wakeSemaphore) { const auto& graphics = m_device->queues().graphics; + const auto& transfer = m_device->queues().transfer; - DxvkQueueSubmission info = { }; + DxvkQueueSubmission info = DxvkQueueSubmission(); + + if (m_cmdBuffersUsed.test(DxvkCmdBuffer::SdmaBuffer)) { + info.cmdBuffers[info.cmdBufferCount++] = m_sdmaBuffer; + + if (m_device->hasDedicatedTransferQueue()) { + info.wakeSync[info.wakeCount++] = m_sdmaSemaphore; + VkResult status = submitToQueue(transfer.queueHandle, VK_NULL_HANDLE, info); + + if (status != VK_SUCCESS) + return status; + + info = DxvkQueueSubmission(); + info.waitSync[info.waitCount] = m_sdmaSemaphore; + info.waitMask[info.waitCount] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + info.waitCount += 1; + } + } if (m_cmdBuffersUsed.test(DxvkCmdBuffer::InitBuffer)) info.cmdBuffers[info.cmdBufferCount++] = m_initBuffer; @@ -108,7 +146,8 @@ namespace dxvk { Logger::err("DxvkCommandList: Failed to reset command buffer"); if (m_vkd->vkBeginCommandBuffer(m_execBuffer, &info) != VK_SUCCESS - || m_vkd->vkBeginCommandBuffer(m_initBuffer, &info) != VK_SUCCESS) + || m_vkd->vkBeginCommandBuffer(m_initBuffer, &info) != VK_SUCCESS + || m_vkd->vkBeginCommandBuffer(m_sdmaBuffer, &info) != VK_SUCCESS) Logger::err("DxvkCommandList: Failed to begin command buffer"); if (m_vkd->vkResetFences(m_vkd->device(), 1, &m_fence) != VK_SUCCESS) @@ -122,7 +161,8 @@ namespace dxvk { void DxvkCommandList::endRecording() { if (m_vkd->vkEndCommandBuffer(m_execBuffer) != VK_SUCCESS - || m_vkd->vkEndCommandBuffer(m_initBuffer) != VK_SUCCESS) + || m_vkd->vkEndCommandBuffer(m_initBuffer) != VK_SUCCESS + || m_vkd->vkEndCommandBuffer(m_sdmaBuffer) != VK_SUCCESS) Logger::err("DxvkCommandList::endRecording: Failed to record command buffer"); } diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index e93717ad..4403d1ac 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -25,6 +25,7 @@ namespace dxvk { enum class DxvkCmdBuffer : uint32_t { InitBuffer = 0, ExecBuffer = 1, + SdmaBuffer = 2, }; using DxvkCmdBufferFlags = Flags; @@ -748,6 +749,9 @@ namespace dxvk { VkCommandBuffer m_execBuffer = VK_NULL_HANDLE; VkCommandBuffer m_initBuffer = VK_NULL_HANDLE; + VkCommandBuffer m_sdmaBuffer = VK_NULL_HANDLE; + + VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE; DxvkCmdBufferFlags m_cmdBuffersUsed; DxvkLifetimeTracker m_resources; @@ -759,7 +763,10 @@ namespace dxvk { DxvkStatCounters m_statCounters; VkCommandBuffer getCmdBuffer(DxvkCmdBuffer cmdBuffer) const { - return cmdBuffer == DxvkCmdBuffer::ExecBuffer ? m_execBuffer : m_initBuffer; + if (cmdBuffer == DxvkCmdBuffer::ExecBuffer) return m_execBuffer; + if (cmdBuffer == DxvkCmdBuffer::InitBuffer) return m_initBuffer; + if (cmdBuffer == DxvkCmdBuffer::SdmaBuffer) return m_sdmaBuffer; + return VK_NULL_HANDLE; } VkResult submitToQueue(