Browse Source

CommandPool & CommandBuffer wrappers.

master
Draklaw 4 years ago
parent
commit
b18f3719ed
  1. 4
      CMakeLists.txt
  2. 52
      src/VulkanTutorial.cpp
  3. 14
      src/VulkanTutorial.h
  4. 70
      src/vk/CommandBuffer.cpp
  5. 71
      src/vk/CommandBuffer.h
  6. 67
      src/vk/CommandPool.cpp
  7. 61
      src/vk/CommandPool.h
  8. 40
      src/vk/Context.cpp
  9. 3
      src/vk/Context.h

4
CMakeLists.txt

@ -37,14 +37,16 @@ add_executable(vk_expe
src/core/Logger.cpp src/core/Logger.cpp
src/vk/Context.cpp src/vk/Context.cpp
src/vk/CommandPool.cpp
src/vk/CommandBuffer.cpp
src/vk/Fence.cpp src/vk/Fence.cpp
src/vk/Semaphore.cpp src/vk/Semaphore.cpp
src/vk/Framebuffer.cpp src/vk/Framebuffer.cpp
src/vk/ShaderModule.cpp src/vk/ShaderModule.cpp
src/vk/Pipeline.cpp src/vk/Pipeline.cpp
src/vk/Swapchain.cpp
src/vk/Memory.cpp src/vk/Memory.cpp
src/vk/Buffer.cpp src/vk/Buffer.cpp
src/vk/Swapchain.cpp
src/vk/RenderPass.cpp src/vk/RenderPass.cpp
src/main.cpp src/main.cpp

52
src/VulkanTutorial.cpp

@ -184,7 +184,7 @@ void VulkanTutorial::shutdown() {
destroy_swapchain_objects(); destroy_swapchain_objects();
m_context.destroy_command_pool(m_command_pool); m_command_pool.destroy();
m_index_buffer.destroy(); m_index_buffer.destroy();
m_vertex_buffer.destroy(); m_vertex_buffer.destroy();
m_context.destroy_descriptor_set_layout(m_descriptor_set_layout); m_context.destroy_descriptor_set_layout(m_descriptor_set_layout);
@ -260,13 +260,16 @@ void VulkanTutorial::draw_frame() {
VkPipelineStageFlags stages[] = { VkPipelineStageFlags stages[] = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
}; };
VkCommandBuffer command_buffers[] = {
m_command_buffers[image_index],
};
VkSubmitInfo submit_info { VkSubmitInfo submit_info {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1, .waitSemaphoreCount = 1,
.pWaitSemaphores = wait_semaphores, .pWaitSemaphores = wait_semaphores,
.pWaitDstStageMask = stages, .pWaitDstStageMask = stages,
.commandBufferCount = 1, .commandBufferCount = 1,
.pCommandBuffers = &m_command_buffers[image_index], .pCommandBuffers = command_buffers,
.signalSemaphoreCount = 1, .signalSemaphoreCount = 1,
.pSignalSemaphores = done_semaphores, .pSignalSemaphores = done_semaphores,
}; };
@ -304,12 +307,6 @@ void VulkanTutorial::destroy_swapchain_objects() {
if(m_command_pool == VK_NULL_HANDLE) if(m_command_pool == VK_NULL_HANDLE)
return; return;
vkFreeCommandBuffers(
m_context.device(),
m_command_pool,
uint32_t(m_command_buffers.size()),
m_command_buffers.data()
);
m_command_buffers.clear(); m_command_buffers.clear();
for(auto& buffer: m_uniform_buffers) for(auto& buffer: m_uniform_buffers)
@ -561,22 +558,13 @@ void VulkanTutorial::create_framebuffers() {
} }
void VulkanTutorial::create_command_pool() { void VulkanTutorial::create_command_pool() {
if(m_command_pool != VK_NULL_HANDLE) if(!m_command_pool.is_null())
return; return;
VkCommandPoolCreateInfo pool_info { m_command_pool = vk::CommandPool(
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, m_context,
.flags = 0, m_context.queue_family(GRAPHIC_QUEUE)
.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");
} }
void VulkanTutorial::create_vertex_buffer() { void VulkanTutorial::create_vertex_buffer() {
@ -704,23 +692,9 @@ void VulkanTutorial::create_descriptor_sets() {
} }
void VulkanTutorial::create_command_buffers() { void VulkanTutorial::create_command_buffers() {
m_command_buffers.resize(m_framebuffers.size()); m_command_buffers.clear();
for(size_t index = 0; index < m_framebuffers.size(); index += 1) {
VkCommandBufferAllocateInfo allocate_info { m_command_buffers.emplace_back(m_context, m_command_pool);
.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) {
VkCommandBuffer command_buffer = m_command_buffers[index]; VkCommandBuffer command_buffer = m_command_buffers[index];
VkCommandBufferBeginInfo begin_info { VkCommandBufferBeginInfo begin_info {

14
src/VulkanTutorial.h

@ -1,12 +1,14 @@
// Copyright 2022 Simon Boyé // Copyright 2022 Simon Boyé
#pragma once #pragma once
#include <vk/Swapchain.h>
#include <vk/Buffer.h>
#include <vk/Pipeline.h>
#include <vk/Framebuffer.h> #include <vk/Framebuffer.h>
#include <vk/Semaphore.h>
#include <vk/RenderPass.h> #include <vk/RenderPass.h>
#include <vk/Pipeline.h> #include <vk/Semaphore.h>
#include <vk/Buffer.h> #include <vk/CommandBuffer.h>
#include <vk/Swapchain.h> #include <vk/CommandPool.h>
#include <vk/Context.h> #include <vk/Context.h>
#include <core/math.h> #include <core/math.h>
@ -78,7 +80,7 @@ private:
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE; VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
vk::Pipeline m_pipeline; vk::Pipeline m_pipeline;
std::vector<vk::Framebuffer> m_framebuffers; 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_vertex_buffer;
vk::Buffer m_index_buffer; vk::Buffer m_index_buffer;
std::vector<vk::Buffer> m_uniform_buffers; std::vector<vk::Buffer> m_uniform_buffers;
@ -86,7 +88,7 @@ private:
vk::MemoryBlock m_uniform_buffer_memory; vk::MemoryBlock m_uniform_buffer_memory;
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE; VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE;
std::vector<VkDescriptorSet> m_descriptor_sets; 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; std::vector<vk::Semaphore> m_render_done;
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f); Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);

70
src/vk/CommandBuffer.cpp

@ -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

@ -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

@ -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

@ -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;
};
}

40
src/vk/Context.cpp

@ -1,6 +1,7 @@
// Copyright 2022 Simon Boyé // Copyright 2022 Simon Boyé
#include <vk/Context.h> #include <vk/Context.h>
#include <vk/Memory.h> #include <vk/Memory.h>
#include <vk/CommandBuffer.h>
#include <core/utils.h> #include <core/utils.h>
#include <core/Logger.h> #include <core/Logger.h>
@ -141,7 +142,7 @@ void Context::shutdown() {
m_allocator.reset(); m_allocator.reset();
m_transfer_fence.destroy(); m_transfer_fence.destroy();
destroy_command_pool(m_transfer_command_pool); m_transfer_command_pool.destroy();
destroy_device(m_device); destroy_device(m_device);
destroy_surface(m_surface); 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) { void Context::copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family, VkDeviceSize size) {
VkCommandBufferAllocateInfo alloc_info { CommandBuffer command_buffer(*this, m_transfer_command_pool);
.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);
});
VkCommandBufferBeginInfo begin_info { VkCommandBufferBeginInfo begin_info {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_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(); m_transfer_fence.reset();
VkCommandBuffer command_buffers[] = {
command_buffer
};
VkSubmitInfo submit_info { VkSubmitInfo submit_info {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1, .commandBufferCount = 1,
.pCommandBuffers = &command_buffer, .pCommandBuffers = command_buffers,
}; };
vkQueueSubmit( vkQueueSubmit(
queue(m_transfer_queue_index), queue(m_transfer_queue_index),
@ -776,20 +769,11 @@ void Context::create_device(const ContextSettings& settings) {
} }
void Context::create_internal_objects() { void Context::create_internal_objects() {
VkCommandPoolCreateInfo pool_info { m_transfer_command_pool = CommandPool(
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, *this,
.flags = 0, queue_family(m_transfer_queue_index),
.queueFamilyIndex = queue_family(m_transfer_queue_index), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
}; );
if(vkCreateCommandPool(
m_device,
&pool_info,
nullptr,
&m_transfer_command_pool
) != VK_SUCCESS) {
throw std::runtime_error("failed to create command pool");
}
m_transfer_fence = Fence(*this); m_transfer_fence = Fence(*this);
} }

3
src/vk/Context.h

@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/CommandPool.h>
#include <vk/Fence.h> #include <vk/Fence.h>
#include <core/utils.h> #include <core/utils.h>
@ -194,7 +195,7 @@ private:
VkPresentModeKHR m_present_mode; VkPresentModeKHR m_present_mode;
uint32_t m_transfer_queue_index = UINT32_MAX; 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; Fence m_transfer_fence;
std::vector<ContextDestructionCallback> m_context_destruction_callbacks; std::vector<ContextDestructionCallback> m_context_destruction_callbacks;

Loading…
Cancel
Save