From 703c817a10fb98173b60b04d225375489eaca9f9 Mon Sep 17 00:00:00 2001
From: Mara Vogt <mvogt@uni-koblenz.de>
Date: Thu, 13 May 2021 16:38:50 +0200
Subject: [PATCH] [#11] Added Pipeline Class

added a simple pipeline class
modified core and added a create pipeline function
---
 config/Sources.cmake      |   3 +
 include/vkcv/Core.hpp     |  12 +++-
 include/vkcv/Pipeline.hpp |  30 +++++++++
 src/vkcv/Core.cpp         | 137 +++++++++++++++++++++++++++++++++++++-
 src/vkcv/Pipeline.cpp     |  13 ++++
 5 files changed, 192 insertions(+), 3 deletions(-)
 create mode 100644 include/vkcv/Pipeline.hpp
 create mode 100644 src/vkcv/Pipeline.cpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index 80fa3a09..b0c72310 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -12,4 +12,7 @@ set(vkcv_sources
 
 		${vkcv_include}/vkcv/Window.hpp
 		${vkcv_source}/vkcv/Window.cpp
+
+		${vkcv_include}/vkcv/Pipeline.hpp
+		${vkcv_source}/vkcv/Pipeline.cpp
 )
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 7a7f3be7..aa5dc52e 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -7,13 +7,13 @@
 #include <vulkan/vulkan.hpp>
 #include "vkcv/Context.hpp"
 #include "vkcv/Handles.hpp"
+#include "vkcv/Pipeline.hpp"
 
 namespace vkcv
 {
     // TODO:
     class Buffer;
     class Renderpass;
-    class Pipeline;
 
     class Core final
     {
@@ -29,6 +29,14 @@ namespace vkcv
         Core() = delete;
 
         Context m_Context;
+
+        uint64_t m_NextPipelineId;
+        std::vector<vk::Pipeline> m_Pipelines;
+        std::vector<vk::PipelineLayout> m_PipelineLayouts;
+
+        uint64_t m_NextRenderpassId;
+        std::vector<vk::RenderPass> m_Renderpasses;
+
     public:
         /**
          * Destructor of #Core destroys the Vulkan objects contained in the core's context.
@@ -94,7 +102,7 @@ namespace vkcv
         // TODO:
         BufferHandle createBuffer(const Buffer &buf);
         PassHandle createRenderPass(const Renderpass &pass) ;
-        PipelineHandle createPipeline(const Pipeline &pipeline);
+        bool createPipeline(const Pipeline &pipeline, PipelineHandle &handle);
 
     };
 }
diff --git a/include/vkcv/Pipeline.hpp b/include/vkcv/Pipeline.hpp
new file mode 100644
index 00000000..a0b5fdd2
--- /dev/null
+++ b/include/vkcv/Pipeline.hpp
@@ -0,0 +1,30 @@
+/**
+ * @authors Mara Vogt, Mark Mints
+ * @file src/vkcv/Pipeline.hpp
+ * @brief Pipeline class to handle shader stages
+ */
+
+#ifndef VKCV_PIPELINE_HPP
+#define VKCV_PIPELINE_HPP
+
+#include <vector>
+#include <cstdint>
+#include "vkcv/Handles.hpp"
+
+namespace vkcv {
+
+    class Pipeline {
+
+    public:
+        Pipeline() = delete;
+        Pipeline(const std::vector<uint32_t> &vertexCode, const std::vector<uint32_t> &fragCode, uint32_t height, uint32_t width, PassHandle &passHandle);
+
+        std::vector<uint32_t> m_vertexCode;
+        std::vector<uint32_t> m_fragCode;
+        uint32_t m_height;
+        uint32_t m_width;
+        PassHandle m_passHandle;
+    };
+
+}
+#endif //VKCV_PIPELINE_HPP
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 0c32f4e4..eb3195b4 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -268,6 +268,141 @@ namespace vkcv
     }
 
     Core::Core(Context &&context) noexcept :
-            m_Context(std::move(context))
+            m_Context(std::move(context)),
+            m_NextPipelineId(0),
+            m_Pipelines{},
+            m_PipelineLayouts{},
+            m_NextRenderpassId(0),
+            m_Renderpasses{}
     {}
+
+    bool Core::createPipeline(const Pipeline &pipeline, PipelineHandle &handle) {
+
+        // vertex shader stage
+        vk::ShaderModuleCreateInfo vertexModuleInfo({},pipeline.m_vertexCode.size(), pipeline.m_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({},pipeline.m_fragCode.size(), pipeline.m_fragCode.data());
+        vk::ShaderModule fragmentModule{};
+        if(m_Context.m_Device.createShaderModule(&fragmentModuleInfo, nullptr, &fragmentModule) != vk::Result::eSuccess){
+            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,
+                0,
+                &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){
+            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_Renderpasses[pipeline.m_passHandle.id],
+                0,
+                {},
+                0
+                );
+
+        vk::Pipeline vkPipeline{};
+        if(m_Context.m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess){
+            return false;
+        }
+
+        m_Pipelines.push_back(vkPipeline);
+        m_PipelineLayouts.push_back(vkPipelineLayout);
+        handle.id = m_NextPipelineId++;
+        return true;
+    }
 }
diff --git a/src/vkcv/Pipeline.cpp b/src/vkcv/Pipeline.cpp
new file mode 100644
index 00000000..b5078e95
--- /dev/null
+++ b/src/vkcv/Pipeline.cpp
@@ -0,0 +1,13 @@
+/**
+ * @authors Mara Vogt, Mark Mints
+ * @file src/vkcv/Pipeline.cpp
+ * @brief Pipeline class to handle shader stages
+ */
+
+#include "vkcv/Pipeline.hpp"
+
+namespace vkcv {
+
+    Pipeline::Pipeline(const std::vector<uint32_t> &vertexCode, const std::vector<uint32_t> &fragCode, uint32_t height, uint32_t width, PassHandle &passHandle):
+        m_vertexCode(vertexCode), m_fragCode(fragCode), m_height(height), m_width(width), m_passHandle(passHandle) {}
+}
-- 
GitLab