From a4cc0e029d2a5a22fb69e3248db7794f6dcacff7 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sun, 16 May 2021 19:20:47 +0200
Subject: [PATCH] [#18]Add swapchain present

---
 config/Sources.cmake                |  3 +++
 include/vkcv/Core.hpp               |  1 +
 include/vkcv/SwapChain.hpp          |  9 +++++++-
 include/vkcv/SyncResources.hpp      |  1 +
 src/vkcv/Core.cpp                   | 35 ++++++++++++++++++++++++++---
 src/vkcv/ImageLayoutTransitions.cpp | 24 ++++++++++++++++++++
 src/vkcv/ImageLayoutTransitions.hpp |  7 ++++++
 src/vkcv/Queues.cpp                 |  1 -
 src/vkcv/SwapChain.cpp              |  9 +++++---
 src/vkcv/SyncResources.cpp          |  2 ++
 10 files changed, 84 insertions(+), 8 deletions(-)
 create mode 100644 src/vkcv/ImageLayoutTransitions.cpp
 create mode 100644 src/vkcv/ImageLayoutTransitions.hpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index 784562de..ee7da418 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -42,4 +42,7 @@ set(vkcv_sources
         
         ${vkcv_source}/vkcv/Surface.hpp
         ${vkcv_source}/vkcv/Surface.cpp
+        
+        ${vkcv_source}/vkcv/ImageLayoutTransitions.hpp
+        ${vkcv_source}/vkcv/ImageLayoutTransitions.cpp
 )
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index addce8e5..60514181 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -51,6 +51,7 @@ namespace vkcv
 		CommandResources m_CommandResources;
 		SyncResources m_SyncResources;
 		VulkanQueues m_Queues;
+		uint32_t m_FrameIndex;
     public:
         /**
          * Destructor of #Core destroys the Vulkan objects contained in the core's context.
diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp
index 91d2ccbb..d5d985ec 100644
--- a/include/vkcv/SwapChain.hpp
+++ b/include/vkcv/SwapChain.hpp
@@ -12,6 +12,8 @@ namespace vkcv {
         vk::SwapchainKHR m_swapchain;
         vk::SurfaceFormatKHR m_format;
 
+		uint32_t m_ImageCount;
+
         /**
          * Constructor of a SwapChain object
          * glfw is not initialized in this class because ist must be sure that there exists a context first
@@ -20,7 +22,7 @@ namespace vkcv {
          * @param swapchain to show images in the window
          * @param format
          */
-        SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format);
+        SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount);
 
     public:
         SwapChain(const SwapChain &other) = default;
@@ -58,6 +60,11 @@ namespace vkcv {
          * Destructor of SwapChain
          */
         virtual ~SwapChain();
+
+		/**
+		 * @return number of images in swapchain
+		*/
+		uint32_t getImageCount();
     };
 
 }
diff --git a/include/vkcv/SyncResources.hpp b/include/vkcv/SyncResources.hpp
index 35e8c774..44565947 100644
--- a/include/vkcv/SyncResources.hpp
+++ b/include/vkcv/SyncResources.hpp
@@ -4,6 +4,7 @@
 namespace vkcv {
 	struct SyncResources {
 		vk::Semaphore renderFinished;
+		vk::Fence swapchainImageAcquired;
 		vk::Fence presentFinished;
 	};
 
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index da17d6ec..7321f780 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -8,6 +8,7 @@
 #include "PassManager.hpp"
 #include "PipelineManager.hpp"
 #include "Surface.hpp"
+#include "ImageLayoutTransitions.hpp"
 
 namespace vkcv
 {
@@ -278,10 +279,12 @@ namespace vkcv
 			m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
 			m_CommandResources(commandResources),
 			m_SyncResources(syncResources),
-			m_Queues(queues)
+			m_Queues(queues),
+			m_FrameIndex(0)
 	{}
 
 	Core::~Core() noexcept {
+		m_Context.getDevice().waitIdle();
 		for (auto image : m_swapchainImageViews) {
 			m_Context.m_Device.destroyImageView(image);
 		}
@@ -306,6 +309,7 @@ namespace vkcv
     }
 
 	void Core::beginFrame() {
+		m_Context.getDevice().waitIdle();	// FIMXE: this is a sin against graphics programming, but its getting late - Alex
 		const vk::CommandBufferUsageFlags beginFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
 		const vk::CommandBufferBeginInfo beginInfos(beginFlags);
 		m_CommandResources.commandBuffer.begin(beginInfos);
@@ -316,8 +320,33 @@ namespace vkcv
 	}
 
 	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);
+
 		m_CommandResources.commandBuffer.end();
-		//m_Context.
+		
+		const vk::SubmitInfo submitInfo(0, nullptr, 0, 1, &(m_CommandResources.commandBuffer), 1, &m_SyncResources.renderFinished);
+		m_Queues.graphicsQueue.submit(submitInfo);
+
+		vk::Result presentResult;
+		vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &m_swapchain.getSwapchain(), &swapchainImageIndex, &presentResult);
+		m_Queues.presentQueue.presentKHR(presentInfo);
+		if (presentResult != vk::Result::eSuccess) {
+			std::cout << "Error: swapchain present failed" << std::endl;
+		}
 	}
