From 16d6d04ac2603e486e6c9d3f1b6d94b1d89c971f Mon Sep 17 00:00:00 2001
From: Lars Hoerttrich <larshoerttrich@uni-koblenz.de>
Date: Sat, 29 May 2021 13:08:41 +0200
Subject: [PATCH] [#31] Added ImageLayoutSwitch function

---
 include/vkcv/Core.hpp         |  3 +++
 include/vkcv/Image.hpp        |  3 ++-
 include/vkcv/ImageManager.hpp |  1 +
 src/vkcv/Image.cpp            |  9 +++++--
 src/vkcv/ImageManager.cpp     | 49 ++++++++++++++++++++++++++++++++++-
 5 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 78574ffa..3bf93706 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -13,6 +13,7 @@
 #include "vkcv/PassConfig.hpp"
 #include "vkcv/Handles.hpp"
 #include "vkcv/Buffer.hpp"
+#include "vkcv/Image.hpp"
 #include "vkcv/PipelineConfig.hpp"
 #include "CommandResources.hpp"
 #include "SyncResources.hpp"
@@ -24,6 +25,7 @@ namespace vkcv
     class PassManager;
     class PipelineManager;
     class BufferManager;
+    class ImageManager;
 
 	struct SubmitInfo {
 		QueueType queueType;
@@ -60,6 +62,7 @@ namespace vkcv
         std::unique_ptr<PassManager> m_PassManager;
         std::unique_ptr<PipelineManager> m_PipelineManager;
         std::unique_ptr<BufferManager> m_BufferManager;
+        std::unique_ptr<ImageManager> m_ImageManager;
 		CommandResources m_CommandResources;
 		SyncResources m_SyncResources;
 		uint32_t m_currentSwapchainImageIndex;
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 9b632c29..3c211402 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -9,7 +9,8 @@
 namespace vkcv {
 	class Image {
 	public:
-		static Image create(ImageManager* manager);
+		static Image create(ImageManager* manager, uint32_t width, uint32_t height);
+		void switchImageLayout(vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout);
 	private:
 		ImageManager* const m_manager;
 		const uint64_t m_handle_id;
diff --git a/include/vkcv/ImageManager.hpp b/include/vkcv/ImageManager.hpp
index b2957f6a..bb4efef7 100644
--- a/include/vkcv/ImageManager.hpp
+++ b/include/vkcv/ImageManager.hpp
@@ -32,6 +32,7 @@ namespace vkcv {
 		ImageManager& operator=(const ImageManager& other) = delete;
 
 		void copyBufferToImage(vk::Buffer bufffer, vk::Image image, uint32_t width, uint32_t height);
+		void switchImageLayout(uint64_t id, vk::ImageLayout oldLayout, vk::ImageLayout newLayout);
 
 		uint64_t createImage(uint32_t width, uint32_t height);
 
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 4af32f97..887bf3b2 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -4,12 +4,17 @@
  * @brief class for image handles
  */
 #include "vkcv/Image.hpp"
+
 namespace vkcv{
-	Image Image::create(ImageManager* manager)
+	Image Image::create(ImageManager* manager, uint32_t width, uint32_t height)
 	{
-		return Image(manager, manager->createImage());
+		return Image(manager, manager->createImage(width, height));
 	}
 
+	void Image::switchImageLayout(vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
+	{
+		m_manager->switchImageLayout(m_handle_id, oldLayout, newLayout);
+	}
 	Image::Image(ImageManager* manager, uint64_t id) :
 		m_manager(manager),
 		m_handle_id(id)
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index db60960d..c99f1b8a 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -48,7 +48,7 @@ namespace vkcv {
 	{
 		vk::ImageCreateFlags createFlags;
 		vk::ImageUsageFlags imageUsageFlags = (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst);
-		vk::Format format = vk::Format::eR8G8B8A8Unorm; // als Argument variabel?
+		vk::Format format = vk::Format::eR8G8B8A8Unorm; // als Argument variabel
 
 
 		const vk::Device& device = m_core->getContext().getDevice();
@@ -89,6 +89,53 @@ namespace vkcv {
 		return id;
 	}
 
+	void ImageManager::switchImageLayout(uint64_t id, vk::ImageLayout oldLayout, vk::ImageLayout newLayout) {
+		//alternativly we could use switch case for every variable to set
+		vk::AccessFlags sourceAccessMask;
+		vk::PipelineStageFlags sourceStage;
+		vk::AccessFlags destinationAccessMask;
+		vk::PipelineStageFlags destinationStage;
+		if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) {
+			destinationAccessMask = vk::AccessFlagBits::eTransferWrite;
+			sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
+			destinationStage = vk::PipelineStageFlagBits::eTransfer;
+		}
+		else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) {
+			sourceAccessMask = vk::AccessFlagBits::eTransferWrite;
+			destinationAccessMask = vk::AccessFlagBits::eShaderRead;
+			sourceStage = vk::PipelineStageFlagBits::eTransfer;
+			destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
+		}
+		vk::ImageSubresourceRange imageSubresourceRange(vk::ImageAspectFlagBits::eColor , 0, 1, 0, 1);
+		ImageManager::Image image = m_images[id];
+		vk::ImageMemoryBarrier imageMemoryBarrier(
+			sourceAccessMask,
+			destinationAccessMask,
+			oldLayout,
+			newLayout,
+			VK_QUEUE_FAMILY_IGNORED,
+			VK_QUEUE_FAMILY_IGNORED,
+			image.m_handle,
+			imageSubresourceRange
+			);
+		SubmitInfo submitInfo;
+		submitInfo.queueType = QueueType::Present; //not sure
+		m_core->submitCommands(
+			submitInfo,
+			[sourceStage, destinationStage, imageMemoryBarrier](const vk::CommandBuffer& commandBuffer) {
+				commandBuffer.pipelineBarrier(
+					sourceStage,
+					destinationStage,
+					{},
+					nullptr,
+					nullptr,
+					imageMemoryBarrier
+				);
+			},
+			[]() {}
+		);
+	}
+
 	void ImageManager::destroyImage(uint64_t id)
 	{
 		if (id >= m_images.size()) {
-- 
GitLab