From 7890faf3685b7fdcb41038e49bce9d503e383c55 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sun, 16 May 2021 20:48:39 +0200
Subject: [PATCH] [#18]Do yellow nice (now executing renderpass)

---
 config/Sources.cmake                 |  3 ++
 include/vkcv/Core.hpp                | 11 ++++-
 include/vkcv/PassConfig.hpp          | 15 ++++---
 include/vkcv/SwapChain.hpp           |  3 ++
 projects/first_triangle/src/main.cpp |  5 ++-
 src/vkcv/Core.cpp                    | 62 +++++++++++++++++++---------
 src/vkcv/Framebuffer.cpp             | 11 +++++
 src/vkcv/Framebuffer.hpp             |  7 ++++
 src/vkcv/PassConfig.cpp              | 23 ++++++-----
 src/vkcv/PassManager.cpp             |  7 +---
 src/vkcv/SwapChain.cpp               |  6 ++-
 11 files changed, 108 insertions(+), 45 deletions(-)
 create mode 100644 src/vkcv/Framebuffer.cpp
 create mode 100644 src/vkcv/Framebuffer.hpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index ee7da418..dce76b39 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -45,4 +45,7 @@ set(vkcv_sources
         
         ${vkcv_source}/vkcv/ImageLayoutTransitions.hpp
         ${vkcv_source}/vkcv/ImageLayoutTransitions.cpp
+        
+        ${vkcv_source}/vkcv/Framebuffer.hpp
+        ${vkcv_source}/vkcv/Framebuffer.cpp
 )
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 60514181..b7b553d7 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -40,6 +40,9 @@ namespace vkcv
         // explicit destruction of default constructor
         Core() = delete;
 
+		uint32_t acquireSwapchainImage();
+		void destroyTemporaryFramebuffers();
+
         Context m_Context;
 
         SwapChain m_swapchain;
@@ -51,7 +54,8 @@ namespace vkcv
 		CommandResources m_CommandResources;
 		SyncResources m_SyncResources;
 		VulkanQueues m_Queues;
-		uint32_t m_FrameIndex;
+		uint32_t m_currentSwapchainImageIndex;
+		std::vector<vk::Framebuffer> m_TemporaryFramebuffers;
     public:
         /**
          * Destructor of #Core destroys the Vulkan objects contained in the core's context.
@@ -146,11 +150,14 @@ namespace vkcv
 		/**
 		 * @brief render a beautiful triangle
 		*/
-		void renderTriangle();
+		void renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle,
+			const int width, const int height);
 
 		/**
 		 * @brief end recording and present image
 		*/
 		void endFrame();
+
+		vk::Format getSwapchainImageFormat();
     };
 }
diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp
index b0ded8f5..b8e80c67 100644
--- a/include/vkcv/PassConfig.hpp
+++ b/include/vkcv/PassConfig.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <vector>
+#include <vulkan/vulkan.hpp>
 
 namespace vkcv
 {
@@ -32,11 +33,13 @@ namespace vkcv
     struct AttachmentDescription
     {
         AttachmentDescription() = delete;
-        AttachmentDescription(AttachmentLayout initial,
-                              AttachmentLayout in_pass,
-                              AttachmentLayout final,
-                              AttachmentOperation store_op,
-                              AttachmentOperation load_op) noexcept;
+        AttachmentDescription(
+			AttachmentLayout initial,
+			AttachmentLayout in_pass,
+			AttachmentLayout final,
+			AttachmentOperation store_op,
+			AttachmentOperation load_op,
+			vk::Format format) noexcept;
 
         AttachmentLayout layout_initial;
         AttachmentLayout layout_in_pass;
@@ -44,6 +47,8 @@ namespace vkcv
 
         AttachmentOperation store_operation;
         AttachmentOperation load_operation;
+
+		vk::Format format;
     };
 
     struct PassConfig
diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp
index 1d2f4710..351905fa 100644
--- a/include/vkcv/SwapChain.hpp
+++ b/include/vkcv/SwapChain.hpp
@@ -13,6 +13,7 @@ namespace vkcv {
         vk::SurfaceFormatKHR m_format;
 
 		uint32_t m_ImageCount;
+		vk::Format m_ImageFormat;
 
         /**
          * Constructor of a SwapChain object
@@ -65,6 +66,8 @@ namespace vkcv {
 		 * @return number of images in swapchain
 		*/
 		uint32_t getImageCount();
+
+		vk::Format getImageFormat();
     };
 
 }
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 0e567db7..fb9d764c 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -46,7 +46,8 @@ int main(int argc, const char** argv) {
 		vkcv::AttachmentLayout::COLOR_ATTACHMENT,
 		vkcv::AttachmentLayout::PRESENTATION,
 		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR);
