mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
88 lines
3.5 KiB
C++
88 lines
3.5 KiB
C++
#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>(CommandBufferState::Empty);
|
|
this->commandBuffer = std::shared_ptr<VkCommandBuffer>(
|
|
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<Semaphore>& waitSemaphores,
|
|
const std::vector<Semaphore>& 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);
|
|
|
|
std::vector<VkSemaphore> waitSemaphoresHandles;
|
|
waitSemaphoresHandles.reserve(waitSemaphores.size());
|
|
for (const auto& semaphore : waitSemaphores)
|
|
waitSemaphoresHandles.push_back(semaphore.handle());
|
|
std::vector<VkSemaphore> 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<uint32_t>(waitSemaphores.size()),
|
|
.pWaitSemaphores = waitSemaphoresHandles.data(),
|
|
.pWaitDstStageMask = waitStages.data(),
|
|
.commandBufferCount = 1,
|
|
.pCommandBuffers = &(*this->commandBuffer),
|
|
.signalSemaphoreCount = static_cast<uint32_t>(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;
|
|
}
|