#include "materialsystem/imaterialsystem.h" #include "tier0/platform.h" #include "tier1/interface.h" #include "tier1/utlvector.h" #include "vulkan_state.h" class CVkCommandBuffer: public IVkCommandBuffer { public: virtual void SetVulkanHandlers( VkDevice hDevice, IVkCommandBufferManager *pManager ) override; virtual void AddCommand( CVkCommand *pCommand ) override; virtual void Reset() override; virtual void Submit() override; virtual void Render() override; void FreeWithCommands(); private: CUtlVector m_commands; VkCommandBuffer m_hBuffer = NULL; VkDevice m_hDevice; IVkCommandBufferManager *m_pMgr; VkCommandPool m_hPool = NULL; }; void CVkCommandBuffer::FreeWithCommands() { if (m_hPool) { for ( auto &c: m_commands) { delete c; }; vkFreeCommandBuffers(m_hDevice, m_hPool, 1, &m_hBuffer); vkDestroyCommandPool(m_hDevice, m_hPool, NULL); m_hPool = NULL; } } void CVkCommandBuffer::SetVulkanHandlers( VkDevice hDevice, IVkCommandBufferManager *pManager ) { m_hDevice = hDevice; m_pMgr = pManager; } void CVkCommandBuffer::Reset() { VkCommandBufferAllocateInfo commandBufferAllocInfo = {}; VkCommandPoolCreateInfo stCreateInfo = {}; FreeWithCommands(); stCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; stCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; vkCreateCommandPool(m_hDevice, &stCreateInfo, NULL, &m_hPool); m_hBuffer = {}; commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; commandBufferAllocInfo.commandPool = m_hPool; commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; commandBufferAllocInfo.commandBufferCount = 1; vkAllocateCommandBuffers(m_hDevice, &commandBufferAllocInfo, &m_hBuffer); m_commands = {}; } void CVkCommandBuffer::AddCommand( CVkCommand *pCommand ) { m_commands.AppendTail(pCommand); } void CVkCommandBuffer::Submit() { m_pMgr->GetVulkanCommands().AppendTail(m_hBuffer); }; void CVkCommandBuffer::Render() { VkCommandBufferBeginInfo stCommandBufferBeginInfo = {}; stCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; vkBeginCommandBuffer(m_hBuffer, &stCommandBufferBeginInfo); for (auto &pCommand: m_commands) { pCommand->Execute(m_hDevice, m_hBuffer, 0); }; vkEndCommandBuffer(m_hBuffer); } class CVkCommandBufferManager: public IVkCommandBufferManager { public: virtual void Init() override; virtual void Shutdown() override; virtual void SetVulkanHandlers( VkInstance hInstance, VkDevice hDevice ) override; virtual IVkCommandBuffer *CreateCommandBuffer() override; virtual CVkCommand *CreateCommand( const char *szName ) override; virtual CUtlVector &GetVulkanCommands() override; virtual void FreeCommandBufferWithCommands(IVkCommandBuffer* pCommandBuffer) override; virtual void RenderingFinished() override; private: VkDevice m_hDevice; CUtlVector m_commands = {}; }; EXPOSE_INTERFACE(CVkCommandBufferManager, IVkCommandBufferManager, VULKAN_COMMAND_BUFFER_MANAGER_INTERFACE_NAME); void CVkCommandBufferManager::Init() { } void CVkCommandBufferManager::Shutdown() { } void CVkCommandBufferManager::SetVulkanHandlers( VkInstance hInstance, VkDevice hDevice ) { m_hDevice = hDevice; } IVkCommandBuffer *CVkCommandBufferManager::CreateCommandBuffer() { IVkCommandBuffer *pBuffer = new CVkCommandBuffer; pBuffer->SetVulkanHandlers(m_hDevice, this); return pBuffer; } struct VulkanCommandRegistry_t { const char *m_szName; fnCreateVulkanCommand_t m_pfnCreate; struct VulkanCommandRegistry_t *m_pNext; } *s_pVulkanCommands = NULL; CVkCommand *CVkCommandBufferManager::CreateCommand( const char *szName ) { VulkanCommandRegistry_t *pCommand; for ( pCommand = s_pVulkanCommands; pCommand; pCommand = pCommand->m_pNext ) { if (!V_strcmp(pCommand->m_szName, szName)) return pCommand->m_pfnCreate(); } Plat_FatalErrorFunc("Command %s not found\n", szName); return NULL; } CUtlVector &CVkCommandBufferManager::GetVulkanCommands() { return m_commands; } void CVkCommandBufferManager::FreeCommandBufferWithCommands(IVkCommandBuffer* pCommandBuffer) { CVkCommandBuffer *pVkBuffer = (CVkCommandBuffer*)pCommandBuffer; pVkBuffer->FreeWithCommands(); delete pVkBuffer; }; void CVkCommandBufferManager::RenderingFinished() { m_commands = {}; } CVkCommandRegistry::CVkCommandRegistry( const char *szName, fnCreateVulkanCommand_t pfnCreate ) { VulkanCommandRegistry_t *pCommand = new VulkanCommandRegistry_t; pCommand->m_szName = szName; pCommand->m_pfnCreate = pfnCreate; pCommand->m_pNext = s_pVulkanCommands; s_pVulkanCommands = pCommand; }