Created a command buffer and command pool object for managing and tracking as well as wrapping vulkan functions to reduce boilerplate
This commit is contained in:
158
src/vulkan/basalt_command_buffer.cpp
Normal file
158
src/vulkan/basalt_command_buffer.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "vulkan/basalt_command_buffer.h"
|
||||
|
||||
basalt::CommandPool::CommandPool(CommandPool&& other) noexcept
|
||||
{
|
||||
BTRACE("Moved command pool %p to %p\n", &other, this);
|
||||
this->device = other.device;
|
||||
this->vk = other.vk;
|
||||
this->num_active_buffers = other.num_active_buffers;
|
||||
this->index = other.index;
|
||||
other.device = nullptr;
|
||||
other.vk = VK_NULL_HANDLE;
|
||||
other.num_active_buffers = 0;
|
||||
other.should_free = false;
|
||||
}
|
||||
|
||||
basalt::CommandPool& basalt::CommandPool::operator=(CommandPool&& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
BTRACE("Moved command pool %p to %p\n", &other, this);
|
||||
if (should_free && vk != VK_NULL_HANDLE)
|
||||
this->~CommandPool();
|
||||
this->device = other.device;
|
||||
this->vk = other.vk;
|
||||
this->num_active_buffers = other.num_active_buffers;
|
||||
this->index = other.index;
|
||||
other.device = nullptr;
|
||||
other.vk = VK_NULL_HANDLE;
|
||||
other.num_active_buffers = 0;
|
||||
other.should_free = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::CommandPool::CommandPool(basalt::Device& device, u32 index) :
|
||||
device(&device), index(index)
|
||||
{
|
||||
this->should_free = true;
|
||||
this->num_active_buffers = 0;
|
||||
VkCommandPoolCreateInfo ci = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
|
||||
ci.pNext = VK_NULL_HANDLE;
|
||||
ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
ci.queueFamilyIndex = index;
|
||||
VkResult err = VK_SUCCESS;
|
||||
VK_ASSERT(vkCreateCommandPool(device, &ci, device.ctx->vk_alloc, &vk), "Failed to create command pool\n\tAt %s:%d\n\tError %s\n\tFor queue index %u\n", index);
|
||||
BTRACE("Created command pool %p for device %p (%p)\n", this, &device, device.logical);
|
||||
}
|
||||
|
||||
basalt::CommandPool::~CommandPool()
|
||||
{
|
||||
if (should_free)
|
||||
{
|
||||
vkDeviceWaitIdle(device->logical);
|
||||
BASSERT_WARN(num_active_buffers == 0, "Assertion %s failed at %s:%d\n\t%u command buffer(s) of command pool %p were not freed\n", num_active_buffers, this);
|
||||
BTRACE("Destroyed command pool %p for device %p (%p)\n", this, device, device->logical);
|
||||
vkDestroyCommandPool(device->logical, vk, device->ctx->vk_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
basalt::CommandBuffer basalt::CommandPool::get_buffer(VkCommandBufferLevel level)
|
||||
{
|
||||
VkCommandBufferAllocateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
info.commandPool = this->vk;
|
||||
info.level = level;
|
||||
info.commandBufferCount = 1;
|
||||
|
||||
VkCommandBuffer buffer = VK_NULL_HANDLE;
|
||||
VkResult err = VK_SUCCESS;
|
||||
VK_ASSERT(vkAllocateCommandBuffers(device->logical, &info, &buffer), "Failed to allocate command buffer from pool\n\tAt %s:%d\n\tError %s\n\tFor command pool %p\n", this);
|
||||
return basalt::CommandBuffer(buffer, this);
|
||||
}
|
||||
|
||||
basalt::CommandBuffer::CommandBuffer(CommandBuffer&& other) noexcept
|
||||
{
|
||||
BTRACE("Moved command buffer %p to %p\n", &other, this);
|
||||
this->pool = other.pool;
|
||||
this->vk = other.vk;
|
||||
this->should_free = other.should_free;
|
||||
other.pool = nullptr;
|
||||
other.vk = VK_NULL_HANDLE;
|
||||
other.should_free = false;
|
||||
}
|
||||
|
||||
basalt::CommandBuffer& basalt::CommandBuffer::operator=(CommandBuffer&& other) noexcept
|
||||
{
|
||||
if (&other == this)
|
||||
return *this;
|
||||
// If statement is technically redundant - left in for sanity/clarity
|
||||
if (this->pool != nullptr)
|
||||
this->~CommandBuffer();
|
||||
BTRACE("Moved command buffer %p to %p\n", &other, this);
|
||||
this->pool = other.pool;
|
||||
this->vk = other.vk;
|
||||
this->should_free = other.should_free;
|
||||
other.pool = nullptr;
|
||||
other.vk = VK_NULL_HANDLE;
|
||||
other.should_free = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::CommandBuffer::CommandBuffer(VkCommandBuffer buffer, CommandPool* pool) :
|
||||
vk(buffer), pool(pool)
|
||||
{
|
||||
BTRACE("Created command buffer %p from pool %p\n", this, pool);
|
||||
if (pool != nullptr)
|
||||
pool->num_active_buffers++;
|
||||
}
|
||||
|
||||
basalt::CommandBuffer::~CommandBuffer()
|
||||
{
|
||||
if (pool != nullptr && should_free)
|
||||
{
|
||||
BTRACE("Freed command buffer %p from pool %p\n", this, pool);
|
||||
vkDeviceWaitIdle(pool->device->logical);
|
||||
vkFreeCommandBuffers(pool->device->logical, pool->vk, 1, &vk);
|
||||
if ((pool->num_active_buffers - 1) < pool->num_active_buffers)
|
||||
pool->num_active_buffers--;
|
||||
}
|
||||
}
|
||||
|
||||
void basalt::CommandBuffer::start(basalt::RenderPass& render_pass, VkFramebuffer framebuffer, VkRect2D render_area)
|
||||
{
|
||||
VkResult err = VK_SUCCESS;
|
||||
VkCommandBufferBeginInfo beg = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
beg.flags = 0;
|
||||
beg.pNext = VK_NULL_HANDLE;
|
||||
beg.pInheritanceInfo = VK_NULL_HANDLE;
|
||||
VK_ASSERT(vkBeginCommandBuffer(vk, &beg), "Failed to begin command buffer\n\tAt %s:%d\n\tError %s\n\tFor command buffer %p\n", this);
|
||||
|
||||
VkRenderPassBeginInfo render = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
render.pNext = VK_NULL_HANDLE;
|
||||
render.renderPass = render_pass.render_pass;
|
||||
render.framebuffer = framebuffer;
|
||||
render.renderArea = render_area;
|
||||
VkClearValue clear_colour = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||
render.clearValueCount = 1;
|
||||
render.pClearValues = &clear_colour;
|
||||
vkCmdBeginRenderPass(vk, &render, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
void basalt::CommandBuffer::stop(void)
|
||||
{
|
||||
vkCmdEndRenderPass(vk);
|
||||
VkResult err = VK_SUCCESS;
|
||||
VK_ASSERT(vkEndCommandBuffer(vk), "Failed to end command buffer recording\n\tAt %s:%d\n\tError %s\n\tFor command buffer %p\n", this);
|
||||
}
|
||||
|
||||
void basalt::CommandBuffer::reset(void)
|
||||
{ vkResetCommandBuffer(vk, 0); }
|
||||
|
||||
void basalt::CommandBuffer::bind_pipeline(basalt::Pipeline& pipeline, VkPipelineBindPoint bind)
|
||||
{ vkCmdBindPipeline(vk, bind, pipeline.vk); }
|
||||
|
||||
void basalt::CommandBuffer::set_viewport(VkViewport port)
|
||||
{ vkCmdSetViewport(vk, 0, 1, &port); }
|
||||
|
||||
void basalt::CommandBuffer::set_scissor(VkRect2D scissor)
|
||||
{ vkCmdSetScissor(vk, 0, 1, &scissor); }
|
||||
Reference in New Issue
Block a user