+		vkcv::AttachmentOperation::CLEAR,
+		core.getSwapchainImageFormat());
 
 	vkcv::PassConfig trianglePassDefinition({present_color_attachment});
 	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
@@ -88,7 +89,7 @@ int main(int argc, const char** argv) {
 	while (window.isWindowOpen())
 	{
 		core.beginFrame();
-	    // core.execute(trianglePass, trianglePipeline, triangleModel);
+	    core.renderTriangle(trianglePass, trianglePipeline, windowWidth, windowHeight);
 	    core.endFrame();
 
 		window.pollEvents();
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 70f0425f..3c113a7a 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -9,6 +9,7 @@
 #include "PipelineManager.hpp"
 #include "Surface.hpp"
 #include "ImageLayoutTransitions.hpp"
+#include "Framebuffer.hpp"
 
 namespace vkcv
 {
@@ -279,8 +280,7 @@ namespace vkcv
 			m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
 			m_CommandResources(commandResources),
 			m_SyncResources(syncResources),
-			m_Queues(queues),
-			m_FrameIndex(0)
+			m_Queues(queues)
 	{}
 
 	Core::~Core() noexcept {
@@ -291,6 +291,7 @@ namespace vkcv
 
 		destroyCommandResources(m_Context.getDevice(), m_CommandResources);
 		destroySyncResources(m_Context.getDevice(), m_SyncResources);
+		destroyTemporaryFramebuffers();
 
 		m_Context.m_Device.destroySwapchainKHR(m_swapchain.getSwapchain());
 		m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface());
@@ -308,34 +309,50 @@ namespace vkcv
         return m_PassManager->createPass(config);
     }
 
+	uint32_t Core::acquireSwapchainImage() {
+		uint32_t index;
+		m_Context.getDevice().acquireNextImageKHR(m_swapchain.getSwapchain(), 0, nullptr,
+			m_SyncResources.swapchainImageAcquired, &index, {});
+		const uint64_t timeoutPeriodNs = 1000;	// TODO: think if is adequate
+		m_Context.getDevice().waitForFences(m_SyncResources.swapchainImageAcquired, true, timeoutPeriodNs);
+		m_Context.getDevice().resetFences(m_SyncResources.swapchainImageAcquired);
+		return index;
+	}
+
+	void Core::destroyTemporaryFramebuffers() {
+		for (const vk::Framebuffer f : m_TemporaryFramebuffers) {
+			m_Context.getDevice().destroyFramebuffer(f);
+		}
+		m_TemporaryFramebuffers.clear();
+	}
+
 	void Core::beginFrame() {
+		m_currentSwapchainImageIndex = acquireSwapchainImage();
 		m_Context.getDevice().waitIdle();	// FIMXE: this is a sin against graphics programming, but its getting late - Alex
+		destroyTemporaryFramebuffers();
 		const vk::CommandBufferUsageFlags beginFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
 		const vk::CommandBufferBeginInfo beginInfos(beginFlags);
 		m_CommandResources.commandBuffer.begin(beginInfos);
 	}
 
-	void Core::renderTriangle() {
-
+	void Core::renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, 
+		const int width, const int height) {
+		const vk::RenderPass renderpass = m_PassManager->getVkPass(renderpassHandle);
+		const std::array<float, 4> clearColor = { 1.f, 1.f, 0.f, 1.f };
+		const vk::ClearValue clearValues(clearColor);
+		const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height));
+		const vk::ImageView imageView = m_swapchainImageViews[m_currentSwapchainImageIndex];
+		const vk::Framebuffer framebuffer = createFramebuffer(m_Context.getDevice(), renderpass, width, height, imageView);
+		m_TemporaryFramebuffers.push_back(framebuffer);
+		const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, 1, &clearValues);
+		const vk::SubpassContents subpassContents = {};
+		m_CommandResources.commandBuffer.beginRenderPass(beginInfo, subpassContents, {});
+		m_CommandResources.commandBuffer.endRenderPass();
 	}
 
 	void Core::endFrame() {
-
-		uint32_t swapchainImageIndex;
-		m_Context.getDevice().acquireNextImageKHR(m_swapchain.getSwapchain(), 0, nullptr, 
-			m_SyncResources.swapchainImageAcquired, &swapchainImageIndex, {});
-		const uint64_t timeoutPeriodNs = 1000;	// TODO: think if is adequate
-		m_Context.getDevice().waitForFences(m_SyncResources.swapchainImageAcquired, true, timeoutPeriodNs);
-		m_Context.getDevice().resetFences(m_SyncResources.swapchainImageAcquired);
-
 		const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain());
