From 1c84af84434ccfdc4072ec5f09ebefc10814d373 Mon Sep 17 00:00:00 2001 From: Artur Wasmut <awasmut@uni-koblenz.de> Date: Sun, 16 May 2021 14:35:57 +0200 Subject: [PATCH] implement PipelineManager class. --- config/Sources.cmake | 7 +- include/vkcv/Core.hpp | 26 ++- .../vkcv/{Pipeline.hpp => PipelineConfig.hpp} | 12 +- projects/first_triangle/src/main.cpp | 7 +- src/vkcv/Core.cpp | 194 +-------------- src/vkcv/PassManager.cpp | 3 +- src/vkcv/{Pipeline.cpp => PipelineConfig.cpp} | 4 +- src/vkcv/PipelineManager.cpp | 221 ++++++++++++++++++ src/vkcv/PipelineManager.hpp | 35 +++ 9 files changed, 302 insertions(+), 207 deletions(-) rename include/vkcv/{Pipeline.hpp => PipelineConfig.hpp} (77%) rename src/vkcv/{Pipeline.cpp => PipelineConfig.cpp} (59%) create mode 100644 src/vkcv/PipelineManager.cpp create mode 100644 src/vkcv/PipelineManager.hpp diff --git a/config/Sources.cmake b/config/Sources.cmake index 0a612e7f..dc4d2e85 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -25,6 +25,9 @@ set(vkcv_sources ${vkcv_include}/vkcv/ShaderProgram.hpp ${vkcv_source}/vkcv/ShaderProgram.cpp - ${vkcv_include}/vkcv/Pipeline.hpp - ${vkcv_source}/vkcv/Pipeline.cpp + ${vkcv_include}/vkcv/PipelineConfig.hpp + ${vkcv_source}/vkcv/PipelineConfig.cpp + + ${vkcv_source}/vkcv/PipelineManager.hpp + ${vkcv_source}/vkcv/PipelineManager.cpp ) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 048b1ad5..e700ac4a 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -12,7 +12,7 @@ #include "vkcv/Window.hpp" #include "vkcv/PassConfig.hpp" #include "vkcv/Handles.hpp" -#include "vkcv/Pipeline.hpp" +#include "vkcv/PipelineConfig.hpp" namespace vkcv { @@ -21,6 +21,7 @@ namespace vkcv // forward declarations class PassManager; + class PipelineManager; class Core final { @@ -46,6 +47,7 @@ namespace vkcv std::vector<vk::PipelineLayout> m_PipelineLayouts; std::unique_ptr<PassManager> m_PassManager; + std::unique_ptr<PipelineManager> m_PipelineManager; public: /** * Destructor of #Core destroys the Vulkan objects contained in the core's context. @@ -108,19 +110,29 @@ namespace vkcv std::vector<const char*> deviceExtensions = {}); /** - * Creates a basic vulkan graphics pipeline using @p pipeline from the pipeline class and returns it using the @p handle. + * Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle. * Fixed Functions for pipeline are set with standard values. * - * @param pipeline a pipeline object from the pipeline class + * @param config a pipeline config object from the pipeline config class * @param handle a handle to return the created vulkan handle - * @return True if Pipeline creation was successfull, False if not + * @return True if pipeline creation was successful, False if not */ - bool createGraphicsPipeline(const Pipeline &pipeline, PipelineHandle &handle); + [[nodiscard]] + PipelineHandle createGraphicsPipeline(const PipelineConfig &config); + + /** + * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle. + * Fixed Functions for pipeline are set with standard values. + * + * @param config a render pass config object from the render pass config class + * @param handle a handle to return the created vulkan handle + * @return True if render pass creation was successful, False if not + */ + [[nodiscard]] + PassHandle createPass(const PassConfig &config); // TODO: BufferHandle createBuffer(const Buffer &buf); - [[nodiscard]] - PassHandle createPass(const PassConfig &config); }; } diff --git a/include/vkcv/Pipeline.hpp b/include/vkcv/PipelineConfig.hpp similarity index 77% rename from include/vkcv/Pipeline.hpp rename to include/vkcv/PipelineConfig.hpp index 06380d0a..5aa4dac9 100644 --- a/include/vkcv/Pipeline.hpp +++ b/include/vkcv/PipelineConfig.hpp @@ -4,8 +4,8 @@ * @brief Pipeline class to handle shader stages */ -#ifndef VKCV_PIPELINE_HPP -#define VKCV_PIPELINE_HPP +#ifndef VKCV_PIPELINECONFIG_HPP +#define VKCV_PIPELINECONFIG_HPP #include <vector> #include <cstdint> @@ -14,13 +14,13 @@ namespace vkcv { - class Pipeline { + class PipelineConfig { public: /** * Default constructer is deleted! */ - Pipeline() = delete; + PipelineConfig() = delete; /** * Constructor for the pipeline. Creates a pipeline using @p vertexCode, @p fragmentCode as well as the @@ -31,7 +31,7 @@ namespace vkcv { * @param width width of the application window * @param passHandle handle for Render Pass */ - Pipeline(const ShaderProgram& shaderProgram, uint32_t width, uint32_t height, PassHandle &passHandle); + PipelineConfig(const ShaderProgram& shaderProgram, uint32_t width, uint32_t height, PassHandle &passHandle); ShaderProgram m_shaderProgram; uint32_t m_height; @@ -40,4 +40,4 @@ namespace vkcv { }; } -#endif //VKCV_PIPELINE_HPP +#endif //VKCV_PIPELINECONFIG_HPP diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index e39e19c3..4c2a380e 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -61,9 +61,10 @@ int main(int argc, const char** argv) { triangleShaderProgram.addShader(vkcv::ShaderProgram::ShaderStage::VERTEX, "shaders/vert.spv"); triangleShaderProgram.addShader(vkcv::ShaderProgram::ShaderStage::FRAGMENT, "shaders/frag.spv"); - const vkcv::Pipeline trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass); - vkcv::PipelineHandle trianglePipeline{}; - if (!core.createGraphicsPipeline(trianglePipelineDefinition, trianglePipeline)) { + const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass); + vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); + if (trianglePipeline.id == 0) + { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 6015363c..07e00816 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -6,6 +6,7 @@ #include "vkcv/Core.hpp" #include "PassManager.hpp" +#include "PipelineManager.hpp" namespace vkcv { @@ -465,7 +466,8 @@ namespace vkcv m_NextPipelineId(0), m_Pipelines{}, m_PipelineLayouts{}, - m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)} + m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, + m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)} {} Core::~Core() noexcept { @@ -493,194 +495,16 @@ namespace vkcv m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface()); } - bool Core::createGraphicsPipeline(const Pipeline &pipeline, PipelineHandle &handle) { - - // TODO: this search could be avoided if ShaderProgram could be queried for a specific stage - const auto shaderStageFlags = pipeline.m_shaderProgram.getShaderStages(); - const auto shaderCode = pipeline.m_shaderProgram.getShaderCode(); - std::vector<char> vertexCode; - std::vector<char> fragCode; - assert(shaderStageFlags.size() == shaderCode.size()); - for (int i = 0; i < shaderStageFlags.size(); i++) { - switch (shaderStageFlags[i]) { - case vk::ShaderStageFlagBits::eVertex: vertexCode = shaderCode[i]; break; - case vk::ShaderStageFlagBits::eFragment: fragCode = shaderCode[i]; break; - default: std::cout << "Core::createGraphicsPipeline encountered unknown shader stage" << std::endl; return false; - } - } - - const bool foundVertexCode = !vertexCode.empty(); - const bool foundFragCode = !fragCode.empty(); - const bool foundRequiredShaderCode = foundVertexCode && foundFragCode; - if (!foundRequiredShaderCode) { - std::cout << "Core::createGraphicsPipeline requires vertex and fragment shader code" << std::endl; - return false; - } - - // vertex shader stage - // TODO: store shader code as uint32_t in ShaderProgram to avoid pointer cast - vk::ShaderModuleCreateInfo vertexModuleInfo({}, vertexCode.size(), reinterpret_cast<uint32_t*>(vertexCode.data())); - vk::ShaderModule vertexModule{}; - if (m_Context.m_Device.createShaderModule(&vertexModuleInfo, nullptr, &vertexModule) != vk::Result::eSuccess) - return false; - - vk::PipelineShaderStageCreateInfo pipelineVertexShaderStageInfo( - {}, - vk::ShaderStageFlagBits::eVertex, - vertexModule, - "main", - nullptr - ); - - // fragment shader stage - vk::ShaderModuleCreateInfo fragmentModuleInfo({}, fragCode.size(), reinterpret_cast<uint32_t*>(fragCode.data())); - vk::ShaderModule fragmentModule{}; - if (m_Context.m_Device.createShaderModule(&fragmentModuleInfo, nullptr, &fragmentModule) != vk::Result::eSuccess) - { - m_Context.m_Device.destroy(vertexModule); - return false; - } - - vk::PipelineShaderStageCreateInfo pipelineFragmentShaderStageInfo( - {}, - vk::ShaderStageFlagBits::eFragment, - fragmentModule, - "main", - nullptr - ); - - // vertex input state - vk::VertexInputBindingDescription vertexInputBindingDescription(0, 12, vk::VertexInputRate::eVertex); - vk::VertexInputAttributeDescription vertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, 0); - - vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo( - {}, - 1, - &vertexInputBindingDescription, - 1, - &vertexInputAttributeDescription - ); - - // input assembly state - vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo( - {}, - vk::PrimitiveTopology::eTriangleList, - false - ); - - // viewport state - vk::Viewport viewport(0.f, 0.f, static_cast<float>(pipeline.m_width), static_cast<float>(pipeline.m_height), 0.f, 1.f); - vk::Rect2D scissor({ 0,0 }, { pipeline.m_width, pipeline.m_height }); - vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, &scissor); - - // rasterization state - vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo( - {}, - false, - false, - vk::PolygonMode::eFill, - vk::CullModeFlagBits::eNone, - vk::FrontFace::eCounterClockwise, - false, - 0.f, - 0.f, - 0.f, - 1.f - ); - - // multisample state - vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( - {}, - vk::SampleCountFlagBits::e1, - false, - 0.f, - nullptr, - false, - false - ); - - // color blend state - vk::ColorComponentFlags colorWriteMask(VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT); - vk::PipelineColorBlendAttachmentState colorBlendAttachmentState( - false, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - colorWriteMask - ); - vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( - {}, - false, - vk::LogicOp::eClear, - 1, //TODO: hardcoded to one - &colorBlendAttachmentState, - { 1.f,1.f,1.f,1.f } - ); - - // pipeline layout - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( - {}, - 0, - {}, - 0, - {} - ); - vk::PipelineLayout vkPipelineLayout{}; - if (m_Context.m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) - { - m_Context.m_Device.destroy(vertexModule); - m_Context.m_Device.destroy(fragmentModule); - return false; - } - - // graphics pipeline create - std::vector<vk::PipelineShaderStageCreateInfo> shaderStages = { pipelineVertexShaderStageInfo, pipelineFragmentShaderStageInfo }; - vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( - {}, - static_cast<uint32_t>(shaderStages.size()), - shaderStages.data(), - &pipelineVertexInputStateCreateInfo, - &pipelineInputAssemblyStateCreateInfo, - nullptr, - &pipelineViewportStateCreateInfo, - &pipelineRasterizationStateCreateInfo, - &pipelineMultisampleStateCreateInfo, - nullptr, - &pipelineColorBlendStateCreateInfo, - nullptr, - vkPipelineLayout, - m_PassManager->getVkPass(pipeline.m_passHandle), - 0, - {}, - 0 - ); - - vk::Pipeline vkPipeline{}; - if (m_Context.m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess) - { - m_Context.m_Device.destroy(vertexModule); - m_Context.m_Device.destroy(fragmentModule); - return false; - } - - m_Context.m_Device.destroy(vertexModule); - m_Context.m_Device.destroy(fragmentModule); - - m_Pipelines.push_back(vkPipeline); - m_PipelineLayouts.push_back(vkPipelineLayout); - handle.id = m_NextPipelineId++; + PipelineHandle Core::createGraphicsPipeline(const PipelineConfig &config) + { + const vk::RenderPass &pass = m_PassManager->getVkPass(config.m_passHandle); + return m_PipelineManager->createPipeline(config, pass); + } - return true; - } PassHandle Core::createPass(const PassConfig &config) { return m_PassManager->createPass(config); } + } diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp index 43674620..3184cfa2 100644 --- a/src/vkcv/PassManager.cpp +++ b/src/vkcv/PassManager.cpp @@ -56,9 +56,8 @@ namespace vkcv PassManager::~PassManager() noexcept { for(const auto &pass : m_RenderPasses) - { m_Device.destroy(pass); - } + m_RenderPasses.clear(); m_NextPassId = 1; } diff --git a/src/vkcv/Pipeline.cpp b/src/vkcv/PipelineConfig.cpp similarity index 59% rename from src/vkcv/Pipeline.cpp rename to src/vkcv/PipelineConfig.cpp index df3e6041..9fed7323 100644 --- a/src/vkcv/Pipeline.cpp +++ b/src/vkcv/PipelineConfig.cpp @@ -4,10 +4,10 @@ * @brief Pipeline class to handle shader stages */ -#include "vkcv/Pipeline.hpp" +#include "vkcv/PipelineConfig.hpp" namespace vkcv { - Pipeline::Pipeline(const ShaderProgram& shaderProgram, uint32_t width, uint32_t height, PassHandle &passHandle): + PipelineConfig::PipelineConfig(const ShaderProgram& shaderProgram, uint32_t width, uint32_t height, PassHandle &passHandle): m_shaderProgram(shaderProgram), m_height(height), m_width(width), m_passHandle(passHandle) {} } diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp new file mode 100644 index 00000000..327c443c --- /dev/null +++ b/src/vkcv/PipelineManager.cpp @@ -0,0 +1,221 @@ +#include "PipelineManager.hpp" + +namespace vkcv +{ + + PipelineManager::PipelineManager(vk::Device device) noexcept : + m_Device{device}, + m_Pipelines{}, + m_PipelineLayouts{}, + m_NextPipelineId{1} + {} + + PipelineManager::~PipelineManager() noexcept + { + for(const auto &pipeline: m_Pipelines) + m_Device.destroy(pipeline); + + for(const auto &layout : m_PipelineLayouts) + m_Device.destroy(layout); + + m_Pipelines.clear(); + m_PipelineLayouts.clear(); + m_NextPipelineId = 1; + } + + PipelineHandle PipelineManager::createPipeline(const PipelineConfig &config, const vk::RenderPass &pass) + { + + // TODO: this search could be avoided if ShaderProgram could be queried for a specific stage + const auto shaderStageFlags = config.m_shaderProgram.getShaderStages(); + const auto shaderCode = config.m_shaderProgram.getShaderCode(); + std::vector<char> vertexCode; + std::vector<char> fragCode; + assert(shaderStageFlags.size() == shaderCode.size()); + for (int i = 0; i < shaderStageFlags.size(); i++) { + switch (shaderStageFlags[i]) { + case vk::ShaderStageFlagBits::eVertex: vertexCode = shaderCode[i]; break; + case vk::ShaderStageFlagBits::eFragment: fragCode = shaderCode[i]; break; + default: std::cout << "Core::createGraphicsPipeline encountered unknown shader stage" << std::endl; + return PipelineHandle{0}; + } + } + + const bool foundVertexCode = !vertexCode.empty(); + const bool foundFragCode = !fragCode.empty(); + const bool foundRequiredShaderCode = foundVertexCode && foundFragCode; + if (!foundRequiredShaderCode) { + std::cout << "Core::createGraphicsPipeline requires vertex and fragment shader code" << std::endl; + return PipelineHandle{0}; + } + + // vertex shader stage + // TODO: store shader code as uint32_t in ShaderProgram to avoid pointer cast + vk::ShaderModuleCreateInfo vertexModuleInfo({}, vertexCode.size(), reinterpret_cast<uint32_t*>(vertexCode.data())); + vk::ShaderModule vertexModule{}; + if (m_Device.createShaderModule(&vertexModuleInfo, nullptr, &vertexModule) != vk::Result::eSuccess) + return PipelineHandle{0}; + + vk::PipelineShaderStageCreateInfo pipelineVertexShaderStageInfo( + {}, + vk::ShaderStageFlagBits::eVertex, + vertexModule, + "main", + nullptr + ); + + // fragment shader stage + vk::ShaderModuleCreateInfo fragmentModuleInfo({}, fragCode.size(), reinterpret_cast<uint32_t*>(fragCode.data())); + vk::ShaderModule fragmentModule{}; + if (m_Device.createShaderModule(&fragmentModuleInfo, nullptr, &fragmentModule) != vk::Result::eSuccess) + { + m_Device.destroy(vertexModule); + return PipelineHandle{0}; + } + + vk::PipelineShaderStageCreateInfo pipelineFragmentShaderStageInfo( + {}, + vk::ShaderStageFlagBits::eFragment, + fragmentModule, + "main", + nullptr + ); + + // vertex input state + vk::VertexInputBindingDescription vertexInputBindingDescription(0, 12, vk::VertexInputRate::eVertex); + vk::VertexInputAttributeDescription vertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, 0); + + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo( + {}, + 1, + &vertexInputBindingDescription, + 1, + &vertexInputAttributeDescription + ); + + // input assembly state + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo( + {}, + vk::PrimitiveTopology::eTriangleList, + false + ); + + // viewport state + vk::Viewport viewport(0.f, 0.f, static_cast<float>(config.m_width), static_cast<float>(config.m_height), 0.f, 1.f); + vk::Rect2D scissor({ 0,0 }, { config.m_width, config.m_height }); + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, &scissor); + + // rasterization state + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo( + {}, + false, + false, + vk::PolygonMode::eFill, + vk::CullModeFlagBits::eNone, + vk::FrontFace::eCounterClockwise, + false, + 0.f, + 0.f, + 0.f, + 1.f + ); + + // multisample state + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( + {}, + vk::SampleCountFlagBits::e1, + false, + 0.f, + nullptr, + false, + false + ); + + // color blend state + vk::ColorComponentFlags colorWriteMask(VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT); + vk::PipelineColorBlendAttachmentState colorBlendAttachmentState( + false, + vk::BlendFactor::eOne, + vk::BlendFactor::eOne, + vk::BlendOp::eAdd, + vk::BlendFactor::eOne, + vk::BlendFactor::eOne, + vk::BlendOp::eAdd, + colorWriteMask + ); + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( + {}, + false, + vk::LogicOp::eClear, + 1, //TODO: hardcoded to one + &colorBlendAttachmentState, + { 1.f,1.f,1.f,1.f } + ); + + // pipeline layout + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( + {}, + 0, + {}, + 0, + {} + ); + vk::PipelineLayout vkPipelineLayout{}; + if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) + { + m_Device.destroy(vertexModule); + m_Device.destroy(fragmentModule); + return PipelineHandle{0}; + } + + // graphics pipeline create + std::vector<vk::PipelineShaderStageCreateInfo> shaderStages = { pipelineVertexShaderStageInfo, pipelineFragmentShaderStageInfo }; + vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( + {}, + static_cast<uint32_t>(shaderStages.size()), + shaderStages.data(), + &pipelineVertexInputStateCreateInfo, + &pipelineInputAssemblyStateCreateInfo, + nullptr, + &pipelineViewportStateCreateInfo, + &pipelineRasterizationStateCreateInfo, + &pipelineMultisampleStateCreateInfo, + nullptr, + &pipelineColorBlendStateCreateInfo, + nullptr, + vkPipelineLayout, + pass, + 0, + {}, + 0 + ); + + vk::Pipeline vkPipeline{}; + if (m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess) + { + m_Device.destroy(vertexModule); + m_Device.destroy(fragmentModule); + return PipelineHandle{0}; + } + + m_Device.destroy(vertexModule); + m_Device.destroy(fragmentModule); + + m_Pipelines.push_back(vkPipeline); + m_PipelineLayouts.push_back(vkPipelineLayout); + return PipelineHandle{m_NextPipelineId++}; + } + + vk::Pipeline PipelineManager::getVkPipeline(const PipelineHandle &handle) const + { + return m_Pipelines[handle.id -1]; + } + + vk::PipelineLayout PipelineManager::getVkPipelineLayout(const PipelineHandle &handle) const + { + return m_PipelineLayouts[handle.id - 1]; + } +} \ No newline at end of file diff --git a/src/vkcv/PipelineManager.hpp b/src/vkcv/PipelineManager.hpp new file mode 100644 index 00000000..b5c0948e --- /dev/null +++ b/src/vkcv/PipelineManager.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <vulkan/vulkan.hpp> +#include <vector> +#include "vkcv/Handles.hpp" +#include "vkcv/PipelineConfig.hpp" + +namespace vkcv +{ + class PipelineManager + { + private: + vk::Device m_Device; + std::vector<vk::Pipeline> m_Pipelines; + std::vector<vk::PipelineLayout> m_PipelineLayouts; + uint64_t m_NextPipelineId; + public: + PipelineManager() = delete; // no default ctor + explicit PipelineManager(vk::Device device) noexcept; // ctor + ~PipelineManager() noexcept; // dtor + + PipelineManager(const PipelineManager &other) = delete; // copy-ctor + PipelineManager(PipelineManager &&other) = delete; // move-ctor; + + PipelineManager & operator=(const PipelineManager &other) = delete; // copy-assign op + PipelineManager & operator=(PipelineManager &&other) = delete; // move-assign op + + PipelineHandle createPipeline(const PipelineConfig &config, const vk::RenderPass &pass); + + [[nodiscard]] + vk::Pipeline getVkPipeline(const PipelineHandle &handle) const; + [[nodiscard]] + vk::PipelineLayout getVkPipelineLayout(const PipelineHandle &handle) const; + }; +} -- GitLab