diff --git a/CMakeLists.txt b/CMakeLists.txt index 1217602..b8921f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(vk_expe src/vk/Fence.cpp src/vk/Semaphore.cpp src/vk/Framebuffer.cpp + src/vk/ShaderModule.cpp src/vk/Swapchain.cpp src/vk/Memory.cpp src/vk/Buffer.cpp diff --git a/src/VulkanTutorial.cpp b/src/VulkanTutorial.cpp index b20d2aa..25733d0 100644 --- a/src/VulkanTutorial.cpp +++ b/src/VulkanTutorial.cpp @@ -3,6 +3,8 @@ #include +#include + #include #include @@ -392,23 +394,9 @@ void VulkanTutorial::create_descriptor_set_layout() { } void VulkanTutorial::create_graphic_pipeline() { - auto const vertex_shader_module = - m_context.create_shader_module_from_file("shaders/shader.vert.spv"); - auto const vertex_shader_guard = make_guard([&]{ - vkDestroyShaderModule(m_context.device(), vertex_shader_module, nullptr); - }); - - auto const geometry_shader_module = - m_context.create_shader_module_from_file("shaders/shader.geom.spv"); - auto const geometry_shader_guard = make_guard([&]{ - vkDestroyShaderModule(m_context.device(), geometry_shader_module, nullptr); - }); - - auto const fragment_shader_module = - m_context.create_shader_module_from_file("shaders/shader.frag.spv"); - auto const fragment_shader_guard = make_guard([&]{ - vkDestroyShaderModule(m_context.device(), fragment_shader_module, nullptr); - }); + auto vertex_shader_module = vk::ShaderModule(m_context, "shaders/shader.vert.spv"); + auto geometry_shader_module = vk::ShaderModule(m_context, "shaders/shader.geom.spv"); + auto fragment_shader_module = vk::ShaderModule(m_context, "shaders/shader.frag.spv"); VkPipelineShaderStageCreateInfo shader_stage_infos[] = { { diff --git a/src/vk/ShaderModule.cpp b/src/vk/ShaderModule.cpp new file mode 100644 index 0000000..6bd976b --- /dev/null +++ b/src/vk/ShaderModule.cpp @@ -0,0 +1,71 @@ +// Copyright 2022 Simon Boyé + +#include +#include + +#include + + +namespace vk { + + +ShaderModule::ShaderModule() noexcept { +} + +ShaderModule::ShaderModule(Context& context, const std::vector& code) + : m_context(&context) +{ + assert(m_context); + + VkShaderModuleCreateInfo create_info { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .codeSize = code.size(), + .pCode = (uint32_t*)code.data(), + }; + if(vkCreateShaderModule( + context.device(), + &create_info, + nullptr, + &m_shader_module + ) != VK_SUCCESS) + throw std::runtime_error("failed to create shader module"); +} + +ShaderModule::ShaderModule(Context& context, const char* path) + : ShaderModule(context, read_binary_file(path)) +{} + +ShaderModule::ShaderModule(ShaderModule&& other) noexcept +{ + swap(*this, other); +} + +ShaderModule::~ShaderModule() noexcept { + if(!is_null()) + destroy(); +} + + +ShaderModule& ShaderModule::operator=(ShaderModule&& other) noexcept { + swap(*this, other); + if(other) + other.destroy(); + return *this; +} + + +void ShaderModule::destroy() noexcept { + assert(!is_null()); + assert(m_context); + + vkDestroyShaderModule( + m_context->device(), + m_shader_module, + nullptr + ); + + m_shader_module = nullptr; +} + + +} diff --git a/src/vk/ShaderModule.h b/src/vk/ShaderModule.h new file mode 100644 index 0000000..a8748ca --- /dev/null +++ b/src/vk/ShaderModule.h @@ -0,0 +1,64 @@ +// Copyright 2022 Simon Boyé +#pragma once + +#include + +#include + +#include + + +namespace vk { + + +class ShaderModule { +public: + ShaderModule() noexcept; + ShaderModule(Context& context, const std::vector& code); + ShaderModule(Context& context, const char* path); + ShaderModule(const ShaderModule&) = delete; + ShaderModule(ShaderModule&& other) noexcept; + ~ShaderModule() noexcept; + + ShaderModule& operator=(const ShaderModule&) = delete; + ShaderModule& operator=(ShaderModule&& other) noexcept; + + explicit inline operator bool() const noexcept { + return !is_null(); + } + + inline bool is_null() const noexcept { + 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 { + return m_shader_module; + } + + inline VkShaderModule shader_module() noexcept { + return m_shader_module; + } + + friend inline void swap(ShaderModule& shader_module_0, ShaderModule& shader_module_1) noexcept { + using std::swap; + swap(shader_module_0.m_context, shader_module_1.m_context); + swap(shader_module_0.m_shader_module, shader_module_1.m_shader_module); + } + + void destroy() noexcept; + +private: + Context* m_context = nullptr; + VkShaderModule m_shader_module = VK_NULL_HANDLE; +}; + + +}