CommandPool & CommandBuffer wrappers.
This commit is contained in:
@@ -184,7 +184,7 @@ void VulkanTutorial::shutdown() {
|
||||
|
||||
destroy_swapchain_objects();
|
||||
|
||||
m_context.destroy_command_pool(m_command_pool);
|
||||
m_command_pool.destroy();
|
||||
m_index_buffer.destroy();
|
||||
m_vertex_buffer.destroy();
|
||||
m_context.destroy_descriptor_set_layout(m_descriptor_set_layout);
|
||||
@@ -260,13 +260,16 @@ void VulkanTutorial::draw_frame() {
|
||||
VkPipelineStageFlags stages[] = {
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
};
|
||||
VkCommandBuffer command_buffers[] = {
|
||||
m_command_buffers[image_index],
|
||||
};
|
||||
VkSubmitInfo submit_info {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = wait_semaphores,
|
||||
.pWaitDstStageMask = stages,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &m_command_buffers[image_index],
|
||||
.pCommandBuffers = command_buffers,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = done_semaphores,
|
||||
};
|
||||
@@ -304,12 +307,6 @@ void VulkanTutorial::destroy_swapchain_objects() {
|
||||
if(m_command_pool == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
vkFreeCommandBuffers(
|
||||
m_context.device(),
|
||||
m_command_pool,
|
||||
uint32_t(m_command_buffers.size()),
|
||||
m_command_buffers.data()
|
||||
);
|
||||
m_command_buffers.clear();
|
||||
|
||||
for(auto& buffer: m_uniform_buffers)
|
||||
@@ -561,22 +558,13 @@ void VulkanTutorial::create_framebuffers() {
|
||||
}
|
||||
|
||||
void VulkanTutorial::create_command_pool() {
|
||||
if(m_command_pool != VK_NULL_HANDLE)
|
||||
if(!m_command_pool.is_null())
|
||||
return;
|
||||
|
||||
VkCommandPoolCreateInfo pool_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.queueFamilyIndex = m_context.queue_family(GRAPHIC_QUEUE),
|
||||
};
|
||||
|
||||
if(vkCreateCommandPool(
|
||||
m_context.device(),
|
||||
&pool_info,
|
||||
nullptr,
|
||||
&m_command_pool
|
||||
) != VK_SUCCESS)
|
||||
throw std::runtime_error("failed to create command pool");
|
||||
m_command_pool = vk::CommandPool(
|
||||
m_context,
|
||||
m_context.queue_family(GRAPHIC_QUEUE)
|
||||
);
|
||||
}
|
||||
|
||||
void VulkanTutorial::create_vertex_buffer() {
|
||||
@@ -704,23 +692,9 @@ void VulkanTutorial::create_descriptor_sets() {
|
||||
}
|
||||
|
||||
void VulkanTutorial::create_command_buffers() {
|
||||
m_command_buffers.resize(m_framebuffers.size());
|
||||
|
||||
VkCommandBufferAllocateInfo allocate_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = m_command_pool,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = uint32_t(m_command_buffers.size()),
|
||||
};
|
||||
|
||||
if(vkAllocateCommandBuffers(
|
||||
m_context.device(),
|
||||
&allocate_info,
|
||||
m_command_buffers.data()
|
||||
) != VK_SUCCESS)
|
||||
throw std::runtime_error("failed to allocate command buffers");
|
||||
|
||||
for(size_t index = 0; index < m_command_buffers.size(); index += 1) {
|
||||
m_command_buffers.clear();
|
||||
for(size_t index = 0; index < m_framebuffers.size(); index += 1) {
|
||||
m_command_buffers.emplace_back(m_context, m_command_pool);
|
||||
VkCommandBuffer command_buffer = m_command_buffers[index];
|
||||
|
||||
VkCommandBufferBeginInfo begin_info {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
#pragma once
|
||||
|
||||
#include <vk/Framebuffer.h>
|
||||
#include <vk/Semaphore.h>
|
||||
#include <vk/RenderPass.h>
|
||||
#include <vk/Pipeline.h>
|
||||
#include <vk/Buffer.h>
|
||||
#include <vk/Swapchain.h>
|
||||
#include <vk/Buffer.h>
|
||||
#include <vk/Pipeline.h>
|
||||
#include <vk/Framebuffer.h>
|
||||
#include <vk/RenderPass.h>
|
||||
#include <vk/Semaphore.h>
|
||||
#include <vk/CommandBuffer.h>
|
||||
#include <vk/CommandPool.h>
|
||||
#include <vk/Context.h>
|
||||
|
||||
#include <core/math.h>
|
||||
@@ -78,7 +80,7 @@ private:
|
||||
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
|
||||
vk::Pipeline m_pipeline;
|
||||
std::vector<vk::Framebuffer> m_framebuffers;
|
||||
VkCommandPool m_command_pool = VK_NULL_HANDLE;
|
||||
vk::CommandPool m_command_pool;
|
||||
vk::Buffer m_vertex_buffer;
|
||||
vk::Buffer m_index_buffer;
|
||||
std::vector<vk::Buffer> m_uniform_buffers;
|
||||
@@ -86,7 +88,7 @@ private:
|
||||
vk::MemoryBlock m_uniform_buffer_memory;
|
||||
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE;
|
||||
std::vector<VkDescriptorSet> m_descriptor_sets;
|
||||
std::vector<VkCommandBuffer> m_command_buffers;
|
||||
std::vector<vk::CommandBuffer> m_command_buffers;
|
||||
std::vector<vk::Semaphore> m_render_done;
|
||||
|
||||
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);
|
||||
|
||||
70
src/vk/CommandBuffer.cpp
Normal file
70
src/vk/CommandBuffer.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
|
||||
#include <vk/CommandBuffer.h>
|
||||
#include <vk/Context.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace vk {
|
||||
|
||||
|
||||
CommandBuffer::CommandBuffer() noexcept {
|
||||
}
|
||||
|
||||
CommandBuffer::CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level)
|
||||
: m_context(&context)
|
||||
, m_command_pool(command_pool)
|
||||
{
|
||||
assert(m_context);
|
||||
assert(m_command_pool != VK_NULL_HANDLE);
|
||||
|
||||
VkCommandBufferAllocateInfo allocate_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = m_command_pool,
|
||||
.level = level,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
if(vkAllocateCommandBuffers(
|
||||
context.device(),
|
||||
&allocate_info,
|
||||
&m_command_buffer
|
||||
) != VK_SUCCESS)
|
||||
throw std::runtime_error("failed to allocate command pool");
|
||||
}
|
||||
|
||||
CommandBuffer::CommandBuffer(CommandBuffer&& other) noexcept
|
||||
{
|
||||
swap(*this, other);
|
||||
}
|
||||
|
||||
CommandBuffer::~CommandBuffer() noexcept {
|
||||
if(!is_null())
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
CommandBuffer& CommandBuffer::operator=(CommandBuffer&& other) noexcept {
|
||||
swap(*this, other);
|
||||
if(other)
|
||||
other.destroy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void CommandBuffer::destroy() noexcept {
|
||||
assert(!is_null());
|
||||
assert(m_context);
|
||||
|
||||
vkFreeCommandBuffers(
|
||||
m_context->device(),
|
||||
m_command_pool,
|
||||
1,
|
||||
&m_command_buffer
|
||||
);
|
||||
|
||||
m_command_buffer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
71
src/vk/CommandBuffer.h
Normal file
71
src/vk/CommandBuffer.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
#pragma once
|
||||
|
||||
#include <vk/forward.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
||||
namespace vk {
|
||||
|
||||
|
||||
class CommandBuffer {
|
||||
public:
|
||||
CommandBuffer() noexcept;
|
||||
CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level=VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||
CommandBuffer(const CommandBuffer&) = delete;
|
||||
CommandBuffer(CommandBuffer&& other) noexcept;
|
||||
~CommandBuffer() noexcept;
|
||||
|
||||
CommandBuffer& operator=(const CommandBuffer&) = delete;
|
||||
CommandBuffer& operator=(CommandBuffer&& other) noexcept;
|
||||
|
||||
explicit inline operator bool() const noexcept {
|
||||
return !is_null();
|
||||
}
|
||||
|
||||
inline bool is_null() const noexcept {
|
||||
return m_command_buffer == VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
inline const Context* context() const noexcept {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline Context* context() noexcept {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline const VkCommandPool command_pool() const noexcept {
|
||||
return m_command_pool;
|
||||
}
|
||||
|
||||
inline VkCommandPool command_pool() noexcept {
|
||||
return m_command_pool;
|
||||
}
|
||||
|
||||
inline operator VkCommandBuffer() noexcept {
|
||||
return m_command_buffer;
|
||||
}
|
||||
|
||||
inline VkCommandBuffer command_buffer() noexcept {
|
||||
return m_command_buffer;
|
||||
}
|
||||
|
||||
friend inline void swap(CommandBuffer& command_buffer_0, CommandBuffer& command_buffer_1) noexcept {
|
||||
using std::swap;
|
||||
swap(command_buffer_0.m_context, command_buffer_1.m_context);
|
||||
swap(command_buffer_0.m_command_pool, command_buffer_1.m_command_pool);
|
||||
swap(command_buffer_0.m_command_buffer, command_buffer_1.m_command_buffer);
|
||||
}
|
||||
|
||||
void destroy() noexcept;
|
||||
|
||||
private:
|
||||
Context* m_context = nullptr;
|
||||
VkCommandPool m_command_pool = VK_NULL_HANDLE;
|
||||
VkCommandBuffer m_command_buffer = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
67
src/vk/CommandPool.cpp
Normal file
67
src/vk/CommandPool.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
|
||||
#include <vk/CommandPool.h>
|
||||
#include <vk/Context.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace vk {
|
||||
|
||||
|
||||
CommandPool::CommandPool() noexcept {
|
||||
}
|
||||
|
||||
CommandPool::CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags)
|
||||
: m_context(&context)
|
||||
{
|
||||
assert(m_context);
|
||||
|
||||
VkCommandPoolCreateInfo create_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = flags,
|
||||
.queueFamilyIndex = queue_family,
|
||||
};
|
||||
if(vkCreateCommandPool(
|
||||
context.device(),
|
||||
&create_info,
|
||||
nullptr,
|
||||
&m_command_pool
|
||||
) != VK_SUCCESS)
|
||||
throw std::runtime_error("failed to create command pool");
|
||||
}
|
||||
|
||||
CommandPool::CommandPool(CommandPool&& other) noexcept
|
||||
{
|
||||
swap(*this, other);
|
||||
}
|
||||
|
||||
CommandPool::~CommandPool() noexcept {
|
||||
if(!is_null())
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
CommandPool& CommandPool::operator=(CommandPool&& other) noexcept {
|
||||
swap(*this, other);
|
||||
if(other)
|
||||
other.destroy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void CommandPool::destroy() noexcept {
|
||||
assert(!is_null());
|
||||
assert(m_context);
|
||||
|
||||
vkDestroyCommandPool(
|
||||
m_context->device(),
|
||||
m_command_pool,
|
||||
nullptr
|
||||
);
|
||||
|
||||
m_command_pool = nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
61
src/vk/CommandPool.h
Normal file
61
src/vk/CommandPool.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
#pragma once
|
||||
|
||||
#include <vk/forward.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
||||
namespace vk {
|
||||
|
||||
|
||||
class CommandPool {
|
||||
public:
|
||||
CommandPool() noexcept;
|
||||
CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags=0);
|
||||
CommandPool(const CommandPool&) = delete;
|
||||
CommandPool(CommandPool&& other) noexcept;
|
||||
~CommandPool() noexcept;
|
||||
|
||||
CommandPool& operator=(const CommandPool&) = delete;
|
||||
CommandPool& operator=(CommandPool&& other) noexcept;
|
||||
|
||||
explicit inline operator bool() const noexcept {
|
||||
return !is_null();
|
||||
}
|
||||
|
||||
inline bool is_null() const noexcept {
|
||||
return m_command_pool == VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
inline const Context* context() const noexcept {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline Context* context() noexcept {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline operator VkCommandPool() noexcept {
|
||||
return m_command_pool;
|
||||
}
|
||||
|
||||
inline VkCommandPool command_pool() noexcept {
|
||||
return m_command_pool;
|
||||
}
|
||||
|
||||
friend inline void swap(CommandPool& command_pool_0, CommandPool& command_pool_1) noexcept {
|
||||
using std::swap;
|
||||
swap(command_pool_0.m_context, command_pool_1.m_context);
|
||||
swap(command_pool_0.m_command_pool, command_pool_1.m_command_pool);
|
||||
}
|
||||
|
||||
void destroy() noexcept;
|
||||
|
||||
private:
|
||||
Context* m_context = nullptr;
|
||||
VkCommandPool m_command_pool = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 Simon Boyé
|
||||
#include <vk/Context.h>
|
||||
#include <vk/Memory.h>
|
||||
#include <vk/CommandBuffer.h>
|
||||
|
||||
#include <core/utils.h>
|
||||
#include <core/Logger.h>
|
||||
@@ -141,7 +142,7 @@ void Context::shutdown() {
|
||||
m_allocator.reset();
|
||||
|
||||
m_transfer_fence.destroy();
|
||||
destroy_command_pool(m_transfer_command_pool);
|
||||
m_transfer_command_pool.destroy();
|
||||
|
||||
destroy_device(m_device);
|
||||
destroy_surface(m_surface);
|
||||
@@ -282,18 +283,7 @@ VkShaderModule Context::create_shader_module_from_file(const char* path) {
|
||||
}
|
||||
|
||||
void Context::copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family, VkDeviceSize size) {
|
||||
VkCommandBufferAllocateInfo alloc_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = m_transfer_command_pool,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
|
||||
VkCommandBuffer command_buffer;
|
||||
vkAllocateCommandBuffers(m_device, &alloc_info, &command_buffer);
|
||||
auto const command_buffer_guard = make_guard([this, command_buffer]() {
|
||||
vkFreeCommandBuffers(m_device, m_transfer_command_pool, 1, &command_buffer);
|
||||
});
|
||||
CommandBuffer command_buffer(*this, m_transfer_command_pool);
|
||||
|
||||
VkCommandBufferBeginInfo begin_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
@@ -332,10 +322,13 @@ void Context::copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family,
|
||||
|
||||
m_transfer_fence.reset();
|
||||
|
||||
VkCommandBuffer command_buffers[] = {
|
||||
command_buffer
|
||||
};
|
||||
VkSubmitInfo submit_info {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &command_buffer,
|
||||
.pCommandBuffers = command_buffers,
|
||||
};
|
||||
vkQueueSubmit(
|
||||
queue(m_transfer_queue_index),
|
||||
@@ -776,20 +769,11 @@ void Context::create_device(const ContextSettings& settings) {
|
||||
}
|
||||
|
||||
void Context::create_internal_objects() {
|
||||
VkCommandPoolCreateInfo pool_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.queueFamilyIndex = queue_family(m_transfer_queue_index),
|
||||
};
|
||||
if(vkCreateCommandPool(
|
||||
m_device,
|
||||
&pool_info,
|
||||
nullptr,
|
||||
&m_transfer_command_pool
|
||||
) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create command pool");
|
||||
}
|
||||
|
||||
m_transfer_command_pool = CommandPool(
|
||||
*this,
|
||||
queue_family(m_transfer_queue_index),
|
||||
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
|
||||
);
|
||||
m_transfer_fence = Fence(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vk/forward.h>
|
||||
#include <vk/CommandPool.h>
|
||||
#include <vk/Fence.h>
|
||||
|
||||
#include <core/utils.h>
|
||||
@@ -194,7 +195,7 @@ private:
|
||||
VkPresentModeKHR m_present_mode;
|
||||
|
||||
uint32_t m_transfer_queue_index = UINT32_MAX;
|
||||
VkCommandPool m_transfer_command_pool = VK_NULL_HANDLE;
|
||||
CommandPool m_transfer_command_pool;
|
||||
Fence m_transfer_fence;
|
||||
|
||||
std::vector<ContextDestructionCallback> m_context_destruction_callbacks;
|
||||
|
||||
Reference in New Issue
Block a user