Compare commits

...

4 Commits

Author SHA1 Message Date
b8a15406da Use Wrapper for most wrappers. 2022-03-05 12:03:48 +01:00
46b2698abb Improve wrapper. 2022-03-05 11:33:00 +01:00
8358558ddb DescriptorSet related wrappers. 2022-03-05 00:31:08 +01:00
f15ade11b7 ImageView wrapper. 2022-03-04 23:15:33 +01:00
36 changed files with 977 additions and 258 deletions

View File

@@ -36,18 +36,24 @@ add_executable(vk_expe
src/core/utils.cpp src/core/utils.cpp
src/core/Logger.cpp src/core/Logger.cpp
src/vk/Wrapper.cpp
src/vk/Context.cpp src/vk/Context.cpp
src/vk/CommandPool.cpp src/vk/CommandPool.cpp
src/vk/CommandBuffer.cpp src/vk/CommandBuffer.cpp
src/vk/Fence.cpp src/vk/Fence.cpp
src/vk/Semaphore.cpp src/vk/Semaphore.cpp
src/vk/RenderPass.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/Memory.cpp src/vk/Memory.cpp
src/vk/Buffer.cpp src/vk/Buffer.cpp
src/vk/ImageView.cpp
src/vk/DescriptorSetLayout.cpp
src/vk/PipelineLayout.cpp
src/vk/DescriptorPool.cpp
src/vk/DescriptorSet.cpp
src/vk/Swapchain.cpp src/vk/Swapchain.cpp
src/vk/RenderPass.cpp
src/main.cpp src/main.cpp
src/Simplex.cpp src/Simplex.cpp

View File

@@ -187,7 +187,7 @@ void VulkanTutorial::shutdown() {
m_command_pool.destroy(); 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_descriptor_set_layout.destroy();
m_render_done.clear(); m_render_done.clear();
@@ -314,12 +314,12 @@ void VulkanTutorial::destroy_swapchain_objects() {
m_uniform_buffers.clear(); m_uniform_buffers.clear();
m_uniform_buffer_memory.free(); m_uniform_buffer_memory.free();
m_context.destroy_descriptor_pool(m_descriptor_pool); m_descriptor_pool.destroy();
m_framebuffers.clear(); m_framebuffers.clear();
m_pipeline.destroy(); m_pipeline.destroy();
m_context.destroy_pipeline_layout(m_pipeline_layout); m_pipeline_layout.destroy();
m_render_pass.destroy(); m_render_pass.destroy();
} }
@@ -369,25 +369,16 @@ void VulkanTutorial::create_render_pass() {
} }
void VulkanTutorial::create_descriptor_set_layout() { void VulkanTutorial::create_descriptor_set_layout() {
VkDescriptorSetLayoutBinding binding { VkDescriptorSetLayoutBinding binding[] {
.binding = 0, {
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .binding = 0,
.descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, .descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
}
}; };
VkDescriptorSetLayoutCreateInfo layout_info { m_descriptor_set_layout = vk::DescriptorSetLayout(m_context, binding);
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &binding,
};
if(vkCreateDescriptorSetLayout(
m_context.device(),
&layout_info,
nullptr,
&m_descriptor_set_layout
) != VK_SUCCESS)
throw std::runtime_error("failed to create descriptor set layout");
} }
void VulkanTutorial::create_graphic_pipeline() { void VulkanTutorial::create_graphic_pipeline() {
@@ -506,21 +497,10 @@ void VulkanTutorial::create_graphic_pipeline() {
.blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }, .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f },
}; };
VkPipelineLayoutCreateInfo layout_info = { VkDescriptorSetLayout set_layouts[] {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, m_descriptor_set_layout,
.setLayoutCount = 1,
.pSetLayouts = &m_descriptor_set_layout,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
}; };
m_pipeline_layout = vk::PipelineLayout(m_context, set_layouts);
if(vkCreatePipelineLayout(
m_context.device(),
&layout_info,
nullptr,
&m_pipeline_layout
) != VK_SUCCESS)
throw std::runtime_error("failed to create pipeline layout");
VkGraphicsPipelineCreateInfo pipeline_info { VkGraphicsPipelineCreateInfo pipeline_info {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
@@ -628,46 +608,24 @@ void VulkanTutorial::create_uniform_buffer() {
} }
void VulkanTutorial::create_descriptor_pool() { void VulkanTutorial::create_descriptor_pool() {
VkDescriptorPoolSize pool_size { VkDescriptorPoolSize pool_sizes[] {
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, {
.descriptorCount = uint32_t(m_swapchain.image_count()), .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = uint32_t(m_swapchain.image_count()),
}
}; };
VkDescriptorPoolCreateInfo pool_info { m_descriptor_pool = vk::DescriptorPool(
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, m_context,
.maxSets = uint32_t(m_swapchain.image_count()), uint32_t(m_swapchain.image_count()),
.poolSizeCount = 1, pool_sizes
.pPoolSizes = &pool_size, );
};
if(vkCreateDescriptorPool(
m_context.device(),
&pool_info,
nullptr,
&m_descriptor_pool
) != VK_SUCCESS)
throw std::runtime_error("failed to create descriptor pool");
} }
void VulkanTutorial::create_descriptor_sets() { void VulkanTutorial::create_descriptor_sets() {
const std::vector<VkDescriptorSetLayout> layouts( m_descriptor_sets.clear();
m_swapchain.image_count(), m_descriptor_set_layout);
VkDescriptorSetAllocateInfo alloc_info {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = m_descriptor_pool,
.descriptorSetCount = uint32_t(layouts.size()),
.pSetLayouts = layouts.data(),
};
m_descriptor_sets.resize(m_swapchain.image_count());
if(vkAllocateDescriptorSets(
m_context.device(),
&alloc_info,
m_descriptor_sets.data()
) != VK_SUCCESS)
throw std::runtime_error("failed to allocate descriptor sets");
for(size_t index = 0; index < m_swapchain.image_count(); index += 1) { for(size_t index = 0; index < m_swapchain.image_count(); index += 1) {
m_descriptor_sets.emplace_back(m_context, m_descriptor_pool, m_descriptor_set_layout);
VkDescriptorBufferInfo buffer_info { VkDescriptorBufferInfo buffer_info {
.buffer = m_uniform_buffers[index], .buffer = m_uniform_buffers[index],
.offset = 0, .offset = 0,
@@ -762,11 +720,14 @@ void VulkanTutorial::create_command_buffers() {
VK_INDEX_TYPE_UINT32 VK_INDEX_TYPE_UINT32
); );
VkDescriptorSet descriptor_sets[] {
m_descriptor_sets[index],
};
vkCmdBindDescriptorSets( vkCmdBindDescriptorSets(
command_buffer, command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, m_pipeline_layout,
0, 1, &m_descriptor_sets[index], 0, 1, descriptor_sets,
0, nullptr 0, nullptr
); );

View File

@@ -2,6 +2,10 @@
#pragma once #pragma once
#include <vk/Swapchain.h> #include <vk/Swapchain.h>
#include <vk/DescriptorSet.h>
#include <vk/DescriptorPool.h>
#include <vk/PipelineLayout.h>
#include <vk/DescriptorSetLayout.h>
#include <vk/Buffer.h> #include <vk/Buffer.h>
#include <vk/Pipeline.h> #include <vk/Pipeline.h>
#include <vk/Framebuffer.h> #include <vk/Framebuffer.h>
@@ -76,8 +80,8 @@ private:
VkQueue m_presentation_queue = nullptr; VkQueue m_presentation_queue = nullptr;
vk::RenderPass m_render_pass; vk::RenderPass m_render_pass;
VkDescriptorSetLayout m_descriptor_set_layout = VK_NULL_HANDLE; vk::DescriptorSetLayout m_descriptor_set_layout;
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE; vk::PipelineLayout m_pipeline_layout;
vk::Pipeline m_pipeline; vk::Pipeline m_pipeline;
std::vector<vk::Framebuffer> m_framebuffers; std::vector<vk::Framebuffer> m_framebuffers;
vk::CommandPool m_command_pool; vk::CommandPool m_command_pool;
@@ -86,8 +90,8 @@ private:
std::vector<vk::Buffer> m_uniform_buffers; std::vector<vk::Buffer> m_uniform_buffers;
std::vector<VkDeviceSize> m_uniform_buffer_offsets; std::vector<VkDeviceSize> m_uniform_buffer_offsets;
vk::MemoryBlock m_uniform_buffer_memory; vk::MemoryBlock m_uniform_buffer_memory;
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE; vk::DescriptorPool m_descriptor_pool;
std::vector<VkDescriptorSet> m_descriptor_sets; std::vector<vk::DescriptorSet> m_descriptor_sets;
std::vector<vk::CommandBuffer> m_command_buffers; std::vector<vk::CommandBuffer> m_command_buffers;
std::vector<vk::Semaphore> m_render_done; std::vector<vk::Semaphore> m_render_done;

View File

@@ -21,7 +21,7 @@ Buffer::Buffer(
VkDeviceSize size, VkDeviceSize size,
VkBufferUsageFlags usage VkBufferUsageFlags usage
) )
: m_context(&context) : Wrapper(context)
{ {
assert(*m_context); assert(*m_context);
@@ -51,13 +51,8 @@ Buffer::Buffer(
allocate_and_bind_memory(memory_properties); allocate_and_bind_memory(memory_properties);
} }
Buffer::Buffer(Buffer&& other) noexcept Buffer::Buffer(Buffer&& other) noexcept {
: m_context(other.m_context) swap(other);
, m_buffer(other.m_buffer)
, m_memory(std::move(other.m_memory))
{
other.m_context = nullptr;
other.m_buffer = VK_NULL_HANDLE;
} }
Buffer::~Buffer() noexcept { Buffer::~Buffer() noexcept {
@@ -68,12 +63,9 @@ Buffer::~Buffer() noexcept {
} }
Buffer& Buffer::operator=(Buffer&& other) noexcept { Buffer& Buffer::operator=(Buffer&& other) noexcept {
if(&other != this) { swap(other);
using std::swap; if(other)
swap(m_context, other.m_context); other.destroy();
swap(m_buffer, other.m_buffer);
swap(m_memory, other.m_memory);
}
return *this; return *this;
} }

View File

@@ -3,6 +3,7 @@
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Memory.h> #include <vk/Memory.h>
#include <vk/Wrapper.h>
#include <core/utils.h> #include <core/utils.h>
@@ -15,7 +16,7 @@
namespace vk { namespace vk {
class Buffer { class Buffer: public Wrapper {
public: public:
Buffer() noexcept; Buffer() noexcept;
Buffer( Buffer(
@@ -29,11 +30,11 @@ public:
VkBufferUsageFlags usage, VkBufferUsageFlags usage,
VkMemoryPropertyFlags memory_properties VkMemoryPropertyFlags memory_properties
); );
Buffer(const Buffer&) = delete; Buffer(const Buffer&) = default;
Buffer(Buffer&& other) noexcept; Buffer(Buffer&& other) noexcept;
~Buffer() noexcept; ~Buffer() noexcept;
Buffer& operator=(const Buffer&) = delete; Buffer& operator=(const Buffer&) = default;
Buffer& operator=(Buffer&& other) noexcept; Buffer& operator=(Buffer&& other) noexcept;
inline explicit operator bool() const { inline explicit operator bool() const {
@@ -44,14 +45,6 @@ public:
return m_buffer == VK_NULL_HANDLE; return m_buffer == VK_NULL_HANDLE;
} }
inline Context* context() noexcept {
return m_context;
}
inline const Context* context() const noexcept {
return m_context;
}
inline operator VkBuffer() const noexcept { inline operator VkBuffer() const noexcept {
return m_buffer; return m_buffer;
} }
@@ -76,10 +69,20 @@ public:
void upload(size_t size, void* src_buffer, uint32_t dst_queue_family); void upload(size_t size, void* src_buffer, uint32_t dst_queue_family);
inline void swap(Buffer& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_buffer, other.m_buffer);
swap(m_memory, other.m_memory);
}
friend inline void swap(Buffer& buffer_0, Buffer& buffer_1) noexcept {
buffer_0.swap(buffer_1);
}
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkBuffer m_buffer = VK_NULL_HANDLE; VkBuffer m_buffer = VK_NULL_HANDLE;
MemoryBlock m_memory; MemoryBlock m_memory;
}; };

View File

@@ -13,7 +13,7 @@ CommandBuffer::CommandBuffer() noexcept {
} }
CommandBuffer::CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level) CommandBuffer::CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level)
: m_context(&context) : Wrapper(context)
, m_command_pool(command_pool) , m_command_pool(command_pool)
{ {
assert(m_context); assert(m_context);
@@ -35,7 +35,7 @@ CommandBuffer::CommandBuffer(Context& context, VkCommandPool command_pool, VkCom
CommandBuffer::CommandBuffer(CommandBuffer&& other) noexcept CommandBuffer::CommandBuffer(CommandBuffer&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
CommandBuffer::~CommandBuffer() noexcept { CommandBuffer::~CommandBuffer() noexcept {
@@ -45,7 +45,7 @@ CommandBuffer::~CommandBuffer() noexcept {
CommandBuffer& CommandBuffer::operator=(CommandBuffer&& other) noexcept { CommandBuffer& CommandBuffer::operator=(CommandBuffer&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -9,15 +10,15 @@
namespace vk { namespace vk {
class CommandBuffer { class CommandBuffer: public Wrapper {
public: public:
CommandBuffer() noexcept; CommandBuffer() noexcept;
CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level=VK_COMMAND_BUFFER_LEVEL_PRIMARY); CommandBuffer(Context& context, VkCommandPool command_pool, VkCommandBufferLevel level=VK_COMMAND_BUFFER_LEVEL_PRIMARY);
CommandBuffer(const CommandBuffer&) = delete; CommandBuffer(const CommandBuffer&) = default;
CommandBuffer(CommandBuffer&& other) noexcept; CommandBuffer(CommandBuffer&& other) noexcept;
~CommandBuffer() noexcept; ~CommandBuffer() noexcept;
CommandBuffer& operator=(const CommandBuffer&) = delete; CommandBuffer& operator=(const CommandBuffer&) = default;
CommandBuffer& operator=(CommandBuffer&& other) noexcept; CommandBuffer& operator=(CommandBuffer&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -28,14 +29,6 @@ public:
return m_command_buffer == VK_NULL_HANDLE; 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 { inline const VkCommandPool command_pool() const noexcept {
return m_command_pool; return m_command_pool;
} }
@@ -52,17 +45,20 @@ public:
return m_command_buffer; return m_command_buffer;
} }
friend inline void swap(CommandBuffer& command_buffer_0, CommandBuffer& command_buffer_1) noexcept { inline void swap(CommandBuffer& other) noexcept {
using std::swap; using std::swap;
swap(command_buffer_0.m_context, command_buffer_1.m_context); Wrapper::swap(other);
swap(command_buffer_0.m_command_pool, command_buffer_1.m_command_pool); swap(m_command_pool, other.m_command_pool);
swap(command_buffer_0.m_command_buffer, command_buffer_1.m_command_buffer); swap(m_command_buffer, other.m_command_buffer);
}
friend inline void swap(CommandBuffer& command_buffer_0, CommandBuffer& command_buffer_1) noexcept {
command_buffer_0.swap(command_buffer_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkCommandPool m_command_pool = VK_NULL_HANDLE; VkCommandPool m_command_pool = VK_NULL_HANDLE;
VkCommandBuffer m_command_buffer = VK_NULL_HANDLE; VkCommandBuffer m_command_buffer = VK_NULL_HANDLE;
}; };

View File

@@ -13,7 +13,7 @@ CommandPool::CommandPool() noexcept {
} }
CommandPool::CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags) CommandPool::CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -33,7 +33,7 @@ CommandPool::CommandPool(Context& context, uint32_t queue_family, VkCommandPoolC
CommandPool::CommandPool(CommandPool&& other) noexcept CommandPool::CommandPool(CommandPool&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
CommandPool::~CommandPool() noexcept { CommandPool::~CommandPool() noexcept {
@@ -43,7 +43,7 @@ CommandPool::~CommandPool() noexcept {
CommandPool& CommandPool::operator=(CommandPool&& other) noexcept { CommandPool& CommandPool::operator=(CommandPool&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -9,15 +10,15 @@
namespace vk { namespace vk {
class CommandPool { class CommandPool: public Wrapper {
public: public:
CommandPool() noexcept; CommandPool() noexcept;
CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags=0); CommandPool(Context& context, uint32_t queue_family, VkCommandPoolCreateFlags flags=0);
CommandPool(const CommandPool&) = delete; CommandPool(const CommandPool&) = default;
CommandPool(CommandPool&& other) noexcept; CommandPool(CommandPool&& other) noexcept;
~CommandPool() noexcept; ~CommandPool() noexcept;
CommandPool& operator=(const CommandPool&) = delete; CommandPool& operator=(const CommandPool&) = default;
CommandPool& operator=(CommandPool&& other) noexcept; CommandPool& operator=(CommandPool&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -28,14 +29,6 @@ public:
return m_command_pool == VK_NULL_HANDLE; 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 { inline operator VkCommandPool() noexcept {
return m_command_pool; return m_command_pool;
} }
@@ -44,16 +37,19 @@ public:
return m_command_pool; return m_command_pool;
} }
friend inline void swap(CommandPool& command_pool_0, CommandPool& command_pool_1) noexcept { inline void swap(CommandPool& other) noexcept {
using std::swap; using std::swap;
swap(command_pool_0.m_context, command_pool_1.m_context); Wrapper::swap(other);
swap(command_pool_0.m_command_pool, command_pool_1.m_command_pool); swap(m_command_pool, other.m_command_pool);
}
friend inline void swap(CommandPool& command_pool_0, CommandPool& command_pool_1) noexcept {
command_pool_0.swap(command_pool_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkCommandPool m_command_pool = VK_NULL_HANDLE; VkCommandPool m_command_pool = VK_NULL_HANDLE;
}; };

View File

@@ -803,6 +803,9 @@ VKAPI_ATTR VkBool32 VKAPI_CALL Context::log_debug_message(
const VkDebugUtilsMessengerCallbackDataEXT* data, const VkDebugUtilsMessengerCallbackDataEXT* data,
void* user_data void* user_data
) { ) {
if(data->messageIdNumber == 0) // Loader message
return VK_FALSE;
{ {
auto stream = [severity]() { auto stream = [severity]() {
switch(severity) { switch(severity) {
@@ -834,7 +837,9 @@ VKAPI_ATTR VkBool32 VKAPI_CALL Context::log_debug_message(
} }
if(severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT if(severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
&& data->messageIdNumber != 2094043421 // wrong swapchain extent && (
data->messageIdNumber != 2094043421 // wrong swapchain extent
)
) )
abort(); abort();

74
src/vk/DescriptorPool.cpp Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2022 Simon Boyé
#include <vk/DescriptorPool.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
DescriptorPool::DescriptorPool() noexcept {
}
DescriptorPool::DescriptorPool(
Context& context,
uint32_t max_sets,
Array<const VkDescriptorPoolSize> pool_sizes,
VkDescriptorPoolCreateFlags flags
)
: Wrapper(context)
{
assert(m_context);
VkDescriptorPoolCreateInfo create_info {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = flags,
.maxSets = max_sets,
.poolSizeCount = uint32_t(pool_sizes.size()),
.pPoolSizes = pool_sizes.data(),
};
if(vkCreateDescriptorPool(
context.device(),
&create_info,
nullptr,
&m_descriptor_pool
) != VK_SUCCESS)
throw std::runtime_error("failed to create descriptor pool");
}
DescriptorPool::DescriptorPool(DescriptorPool&& other) noexcept
{
swap(other);
}
DescriptorPool::~DescriptorPool() noexcept {
if(!is_null())
destroy();
}
DescriptorPool& DescriptorPool::operator=(DescriptorPool&& other) noexcept {
swap(other);
if(other)
other.destroy();
return *this;
}
void DescriptorPool::destroy() noexcept {
assert(!is_null());
assert(m_context);
vkDestroyDescriptorPool(
m_context->device(),
m_descriptor_pool,
nullptr
);
m_descriptor_pool = nullptr;
}
}

64
src/vk/DescriptorPool.h Normal file
View File

@@ -0,0 +1,64 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <core/utils.h>
#include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h>
namespace vk {
class DescriptorPool: public Wrapper {
public:
DescriptorPool() noexcept;
DescriptorPool(
Context& context,
uint32_t max_sets,
Array<const VkDescriptorPoolSize> pool_sizes,
VkDescriptorPoolCreateFlags flags=0
);
DescriptorPool(const DescriptorPool&) = default;
DescriptorPool(DescriptorPool&& other) noexcept;
~DescriptorPool() noexcept;
DescriptorPool& operator=(const DescriptorPool&) = default;
DescriptorPool& operator=(DescriptorPool&& other) noexcept;
explicit inline operator bool() const noexcept {
return !is_null();
}
inline bool is_null() const noexcept {
return m_descriptor_pool == VK_NULL_HANDLE;
}
inline operator VkDescriptorPool() noexcept {
return m_descriptor_pool;
}
inline VkDescriptorPool descriptor_pool() noexcept {
return m_descriptor_pool;
}
inline void swap(DescriptorPool& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_descriptor_pool, other.m_descriptor_pool);
}
friend inline void swap(DescriptorPool& descriptor_pool_0, DescriptorPool& descriptor_pool_1) noexcept {
descriptor_pool_0.swap(descriptor_pool_1);
}
void destroy() noexcept;
private:
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE;
};
}

76
src/vk/DescriptorSet.cpp Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2022 Simon Boyé
#include <vk/DescriptorSet.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
DescriptorSet::DescriptorSet() noexcept {
}
DescriptorSet::DescriptorSet(
Context& context,
VkDescriptorPool descriptor_pool,
const VkDescriptorSetLayout& set_layout
)
: Wrapper(context, DontOwnUnderlyingObject)
, m_descriptor_pool(descriptor_pool)
{
assert(m_descriptor_pool != VK_NULL_HANDLE);
VkDescriptorSetAllocateInfo create_info {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = m_descriptor_pool,
.descriptorSetCount = 1,
.pSetLayouts = &set_layout,
};
if(vkAllocateDescriptorSets(
context.device(),
&create_info,
&m_descriptor_set
) != VK_SUCCESS)
throw std::runtime_error("failed to create descriptor_set");
}
DescriptorSet::DescriptorSet(DescriptorSet&& other) noexcept
{
swap(other);
}
DescriptorSet::~DescriptorSet() noexcept {
if(!is_null())
destroy();
}
DescriptorSet& DescriptorSet::operator=(DescriptorSet&& other) noexcept {
swap(other);
if(other)
other.destroy();
return *this;
}
void DescriptorSet::destroy() noexcept {
assert(!is_null());
assert(m_context);
if (!own_underlying_object())
return;
vkFreeDescriptorSets(
m_context->device(),
m_descriptor_pool,
1,
&m_descriptor_set
);
m_descriptor_set = nullptr;
}
}

71
src/vk/DescriptorSet.h Normal file
View File

@@ -0,0 +1,71 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h>
namespace vk {
class DescriptorSet: public Wrapper {
public:
DescriptorSet() noexcept;
DescriptorSet(
Context& context,
VkDescriptorPool descriptor_pool,
const VkDescriptorSetLayout& set_layout
);
DescriptorSet(const DescriptorSet&) = default;
DescriptorSet(DescriptorSet&& other) noexcept;
~DescriptorSet() noexcept;
DescriptorSet& operator=(const DescriptorSet&) = default;
DescriptorSet& operator=(DescriptorSet&& other) noexcept;
explicit inline operator bool() const noexcept {
return !is_null();
}
inline bool is_null() const noexcept {
return m_descriptor_set == VK_NULL_HANDLE;
}
inline const VkDescriptorPool descriptor_pool() const noexcept {
return m_descriptor_pool;
}
inline VkDescriptorPool descriptor_pool() noexcept {
return m_descriptor_pool;
}
inline operator VkDescriptorSet() noexcept {
return m_descriptor_set;
}
inline VkDescriptorSet descriptor_set() noexcept {
return m_descriptor_set;
}
inline void swap(DescriptorSet& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_descriptor_pool, other.m_descriptor_pool);
swap(m_descriptor_set, other.m_descriptor_set);
}
friend inline void swap(DescriptorSet& descriptor_set_0, DescriptorSet& descriptor_set_1) noexcept {
descriptor_set_0.swap(descriptor_set_1);
}
void destroy() noexcept;
private:
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE;
VkDescriptorSet m_descriptor_set = VK_NULL_HANDLE;
};
}

View File

@@ -0,0 +1,67 @@
// Copyright 2022 Simon Boyé
#include <vk/DescriptorSetLayout.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
DescriptorSetLayout::DescriptorSetLayout() noexcept {
}
DescriptorSetLayout::DescriptorSetLayout(Context& context, Array<const VkDescriptorSetLayoutBinding> bindings)
: Wrapper(context)
{
assert(m_context);
VkDescriptorSetLayoutCreateInfo create_info {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = uint32_t(bindings.size()),
.pBindings = bindings.data(),
};
if(vkCreateDescriptorSetLayout(
context.device(),
&create_info,
nullptr,
&m_descriptor_set_layout
) != VK_SUCCESS)
throw std::runtime_error("failed to create descriptor set layout");
}
DescriptorSetLayout::DescriptorSetLayout(DescriptorSetLayout&& other) noexcept
{
swap(other);
}
DescriptorSetLayout::~DescriptorSetLayout() noexcept {
if(!is_null())
destroy();
}
DescriptorSetLayout& DescriptorSetLayout::operator=(DescriptorSetLayout&& other) noexcept {
swap(other);
if(other)
other.destroy();
return *this;
}
void DescriptorSetLayout::destroy() noexcept {
assert(!is_null());
assert(m_context);
vkDestroyDescriptorSetLayout(
m_context->device(),
m_descriptor_set_layout,
nullptr
);
m_descriptor_set_layout = nullptr;
}
}

View File

@@ -0,0 +1,59 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <core/utils.h>
#include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h>
namespace vk {
class DescriptorSetLayout: public Wrapper {
public:
DescriptorSetLayout() noexcept;
DescriptorSetLayout(Context& context, Array<const VkDescriptorSetLayoutBinding> bindings);
DescriptorSetLayout(const DescriptorSetLayout&) = default;
DescriptorSetLayout(DescriptorSetLayout&& other) noexcept;
~DescriptorSetLayout() noexcept;
DescriptorSetLayout& operator=(const DescriptorSetLayout&) = default;
DescriptorSetLayout& operator=(DescriptorSetLayout&& other) noexcept;
explicit inline operator bool() const noexcept {
return !is_null();
}
inline bool is_null() const noexcept {
return m_descriptor_set_layout == VK_NULL_HANDLE;
}
inline operator VkDescriptorSetLayout() noexcept {
return m_descriptor_set_layout;
}
inline VkDescriptorSetLayout descriptor_set_layout() noexcept {
return m_descriptor_set_layout;
}
inline void swap(DescriptorSetLayout& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_descriptor_set_layout, other.m_descriptor_set_layout);
}
friend inline void swap(DescriptorSetLayout& descriptor_set_layout_0, DescriptorSetLayout& descriptor_set_layout_1) noexcept {
descriptor_set_layout_0.swap(descriptor_set_layout_1);
}
void destroy() noexcept;
private:
VkDescriptorSetLayout m_descriptor_set_layout = VK_NULL_HANDLE;
};
}

View File

@@ -13,7 +13,7 @@ Fence::Fence() noexcept {
} }
Fence::Fence(Context& context, VkFenceCreateFlags flags) Fence::Fence(Context& context, VkFenceCreateFlags flags)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -32,7 +32,7 @@ Fence::Fence(Context& context, VkFenceCreateFlags flags)
Fence::Fence(Fence&& other) noexcept Fence::Fence(Fence&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
Fence::~Fence() noexcept { Fence::~Fence() noexcept {
@@ -42,7 +42,7 @@ Fence::~Fence() noexcept {
Fence& Fence::operator=(Fence&& other) noexcept { Fence& Fence::operator=(Fence&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -4,6 +4,7 @@
#include <core/ArrayView.h> #include <core/ArrayView.h>
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -11,15 +12,15 @@
namespace vk { namespace vk {
class Fence { class Fence: public Wrapper {
public: public:
Fence() noexcept; Fence() noexcept;
Fence(Context& context, VkFenceCreateFlags flags=0); Fence(Context& context, VkFenceCreateFlags flags=0);
Fence(const Fence&) = delete; Fence(const Fence&) = default;
Fence(Fence&& other) noexcept; Fence(Fence&& other) noexcept;
~Fence() noexcept; ~Fence() noexcept;
Fence& operator=(const Fence&) = delete; Fence& operator=(const Fence&) = default;
Fence& operator=(Fence&& other) noexcept; Fence& operator=(Fence&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -30,14 +31,6 @@ public:
return m_fence == VK_NULL_HANDLE; return m_fence == VK_NULL_HANDLE;
} }
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline operator VkFence() noexcept { inline operator VkFence() noexcept {
return m_fence; return m_fence;
} }
@@ -50,16 +43,19 @@ public:
void reset(); void reset();
void wait(uint64_t timeout=UINT64_MAX) const; void wait(uint64_t timeout=UINT64_MAX) const;
friend inline void swap(Fence& fence_0, Fence& fence_1) noexcept { inline void swap(Fence& other) noexcept {
using std::swap; using std::swap;
swap(fence_0.m_context, fence_1.m_context); Wrapper::swap(other);
swap(fence_0.m_fence, fence_1.m_fence); swap(m_fence, other.m_fence);
}
friend inline void swap(Fence& fence_0, Fence& fence_1) noexcept {
fence_0.swap(fence_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkFence m_fence = VK_NULL_HANDLE; VkFence m_fence = VK_NULL_HANDLE;
}; };

View File

@@ -18,7 +18,7 @@ Framebuffer::Framebuffer(
Array<VkImageView> attachments, Array<VkImageView> attachments,
uint32_t width, uint32_t height, uint32_t layers uint32_t width, uint32_t height, uint32_t layers
) )
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
assert(render_pass); assert(render_pass);
@@ -52,7 +52,7 @@ Framebuffer::Framebuffer(
Framebuffer::Framebuffer(Framebuffer&& other) noexcept Framebuffer::Framebuffer(Framebuffer&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
Framebuffer::~Framebuffer() noexcept { Framebuffer::~Framebuffer() noexcept {
@@ -62,7 +62,7 @@ Framebuffer::~Framebuffer() noexcept {
Framebuffer& Framebuffer::operator=(Framebuffer&& other) noexcept { Framebuffer& Framebuffer::operator=(Framebuffer&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -4,6 +4,7 @@
#include <core/utils.h> #include <core/utils.h>
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -11,7 +12,7 @@
namespace vk { namespace vk {
class Framebuffer { class Framebuffer: public Wrapper {
public: public:
Framebuffer() noexcept; Framebuffer() noexcept;
Framebuffer( Framebuffer(
@@ -26,11 +27,11 @@ public:
Array<VkImageView> attachments, Array<VkImageView> attachments,
VkExtent2D extent, uint32_t layers=1 VkExtent2D extent, uint32_t layers=1
); );
Framebuffer(const Framebuffer&) = delete; Framebuffer(const Framebuffer&) = default;
Framebuffer(Framebuffer&& other) noexcept; Framebuffer(Framebuffer&& other) noexcept;
~Framebuffer() noexcept; ~Framebuffer() noexcept;
Framebuffer& operator=(const Framebuffer&) = delete; Framebuffer& operator=(const Framebuffer&) = default;
Framebuffer& operator=(Framebuffer&& other) noexcept; Framebuffer& operator=(Framebuffer&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -41,14 +42,6 @@ public:
return m_framebuffer == VK_NULL_HANDLE; return m_framebuffer == VK_NULL_HANDLE;
} }
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline operator VkFramebuffer() noexcept { inline operator VkFramebuffer() noexcept {
return m_framebuffer; return m_framebuffer;
} }
@@ -57,16 +50,19 @@ public:
return m_framebuffer; return m_framebuffer;
} }
friend inline void swap(Framebuffer& framebuffer_0, Framebuffer& framebuffer_1) noexcept { inline void swap(Framebuffer& other) noexcept {
using std::swap; using std::swap;
swap(framebuffer_0.m_context, framebuffer_1.m_context); Wrapper::swap(other);
swap(framebuffer_0.m_framebuffer, framebuffer_1.m_framebuffer); swap(m_framebuffer, other.m_framebuffer);
}
friend inline void swap(Framebuffer& framebuffer_0, Framebuffer& framebuffer_1) noexcept {
framebuffer_0.swap(framebuffer_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkFramebuffer m_framebuffer = VK_NULL_HANDLE; VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
}; };

62
src/vk/ImageView.cpp Normal file
View File

@@ -0,0 +1,62 @@
// Copyright 2022 Simon Boyé
#include <vk/ImageView.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
ImageView::ImageView() noexcept {
}
ImageView::ImageView(Context& context, const VkImageViewCreateInfo& create_info)
: Wrapper(context)
{
assert(m_context);
if(vkCreateImageView(
context.device(),
&create_info,
nullptr,
&m_image_view
) != VK_SUCCESS)
throw std::runtime_error("failed to create image view");
}
ImageView::ImageView(ImageView&& other) noexcept
{
swap(other);
}
ImageView::~ImageView() noexcept {
if(!is_null())
destroy();
}
ImageView& ImageView::operator=(ImageView&& other) noexcept {
swap(other);
if(other)
other.destroy();
return *this;
}
void ImageView::destroy() noexcept {
assert(!is_null());
assert(m_context);
vkDestroyImageView(
m_context->device(),
m_image_view,
nullptr
);
m_image_view = nullptr;
}
}

57
src/vk/ImageView.h Normal file
View File

@@ -0,0 +1,57 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h>
namespace vk {
class ImageView: public Wrapper {
public:
ImageView() noexcept;
ImageView(Context& context, const VkImageViewCreateInfo& create_info);
ImageView(const ImageView&) = default;
ImageView(ImageView&& other) noexcept;
~ImageView() noexcept;
ImageView& operator=(const ImageView&) = default;
ImageView& operator=(ImageView&& other) noexcept;
explicit inline operator bool() const noexcept {
return !is_null();
}
inline bool is_null() const noexcept {
return m_image_view == VK_NULL_HANDLE;
}
inline operator VkImageView() noexcept {
return m_image_view;
}
inline VkImageView image_view() noexcept {
return m_image_view;
}
inline void swap(ImageView& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_image_view, other.m_image_view);
}
friend inline void swap(ImageView& image_view_0, ImageView& image_view_1) noexcept {
image_view_0.swap(image_view_1);
}
void destroy() noexcept;
private:
VkImageView m_image_view = VK_NULL_HANDLE;
};
}

View File

@@ -13,7 +13,7 @@ Pipeline::Pipeline() noexcept {
} }
Pipeline::Pipeline(Context& context, VkPipeline pipeline) Pipeline::Pipeline(Context& context, VkPipeline pipeline)
: m_context(&context) : Wrapper(context)
, m_pipeline(pipeline) , m_pipeline(pipeline)
{ {
assert(m_context); assert(m_context);
@@ -21,7 +21,7 @@ Pipeline::Pipeline(Context& context, VkPipeline pipeline)
} }
Pipeline::Pipeline(Context& context, VkGraphicsPipelineCreateInfo create_info) Pipeline::Pipeline(Context& context, VkGraphicsPipelineCreateInfo create_info)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -37,7 +37,7 @@ Pipeline::Pipeline(Context& context, VkGraphicsPipelineCreateInfo create_info)
Pipeline::Pipeline(Pipeline&& other) noexcept Pipeline::Pipeline(Pipeline&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
Pipeline::~Pipeline() noexcept { Pipeline::~Pipeline() noexcept {
@@ -47,7 +47,7 @@ Pipeline::~Pipeline() noexcept {
Pipeline& Pipeline::operator=(Pipeline&& other) noexcept { Pipeline& Pipeline::operator=(Pipeline&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -9,16 +10,16 @@
namespace vk { namespace vk {
class Pipeline { class Pipeline: public Wrapper {
public: public:
Pipeline() noexcept; Pipeline() noexcept;
Pipeline(Context& context, VkPipeline pipeline); Pipeline(Context& context, VkPipeline pipeline);
Pipeline(Context& context, VkGraphicsPipelineCreateInfo create_info); Pipeline(Context& context, VkGraphicsPipelineCreateInfo create_info);
Pipeline(const Pipeline&) = delete; Pipeline(const Pipeline&) = default;
Pipeline(Pipeline&& other) noexcept; Pipeline(Pipeline&& other) noexcept;
~Pipeline() noexcept; ~Pipeline() noexcept;
Pipeline& operator=(const Pipeline&) = delete; Pipeline& operator=(const Pipeline&) = default;
Pipeline& operator=(Pipeline&& other) noexcept; Pipeline& operator=(Pipeline&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -29,14 +30,6 @@ public:
return m_pipeline == VK_NULL_HANDLE; return m_pipeline == VK_NULL_HANDLE;
} }
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline operator VkPipeline() noexcept { inline operator VkPipeline() noexcept {
return m_pipeline; return m_pipeline;
} }
@@ -45,16 +38,19 @@ public:
return m_pipeline; return m_pipeline;
} }
friend inline void swap(Pipeline& pipeline_0, Pipeline& pipeline_1) noexcept { inline void swap(Pipeline& other) noexcept {
using std::swap; using std::swap;
swap(pipeline_0.m_context, pipeline_1.m_context); Wrapper::swap(other);
swap(pipeline_0.m_pipeline, pipeline_1.m_pipeline); swap(m_pipeline, other.m_pipeline);
}
friend inline void swap(Pipeline& pipeline_0, Pipeline& pipeline_1) noexcept {
pipeline_0.swap(pipeline_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkPipeline m_pipeline = VK_NULL_HANDLE; VkPipeline m_pipeline = VK_NULL_HANDLE;
}; };

73
src/vk/PipelineLayout.cpp Normal file
View File

@@ -0,0 +1,73 @@
// Copyright 2022 Simon Boyé
#include <vk/PipelineLayout.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
PipelineLayout::PipelineLayout() noexcept {
}
PipelineLayout::PipelineLayout(
Context& context,
Array<const VkDescriptorSetLayout> set_layouts,
Array<const VkPushConstantRange> push_constant_ranges
)
: Wrapper(context)
{
assert(m_context);
VkPipelineLayoutCreateInfo create_info {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = uint32_t(set_layouts.size()),
.pSetLayouts = set_layouts.data(),
.pushConstantRangeCount = uint32_t(push_constant_ranges.size()),
.pPushConstantRanges = push_constant_ranges.data(),
};
if(vkCreatePipelineLayout(
context.device(),
&create_info,
nullptr,
&m_pipeline_layout
) != VK_SUCCESS)
throw std::runtime_error("failed to create pipeline layout");
}
PipelineLayout::PipelineLayout(PipelineLayout&& other) noexcept
{
swap(other);
}
PipelineLayout::~PipelineLayout() noexcept {
if(!is_null())
destroy();
}
PipelineLayout& PipelineLayout::operator=(PipelineLayout&& other) noexcept {
swap(other);
if(other)
other.destroy();
return *this;
}
void PipelineLayout::destroy() noexcept {
assert(!is_null());
assert(m_context);
vkDestroyPipelineLayout(
m_context->device(),
m_pipeline_layout,
nullptr
);
m_pipeline_layout = nullptr;
}
}

63
src/vk/PipelineLayout.h Normal file
View File

@@ -0,0 +1,63 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <core/utils.h>
#include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h>
namespace vk {
class PipelineLayout: public Wrapper {
public:
PipelineLayout() noexcept;
PipelineLayout(
Context& context,
Array<const VkDescriptorSetLayout> set_layouts,
Array<const VkPushConstantRange> push_constant_ranges={}
);
PipelineLayout(const PipelineLayout&) = default;
PipelineLayout(PipelineLayout&& other) noexcept;
~PipelineLayout() noexcept;
PipelineLayout& operator=(const PipelineLayout&) = default;
PipelineLayout& operator=(PipelineLayout&& other) noexcept;
explicit inline operator bool() const noexcept {
return !is_null();
}
inline bool is_null() const noexcept {
return m_pipeline_layout == VK_NULL_HANDLE;
}
inline operator VkPipelineLayout() noexcept {
return m_pipeline_layout;
}
inline VkPipelineLayout pipeline_layout() noexcept {
return m_pipeline_layout;
}
inline void swap(PipelineLayout& other) noexcept {
using std::swap;
Wrapper::swap(other);
swap(m_pipeline_layout, other.m_pipeline_layout);
}
friend inline void swap(PipelineLayout& pipeline_layout_0, PipelineLayout& pipeline_layout_1) noexcept {
pipeline_layout_0.swap(pipeline_layout_1);
}
void destroy() noexcept;
private:
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
};
}

View File

@@ -13,7 +13,7 @@ RenderPass::RenderPass() noexcept {
} }
RenderPass::RenderPass(Context& context, const VkRenderPassCreateInfo& create_info) RenderPass::RenderPass(Context& context, const VkRenderPassCreateInfo& create_info)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -28,7 +28,7 @@ RenderPass::RenderPass(Context& context, const VkRenderPassCreateInfo& create_in
RenderPass::RenderPass(RenderPass&& other) noexcept RenderPass::RenderPass(RenderPass&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
RenderPass::~RenderPass() noexcept { RenderPass::~RenderPass() noexcept {
@@ -38,7 +38,7 @@ RenderPass::~RenderPass() noexcept {
RenderPass& RenderPass::operator=(RenderPass&& other) noexcept { RenderPass& RenderPass::operator=(RenderPass&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -9,15 +10,15 @@
namespace vk { namespace vk {
class RenderPass { class RenderPass: public Wrapper {
public: public:
RenderPass() noexcept; RenderPass() noexcept;
RenderPass(Context& context, const VkRenderPassCreateInfo& create_info); RenderPass(Context& context, const VkRenderPassCreateInfo& create_info);
RenderPass(const RenderPass&) = delete; RenderPass(const RenderPass&) = default;
RenderPass(RenderPass&& other) noexcept; RenderPass(RenderPass&& other) noexcept;
~RenderPass() noexcept; ~RenderPass() noexcept;
RenderPass& operator=(const RenderPass&) = delete; RenderPass& operator=(const RenderPass&) = default;
RenderPass& operator=(RenderPass&& other) noexcept; RenderPass& operator=(RenderPass&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -36,16 +37,19 @@ public:
return m_render_pass; return m_render_pass;
} }
friend inline void swap(RenderPass& render_pass_0, RenderPass& render_pass_1) noexcept { inline void swap(RenderPass& other) noexcept {
using std::swap; using std::swap;
swap(render_pass_0.m_context, render_pass_1.m_context); Wrapper::swap(other);
swap(render_pass_0.m_render_pass, render_pass_1.m_render_pass); swap(m_render_pass, other.m_render_pass);
}
friend inline void swap(RenderPass& render_pass_0, RenderPass& render_pass_1) noexcept {
render_pass_0.swap(render_pass_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkRenderPass m_render_pass = VK_NULL_HANDLE; VkRenderPass m_render_pass = VK_NULL_HANDLE;
}; };

View File

@@ -13,7 +13,7 @@ Semaphore::Semaphore() noexcept {
} }
Semaphore::Semaphore(Context& context) Semaphore::Semaphore(Context& context)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -31,7 +31,7 @@ Semaphore::Semaphore(Context& context)
Semaphore::Semaphore(Semaphore&& other) noexcept Semaphore::Semaphore(Semaphore&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
Semaphore::~Semaphore() noexcept { Semaphore::~Semaphore() noexcept {
@@ -41,7 +41,7 @@ Semaphore::~Semaphore() noexcept {
Semaphore& Semaphore::operator=(Semaphore&& other) noexcept { Semaphore& Semaphore::operator=(Semaphore&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
@@ -9,15 +10,15 @@
namespace vk { namespace vk {
class Semaphore { class Semaphore: public Wrapper {
public: public:
Semaphore() noexcept; Semaphore() noexcept;
Semaphore(Context& context); Semaphore(Context& context);
Semaphore(const Semaphore&) = delete; Semaphore(const Semaphore&) = default;
Semaphore(Semaphore&& other) noexcept; Semaphore(Semaphore&& other) noexcept;
~Semaphore() noexcept; ~Semaphore() noexcept;
Semaphore& operator=(const Semaphore&) = delete; Semaphore& operator=(const Semaphore&) = default;
Semaphore& operator=(Semaphore&& other) noexcept; Semaphore& operator=(Semaphore&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -28,14 +29,6 @@ public:
return m_semaphore == VK_NULL_HANDLE; return m_semaphore == VK_NULL_HANDLE;
} }
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline operator VkSemaphore() noexcept { inline operator VkSemaphore() noexcept {
return m_semaphore; return m_semaphore;
} }
@@ -44,16 +37,19 @@ public:
return m_semaphore; return m_semaphore;
} }
friend inline void swap(Semaphore& semaphore_0, Semaphore& semaphore_1) noexcept { inline void swap(Semaphore& other) noexcept {
using std::swap; using std::swap;
swap(semaphore_0.m_context, semaphore_1.m_context); Wrapper::swap(other);
swap(semaphore_0.m_semaphore, semaphore_1.m_semaphore); swap(m_semaphore, other.m_semaphore);
}
friend inline void swap(Semaphore& semaphore_0, Semaphore& semaphore_1) noexcept {
semaphore_0.swap(semaphore_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkSemaphore m_semaphore = VK_NULL_HANDLE; VkSemaphore m_semaphore = VK_NULL_HANDLE;
}; };

View File

@@ -13,7 +13,7 @@ ShaderModule::ShaderModule() noexcept {
} }
ShaderModule::ShaderModule(Context& context, const std::vector<char>& code) ShaderModule::ShaderModule(Context& context, const std::vector<char>& code)
: m_context(&context) : Wrapper(context)
{ {
assert(m_context); assert(m_context);
@@ -37,7 +37,7 @@ ShaderModule::ShaderModule(Context& context, const char* path)
ShaderModule::ShaderModule(ShaderModule&& other) noexcept ShaderModule::ShaderModule(ShaderModule&& other) noexcept
{ {
swap(*this, other); swap(other);
} }
ShaderModule::~ShaderModule() noexcept { ShaderModule::~ShaderModule() noexcept {
@@ -47,7 +47,7 @@ ShaderModule::~ShaderModule() noexcept {
ShaderModule& ShaderModule::operator=(ShaderModule&& other) noexcept { ShaderModule& ShaderModule::operator=(ShaderModule&& other) noexcept {
swap(*this, other); swap(other);
if(other) if(other)
other.destroy(); other.destroy();
return *this; return *this;

View File

@@ -1,26 +1,27 @@
// Copyright 2022 Simon Boyé // Copyright 2022 Simon Boyé
#pragma once #pragma once
#include <core/utils.h>
#include <vk/forward.h> #include <vk/forward.h>
#include <vk/Wrapper.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <vector>
namespace vk { namespace vk {
class ShaderModule { class ShaderModule: public Wrapper {
public: public:
ShaderModule() noexcept; ShaderModule() noexcept;
ShaderModule(Context& context, const std::vector<char>& code); ShaderModule(Context& context, const std::vector<char>& code);
ShaderModule(Context& context, const char* path); ShaderModule(Context& context, const char* path);
ShaderModule(const ShaderModule&) = delete; ShaderModule(const ShaderModule&) = default;
ShaderModule(ShaderModule&& other) noexcept; ShaderModule(ShaderModule&& other) noexcept;
~ShaderModule() noexcept; ~ShaderModule() noexcept;
ShaderModule& operator=(const ShaderModule&) = delete; ShaderModule& operator=(const ShaderModule&) = default;
ShaderModule& operator=(ShaderModule&& other) noexcept; ShaderModule& operator=(ShaderModule&& other) noexcept;
explicit inline operator bool() const noexcept { explicit inline operator bool() const noexcept {
@@ -31,14 +32,6 @@ public:
return m_shader_module == VK_NULL_HANDLE; return m_shader_module == VK_NULL_HANDLE;
} }
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline operator VkShaderModule() noexcept { inline operator VkShaderModule() noexcept {
return m_shader_module; return m_shader_module;
} }
@@ -47,16 +40,19 @@ public:
return m_shader_module; return m_shader_module;
} }
friend inline void swap(ShaderModule& shader_module_0, ShaderModule& shader_module_1) noexcept { inline void swap(ShaderModule& other) noexcept {
using std::swap; using std::swap;
swap(shader_module_0.m_context, shader_module_1.m_context); Wrapper::swap(other);
swap(shader_module_0.m_shader_module, shader_module_1.m_shader_module); swap(m_shader_module, other.m_shader_module);
}
friend inline void swap(ShaderModule& shader_module_0, ShaderModule& shader_module_1) noexcept {
shader_module_0.swap(shader_module_1);
} }
void destroy() noexcept; void destroy() noexcept;
private: private:
Context* m_context = nullptr;
VkShaderModule m_shader_module = VK_NULL_HANDLE; VkShaderModule m_shader_module = VK_NULL_HANDLE;
}; };

View File

@@ -137,9 +137,9 @@ void Swapchain::begin_frame() {
} }
} }
logger.info() << "begin frame " << m_frame_index // logger.info() << "begin frame " << m_frame_index
<< ": image " << m_current_image_index // << ": image " << m_current_image_index
<< ", frame: " << m_frame_resources_index; // << ", frame: " << m_frame_resources_index;
auto& image_resources = m_image_resources[m_current_image_index]; auto& image_resources = m_image_resources[m_current_image_index];
@@ -293,7 +293,7 @@ void Swapchain::create() {
image_resources.image = swapchain_images[index]; image_resources.image = swapchain_images[index];
VkImageViewCreateInfo view_info { image_resources.view = ImageView(*m_context, VkImageViewCreateInfo {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = image_resources.image, .image = image_resources.image,
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
@@ -311,16 +311,7 @@ void Swapchain::create() {
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = 1, .layerCount = 1,
}, },
}; });
if(vkCreateImageView(
m_context->device(),
&view_info,
nullptr,
&image_resources.view
) != VK_SUCCESS) {
throw std::runtime_error("failed to create swapchain image view");
}
image_resources.render_done = Fence(*m_context, VK_FENCE_CREATE_SIGNALED_BIT); image_resources.render_done = Fence(*m_context, VK_FENCE_CREATE_SIGNALED_BIT);
} }
@@ -344,7 +335,7 @@ void Swapchain::destroy() {
for(auto& image_resources: m_image_resources) { for(auto& image_resources: m_image_resources) {
image_resources.render_done.destroy(); image_resources.render_done.destroy();
m_context->destroy_image_view(image_resources.view); image_resources.view.destroy();
} }
m_context->destroy_swapchain(m_swapchain); m_context->destroy_swapchain(m_swapchain);

View File

@@ -1,8 +1,9 @@
// Copyright 2022 Simon Boyé // Copyright 2022 Simon Boyé
#pragma once #pragma once
#include <vk/Semaphore.h>
#include <vk/Context.h> #include <vk/Context.h>
#include <vk/Semaphore.h>
#include <vk/ImageView.h>
#include <core/utils.h> #include <core/utils.h>
@@ -76,7 +77,7 @@ public:
private: private:
struct ImageResources { struct ImageResources {
VkImage image = VK_NULL_HANDLE; VkImage image = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE; ImageView view;
Fence render_done; Fence render_done;
}; };

49
src/vk/Wrapper.cpp Normal file
View File

@@ -0,0 +1,49 @@
// Copyright 2022 Simon Boyé
#include <vk/Wrapper.h>
#include <vk/Context.h>
#include <cassert>
namespace vk {
Wrapper::Wrapper() noexcept {
}
Wrapper::Wrapper(Context& context, Flags flags) noexcept
: m_context(&context)
, m_flags(flags)
{
assert(m_context);
}
Wrapper::Wrapper(const Wrapper& other) noexcept
: m_context(other.m_context)
{}
Wrapper::Wrapper(Wrapper&& other) noexcept
{
swap(other);
}
Wrapper::~Wrapper() noexcept {
}
Wrapper& Wrapper::operator=(const Wrapper& other) noexcept {
if (&other != this) {
m_context = other.m_context;
m_flags = other.m_flags & ~OwnUnderlyingObject;
}
return *this;
}
Wrapper& Wrapper::operator=(Wrapper&& other) noexcept {
swap(other);
return *this;
}
}

65
src/vk/Wrapper.h Normal file
View File

@@ -0,0 +1,65 @@
// Copyright 2022 Simon Boyé
#pragma once
#include <vk/forward.h>
#include <vulkan/vulkan.h>
namespace vk {
class Wrapper {
public:
enum Flag {
DontOwnUnderlyingObject = 0x00,
OwnUnderlyingObject = 0x01,
};
using Flags = unsigned;
public:
Wrapper() noexcept;
Wrapper(Context& context, Flags flags=OwnUnderlyingObject) noexcept;
Wrapper(const Wrapper& other) noexcept;
Wrapper(Wrapper&& other) noexcept;
~Wrapper() noexcept;
Wrapper& operator=(const Wrapper& other) noexcept;
Wrapper& operator=(Wrapper&& other) noexcept;
inline const Context* context() const noexcept {
return m_context;
}
inline Context* context() noexcept {
return m_context;
}
inline bool own_underlying_object() const noexcept {
return (m_flags & OwnUnderlyingObject) != 0;
}
inline void set_own_underlying_object(bool own_underlying_object) noexcept {
if(own_underlying_object)
m_flags |= OwnUnderlyingObject;
else
m_flags &= ~OwnUnderlyingObject;
}
inline void swap(Wrapper& other) noexcept {
using std::swap;
swap(m_context, other.m_context);
swap(m_flags, other.m_flags);
}
friend inline void swap(Wrapper& wrapper_0, Wrapper& wrapper_1) noexcept {
wrapper_0.swap(wrapper_1);
}
protected:
Context* m_context = nullptr;
Flags m_flags = 0;
};
}