#include "mini/commandbuffer.hpp" #include "lsfg.hpp" using namespace Mini; CommandBuffer::CommandBuffer(VkDevice device, const CommandPool& pool) { // create command buffer const VkCommandBufferAllocateInfo desc{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .commandPool = pool.handle(), .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1 }; VkCommandBuffer commandBufferHandle{}; auto res = vkAllocateCommandBuffers(device, &desc, &commandBufferHandle); if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Unable to allocate command buffer"); // store command buffer in shared ptr this->state = std::make_shared(CommandBufferState::Empty); this->commandBuffer = std::shared_ptr( new VkCommandBuffer(commandBufferHandle), [dev = device, pool = pool.handle()](VkCommandBuffer* cmdBuffer) { vkFreeCommandBuffers(dev, pool, 1, cmdBuffer); } ); } void CommandBuffer::begin() { if (*this->state != CommandBufferState::Empty) throw std::logic_error("Command buffer is not in Empty state"); const VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; auto res = vkBeginCommandBuffer(*this->commandBuffer, &beginInfo); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to begin command buffer"); *this->state = CommandBufferState::Recording; } void CommandBuffer::end() { if (*this->state != CommandBufferState::Recording) throw std::logic_error("Command buffer is not in Recording state"); auto res = vkEndCommandBuffer(*this->commandBuffer); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to end command buffer"); *this->state = CommandBufferState::Full; } void CommandBuffer::submit(VkQueue queue, const std::vector& waitSemaphores, const std::vector& signalSemaphores) { if (*this->state != CommandBufferState::Full) throw std::logic_error("Command buffer is not in Full state"); const std::vector waitStages(waitSemaphores.size(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); std::vector waitSemaphoresHandles; waitSemaphoresHandles.reserve(waitSemaphores.size()); for (const auto& semaphore : waitSemaphores) waitSemaphoresHandles.push_back(semaphore.handle()); std::vector signalSemaphoresHandles; signalSemaphoresHandles.reserve(signalSemaphores.size()); for (const auto& semaphore : signalSemaphores) signalSemaphoresHandles.push_back(semaphore.handle()); const VkSubmitInfo submitInfo{ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .waitSemaphoreCount = static_cast(waitSemaphores.size()), .pWaitSemaphores = waitSemaphoresHandles.data(), .pWaitDstStageMask = waitStages.data(), .commandBufferCount = 1, .pCommandBuffers = &(*this->commandBuffer), .signalSemaphoreCount = static_cast(signalSemaphores.size()), .pSignalSemaphores = signalSemaphoresHandles.data() }; auto res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to submit command buffer"); *this->state = CommandBufferState::Submitted; }