From c3a721f562b590b8d301d9d7a2a4e989928f1eeb Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 22 Aug 2022 14:05:29 +0200 Subject: [PATCH] [dxvk] Introduce DxvkCommandPool --- src/dxvk/dxvk_cmdlist.cpp | 65 +++++++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_cmdlist.h | 46 ++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index cc5af6ca3..cd3a1be62 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -87,6 +87,71 @@ namespace dxvk { } + DxvkCommandPool::DxvkCommandPool( + DxvkDevice* device, + uint32_t queueFamily) + : m_device(device) { + auto vk = m_device->vkd(); + + VkCommandPoolCreateInfo poolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + poolInfo.queueFamilyIndex = queueFamily; + + if (vk->vkCreateCommandPool(vk->device(), &poolInfo, nullptr, &m_commandPool)) + throw DxvkError("DxvkCommandPool: Failed to create command pool"); + } + + + DxvkCommandPool::~DxvkCommandPool() { + auto vk = m_device->vkd(); + + vk->vkDestroyCommandPool(vk->device(), m_commandPool, nullptr); + } + + + VkCommandBuffer DxvkCommandPool::getCommandBuffer() { + auto vk = m_device->vkd(); + + if (m_next == m_commandBuffers.size()) { + // Allocate a new command buffer and add it to the list + VkCommandBufferAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + allocInfo.commandPool = m_commandPool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + + if (vk->vkAllocateCommandBuffers(vk->device(), &allocInfo, &commandBuffer)) + throw DxvkError("DxvkCommandPool: Failed to allocate command buffer"); + + m_commandBuffers.push_back(commandBuffer); + } + + // Take existing command buffer. All command buffers + // will be in reset state, so we can begin it safely. + VkCommandBuffer commandBuffer = m_commandBuffers[m_next++]; + + VkCommandBufferBeginInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + if (vk->vkBeginCommandBuffer(commandBuffer, &info)) + throw DxvkError("DxvkCommandPool: Failed to begin command buffer"); + + return commandBuffer; + } + + + void DxvkCommandPool::reset() { + auto vk = m_device->vkd(); + + if (m_next) { + if (vk->vkResetCommandPool(vk->device(), m_commandPool, 0)) + throw DxvkError("DxvkCommandPool: Failed to reset command pool"); + + m_next = 0; + } + } + + DxvkCommandList::DxvkCommandList(DxvkDevice* device) : m_device (device), m_vkd (device->vkd()), diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 25bd59127..9d1487474 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -118,7 +118,51 @@ namespace dxvk { /** - * \brief DXVK command list + * \brief Command pool + * + * Simple command pool abstraction that allows + * us to easily obtain command buffers. + */ + class DxvkCommandPool : public RcObject { + + public: + + /** + * \brief Creates command pool + * + * \param [in] device DXVK device + * \param [in] queueFamily Target queue family + */ + DxvkCommandPool( + DxvkDevice* device, + uint32_t queueFamily); + + ~DxvkCommandPool(); + + /** + * \brief Retrieves or allocates a command buffer + * \returns New command buffer in begun state + */ + VkCommandBuffer getCommandBuffer(); + + /** + * \brief Resets command pool and all command buffers + */ + void reset(); + + private: + + DxvkDevice* m_device; + + VkCommandPool m_commandPool = VK_NULL_HANDLE; + std::vector m_commandBuffers; + size_t m_next = 0; + + }; + + + /** + * \brief Command list * * Stores a command buffer that a context can use to record Vulkan * commands. The command list shall also reference the resources