Files
funnygame/materialsystem/vulkan/commandbuffer.cpp
T
2026-08-26 21:07:12 +03:00

179 lines
4.5 KiB
C++

#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<CVkCommand*> 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<VkCommandBuffer> &GetVulkanCommands() override;
virtual void FreeCommandBufferWithCommands(IVkCommandBuffer* pCommandBuffer) override;
virtual void RenderingFinished() override;
private:
VkDevice m_hDevice;
CUtlVector<VkCommandBuffer> 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<VkCommandBuffer> &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;
}