lsfg-vk/src/mini/commandbuffer.cpp

82 lines
3.2 KiB
C++

#include "mini/commandbuffer.hpp"
#include "layer.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 = Layer::ovkAllocateCommandBuffers(device, &desc, &commandBufferHandle);
if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE)
throw LSFG::vulkan_error(res, "Unable to allocate command buffer");
res = Layer::ovkSetDeviceLoaderData(device, commandBufferHandle);
// store command buffer in shared ptr
this->state = std::make_shared<CommandBufferState>(CommandBufferState::Empty);
this->commandBuffer = std::shared_ptr<VkCommandBuffer>(
new VkCommandBuffer(commandBufferHandle),
[dev = device, pool = pool.handle()](VkCommandBuffer* cmdBuffer) {
Layer::ovkFreeCommandBuffers(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 = Layer::ovkBeginCommandBuffer(*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 = Layer::ovkEndCommandBuffer(*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<VkSemaphore>& waitSemaphores,
const std::vector<VkSemaphore>& signalSemaphores) {
if (*this->state != CommandBufferState::Full)
throw std::logic_error("Command buffer is not in Full state");
const std::vector<VkPipelineStageFlags> waitStages(waitSemaphores.size(),
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
const VkSubmitInfo submitInfo{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size()),
.pWaitSemaphores = waitSemaphores.data(),
.pWaitDstStageMask = waitStages.data(),
.commandBufferCount = 1,
.pCommandBuffers = &(*this->commandBuffer),
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
.pSignalSemaphores = signalSemaphores.data()
};
auto res = Layer::ovkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
if (res != VK_SUCCESS)
throw LSFG::vulkan_error(res, "Unable to submit command buffer");
*this->state = CommandBufferState::Submitted;
}