/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* vk_cmd_buffer.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:26:06 by maldavid #+# #+# */ /* Updated: 2023/12/23 01:32:02 by kbz_8 ### ########.fr */ /* */ /* ************************************************************************** */ #include "vk_cmd_buffer.h" #include #include #include namespace mlx { void CmdBuffer::init(CmdManager* manager) { init(&manager->getCmdPool()); } void CmdBuffer::init(CmdPool* pool) { _pool = pool; VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = pool->get(); allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = 1; if(vkAllocateCommandBuffers(Render_Core::get().getDevice().get(), &allocInfo, &_cmd_buffer) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate command buffer"); #ifdef DEBUG core::error::report(e_kind::message, "Vulkan : created new command buffer"); #endif _fence.init(); _state = state::idle; } void CmdBuffer::beginRecord(VkCommandBufferUsageFlags usage) { if(!isInit()) core::error::report(e_kind::fatal_error, "Vulkan : begenning record on un uninit command buffer"); if(_state == state::recording) return; VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = usage; if(vkBeginCommandBuffer(_cmd_buffer, &beginInfo) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to begin recording command buffer"); _state = state::recording; } void CmdBuffer::endRecord() { if(!isInit()) core::error::report(e_kind::fatal_error, "Vulkan : ending record on un uninit command buffer"); if(_state != state::recording) return; if(vkEndCommandBuffer(_cmd_buffer) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to end recording command buffer"); _state = state::idle; } void CmdBuffer::submitIdle() noexcept { auto device = Render_Core::get().getDevice().get(); VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &_cmd_buffer; VkFenceCreateInfo fenceCreateInfo = {}; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; VkFence fence; vkCreateFence(device, &fenceCreateInfo, nullptr, &fence); vkResetFences(device, 1, &fence); vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, fence); _state = state::submitted; vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX); vkDestroyFence(device, fence, nullptr); _state = state::ready; } void CmdBuffer::submit(Semaphore* semaphores) noexcept { std::array signalSemaphores; std::array waitSemaphores; if(semaphores != nullptr) { signalSemaphores[0] = semaphores->getRenderImageSemaphore(); waitSemaphores[0] = semaphores->getImageSemaphore(); } VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = (semaphores == nullptr ? 0 : waitSemaphores.size()); submitInfo.pWaitSemaphores = waitSemaphores.data(); submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &_cmd_buffer; submitInfo.signalSemaphoreCount = (semaphores == nullptr ? 0 : signalSemaphores.size()); submitInfo.pSignalSemaphores = signalSemaphores.data(); if(vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get()) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer"); _state = state::submitted; } void CmdBuffer::destroy() noexcept { _fence.destroy(); _cmd_buffer = VK_NULL_HANDLE; _state = state::uninit; } }