-
 }
diff --git a/src/vkcv/ImageLayoutTransitions.cpp b/src/vkcv/ImageLayoutTransitions.cpp
new file mode 100644
index 00000000..a64e0662
--- /dev/null
+++ b/src/vkcv/ImageLayoutTransitions.cpp
@@ -0,0 +1,24 @@
+#include "ImageLayoutTransitions.hpp"
+
+namespace vkcv {
+	void transitionImageLayoutImmediate(const vk::CommandBuffer cmdBuffer, const VkImage image,
+		const vk::ImageLayout oldLayout, const vk::ImageLayout newLayout) {
+
+		// TODO: proper src and dst masks
+		const vk::PipelineStageFlags srcStageMask = vk::PipelineStageFlagBits::eAllCommands;
+		const vk::PipelineStageFlags dstStageMask = vk::PipelineStageFlagBits::eAllCommands;
+		const vk::DependencyFlags dependecyFlags = {};
+
+		// TODO: proper src and dst masks
+		const vk::AccessFlags srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
+		const vk::AccessFlags dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
+
+		// TODO: proper aspect flags
+		const vk::ImageAspectFlags aspectFlags = vk::ImageAspectFlagBits::eColor;
+
+		const vk::ImageSubresourceRange subresourceRange(aspectFlags, 0, 1, 0, 1);
+		vk::ImageMemoryBarrier imageBarrier(srcAccessMask, dstAccessMask, oldLayout, newLayout, 0, 0, image, subresourceRange);
+
+		cmdBuffer.pipelineBarrier(srcStageMask, dstStageMask, dependecyFlags, 0, nullptr, 0, nullptr, 1, &imageBarrier, {});
+	}
+}
\ No newline at end of file
diff --git a/src/vkcv/ImageLayoutTransitions.hpp b/src/vkcv/ImageLayoutTransitions.hpp
new file mode 100644
index 00000000..284fb64c
--- /dev/null
+++ b/src/vkcv/ImageLayoutTransitions.hpp
@@ -0,0 +1,7 @@
+#pragma once
+#include <vulkan/vulkan.hpp>
+
+namespace vkcv {
+	void transitionImageLayoutImmediate(const vk::CommandBuffer cmdBuffer, const VkImage image,
+		const vk::ImageLayout oldLayout, const vk::ImageLayout newLayout);
+}
\ No newline at end of file
diff --git a/src/vkcv/Queues.cpp b/src/vkcv/Queues.cpp
index 36b3a0a0..49e992ff 100644
--- a/src/vkcv/Queues.cpp
+++ b/src/vkcv/Queues.cpp
@@ -62,7 +62,6 @@ namespace vkcv {
 		int priorityIndex = 0;
 
 		for (const auto index : familyIndexSet) {
-			outQueuePriorities->push_back(1.f);
 			const vk::DeviceQueueCreateInfo graphicsCreateInfo(flags, index, 1, &outQueuePriorities->at(priorityIndex));
 			createInfos.push_back(graphicsCreateInfo);
 			priorityIndex++;
diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp
index a9aeccea..1a8cfb79 100644
--- a/src/vkcv/SwapChain.cpp
+++ b/src/vkcv/SwapChain.cpp
@@ -2,8 +2,8 @@
 
 namespace vkcv {
 
-    SwapChain::SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format )
-        : m_surface(surface), m_swapchain(swapchain), m_format( format)
+    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)
     {}
 
     vk::SwapchainKHR SwapChain::getSwapchain() {
@@ -157,7 +157,7 @@ namespace vkcv {
 
         vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo);
 
-        return SwapChain(surface, swapchain, surfaceFormat);
+        return SwapChain(surface, swapchain, surfaceFormat, imageCount);
     }
 
 
@@ -165,4 +165,7 @@ namespace vkcv {
         // needs to be destroyed by creator
     }
 
+	uint32_t SwapChain::getImageCount() {
+		return m_ImageCount;
+	}
 }
diff --git a/src/vkcv/SyncResources.cpp b/src/vkcv/SyncResources.cpp
index 71516da8..10d582a2 100644
--- a/src/vkcv/SyncResources.cpp
+++ b/src/vkcv/SyncResources.cpp
@@ -11,6 +11,7 @@ namespace vkcv {
 		const vk::FenceCreateFlags fenceFlags = vk::FenceCreateFlagBits();
 		vk::FenceCreateInfo fenceInfo(fenceFlags);
 		resources.presentFinished = device.createFence(fenceInfo, nullptr, {});
+		resources.swapchainImageAcquired = device.createFence(fenceInfo, nullptr, {});
 
 		return resources;
 	}
@@ -18,5 +19,6 @@ namespace vkcv {
 	void destroySyncResources(const vk::Device& device, const SyncResources& resources) {
 		device.destroySemaphore(resources.renderFinished);
 		device.destroyFence(resources.presentFinished);
+		device.destroyFence(resources.swapchainImageAcquired);
 	}
 }
\ No newline at end of file
-- 
GitLab