-		const vk::Image presentImage = swapchainImages[swapchainImageIndex];
-
-		transitionImageLayoutImmediate(
-			m_CommandResources.commandBuffer, 
-			presentImage, 
-			vk::ImageLayout::eUndefined, 
-			vk::ImageLayout::ePresentSrcKHR);
+		const vk::Image presentImage = swapchainImages[m_currentSwapchainImageIndex];
 
 		m_CommandResources.commandBuffer.end();
 		
@@ -344,10 +361,15 @@ namespace vkcv
 
 		vk::Result presentResult;
 		const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain();
-		const vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &swapchain, &swapchainImageIndex, &presentResult);
+		const vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &swapchain, 
+			&m_currentSwapchainImageIndex, &presentResult);
 		m_Queues.presentQueue.presentKHR(presentInfo);
 		if (presentResult != vk::Result::eSuccess) {
 			std::cout << "Error: swapchain present failed" << std::endl;
 		}
 	}
+
+	vk::Format Core::getSwapchainImageFormat() {
+		return m_swapchain.getImageFormat();
+	}
 }
diff --git a/src/vkcv/Framebuffer.cpp b/src/vkcv/Framebuffer.cpp
new file mode 100644
index 00000000..3b3e8000
--- /dev/null
+++ b/src/vkcv/Framebuffer.cpp
@@ -0,0 +1,11 @@
+#include "Framebuffer.hpp"
+
+namespace vkcv {
+	vk::Framebuffer createFramebuffer(const vk::Device device, const vk::RenderPass renderpass, 
+		const int width, const int height, const vk::ImageView imageView) {
+		const vk::FramebufferCreateFlags flags = {};
+		const uint32_t attachmentCount = 1;	// TODO: proper value
+		const vk::FramebufferCreateInfo createInfo(flags, renderpass, attachmentCount, &imageView, width, height, 1);
+		return device.createFramebuffer(createInfo, nullptr, {});
+	}
+}
\ No newline at end of file
diff --git a/src/vkcv/Framebuffer.hpp b/src/vkcv/Framebuffer.hpp
new file mode 100644
index 00000000..7d5d718a
--- /dev/null
+++ b/src/vkcv/Framebuffer.hpp
@@ -0,0 +1,7 @@
+#pragma once
+#include <vulkan/vulkan.hpp>
+
+namespace vkcv{
+	vk::Framebuffer createFramebuffer(const vk::Device device, const vk::RenderPass renderpass,
+		const int width, const int height, const vk::ImageView imageView);
+}
\ No newline at end of file
diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp
index a0c22896..ef07d3ee 100644
--- a/src/vkcv/PassConfig.cpp
+++ b/src/vkcv/PassConfig.cpp
@@ -4,16 +4,19 @@
 
 namespace vkcv
 {
-    AttachmentDescription::AttachmentDescription(AttachmentLayout initial,
-                                                 AttachmentLayout in_pass,
-                                                 AttachmentLayout final,
-                                                 AttachmentOperation store_op,
-                                                 AttachmentOperation load_op) noexcept :
-    layout_initial{initial},
-    layout_in_pass{in_pass},
-    layout_final{final},
-    store_operation{store_op},
-    load_operation{load_op}
+    AttachmentDescription::AttachmentDescription(
+		AttachmentLayout initial,
+		AttachmentLayout in_pass,
+		AttachmentLayout final,
+		AttachmentOperation store_op,
+		AttachmentOperation load_op,
+		vk::Format format) noexcept :
+	layout_initial{initial},
+	layout_in_pass{in_pass},
+	layout_final{final},
+	store_operation{store_op},
+	load_operation{load_op},
+	format(format)
     {};
 
     PassConfig::PassConfig(std::vector<AttachmentDescription> attachments) noexcept :
diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp
index 3184cfa2..820bf3ff 100644
--- a/src/vkcv/PassManager.cpp
+++ b/src/vkcv/PassManager.cpp
@@ -76,19 +76,16 @@ namespace vkcv
         for (uint32_t i = 0; i < config.attachments.size(); i++)
         {
             // TODO: Renderpass struct should hold proper format information
-            vk::Format format;
+            vk::Format format = config.attachments[i].format;
 
             if (config.attachments[i].layout_in_pass == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT)
             {
-                format = vk::Format::eD16Unorm; // depth attachments;
-
                 depthAttachmentReference.attachment = i;
                 depthAttachmentReference.layout = getVkLayoutFromAttachLayout(config.attachments[i].layout_in_pass);
                 pDepthAttachment = &depthAttachmentReference;
             }
             else
             {
-                format = vk::Format::eB8G8R8A8Srgb; // color attachments, compatible with swapchain
                 vk::AttachmentReference attachmentRef(i, getVkLayoutFromAttachLayout(config.attachments[i].layout_in_pass));
                 colorAttachmentReferences.push_back(attachmentRef);
             }
@@ -97,7 +94,7 @@ namespace vkcv
                                                      format,
                                                      vk::SampleCountFlagBits::e1,
                                                      getVKLoadOpFromAttachOp(config.attachments[i].load_operation),
-                                                     getVkStoreOpFromAttachOp(config.attachments[i].load_operation),
+                                                     getVkStoreOpFromAttachOp(config.attachments[i].store_operation),
                                                      vk::AttachmentLoadOp::eDontCare,
                                                      vk::AttachmentStoreOp::eDontCare,
                                                      getVkLayoutFromAttachLayout(config.attachments[i].layout_initial),
diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp
index 3483ae37..ef182bcd 100644
--- a/src/vkcv/SwapChain.cpp
+++ b/src/vkcv/SwapChain.cpp
@@ -3,7 +3,7 @@
 namespace vkcv {
 
     SwapChain::SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount)
-        : m_surface(surface), m_swapchain(swapchain), m_format( format), m_ImageCount(imageCount)
+        : m_surface(surface), m_swapchain(swapchain), m_format( format), m_ImageCount(imageCount), m_ImageFormat(format.format)
     {}
 
     const vk::SwapchainKHR& SwapChain::getSwapchain() const {
@@ -168,4 +168,8 @@ namespace vkcv {
 	uint32_t SwapChain::getImageCount() {
 		return m_ImageCount;
 	}
+
+	vk::Format SwapChain::getImageFormat() {
+		return m_ImageFormat;
+	}
 }
-- 
GitLab