From 5a3767f0057a47ac6366110f71083d998f5d41dc Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Mon, 19 Jul 2021 16:57:06 +0200
Subject: [PATCH] [#100] Added bilinear upscaling

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Core.hpp                         |  3 ++
 modules/upscaling/CMakeLists.txt              |  6 +++
 .../vkcv/upscaling/BilinearUpscaling.hpp      | 18 +++++++
 .../include/vkcv/upscaling/FSRUpscaling.hpp   | 12 ++---
 .../include/vkcv/upscaling/Upscaling.hpp      | 23 +++++++++
 .../src/vkcv/upscaling/BilinearUpscaling.cpp  | 13 +++++
 .../src/vkcv/upscaling/FSRUpscaling.cpp       |  2 +-
 .../src/vkcv/upscaling/Upscaling.cpp          |  8 +++
 projects/voxelization/src/main.cpp            | 14 +++++-
 src/vkcv/Core.cpp                             | 50 +++++++++++++++++++
 src/vkcv/ImageManager.hpp                     |  2 +
 11 files changed, 140 insertions(+), 11 deletions(-)
 create mode 100644 modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
 create mode 100644 modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
 create mode 100644 modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
 create mode 100644 modules/upscaling/src/vkcv/upscaling/Upscaling.cpp

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index bcca46d6..a892f0d2 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -302,5 +302,8 @@ namespace vkcv
 	
 		void recordMemoryBarrier(const CommandStreamHandle& cmdStream);
 		
+		void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
+							 SamplerFilterType filterType);
+		
     };
 }
diff --git a/modules/upscaling/CMakeLists.txt b/modules/upscaling/CMakeLists.txt
index 1625c3cc..0767e5c4 100644
--- a/modules/upscaling/CMakeLists.txt
+++ b/modules/upscaling/CMakeLists.txt
@@ -9,6 +9,12 @@ set(vkcv_upscaling_source ${PROJECT_SOURCE_DIR}/src)
 set(vkcv_upscaling_include ${PROJECT_SOURCE_DIR}/include)
 
 set(vkcv_upscaling_sources
+		${vkcv_upscaling_include}/vkcv/upscaling/Upscaling.hpp
+		${vkcv_upscaling_source}/vkcv/upscaling/Upscaling.cpp
+		
+		${vkcv_upscaling_include}/vkcv/upscaling/BilinearUpscaling.hpp
+		${vkcv_upscaling_source}/vkcv/upscaling/BilinearUpscaling.cpp
+		
 		${vkcv_upscaling_include}/vkcv/upscaling/FSRUpscaling.hpp
 		${vkcv_upscaling_source}/vkcv/upscaling/FSRUpscaling.cpp
 )
diff --git a/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
new file mode 100644
index 00000000..52124dc8
--- /dev/null
+++ b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Upscaling.hpp"
+
+namespace vkcv::upscaling {
+	
+	class BilinearUpscaling : public Upscaling {
+	private:
+	public:
+		BilinearUpscaling(Core& core);
+		
+		void recordUpscaling(const CommandStreamHandle& cmdStream,
+							 const ImageHandle& input,
+							 const ImageHandle& output) override;
+	
+	};
+
+}
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index 8492029f..2a1338b8 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
-#include <vkcv/Core.hpp>
-#include <vkcv/Handles.hpp>
+#include "Upscaling.hpp"
+
 #include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::upscaling {
@@ -28,10 +28,8 @@ namespace vkcv::upscaling {
 		uint32_t Sample [4];
 	};
 	
-	class FSRUpscaling {
+	class FSRUpscaling : public Upscaling {
 	private:
-		Core& m_core;
-		
 		PipelineHandle m_easuPipeline;
 		PipelineHandle m_rcasPipeline;
 		
@@ -61,11 +59,9 @@ namespace vkcv::upscaling {
 	public:
 		explicit FSRUpscaling(Core& core);
 		
-		~FSRUpscaling() = default;
-		
 		void recordUpscaling(const CommandStreamHandle& cmdStream,
 							 const ImageHandle& input,
-							 const ImageHandle& output);
+							 const ImageHandle& output) override;
 		
 		[[nodiscard]]
 		bool isHdrEnabled() const;
diff --git a/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
new file mode 100644
index 00000000..c44e878a
--- /dev/null
+++ b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <vkcv/Core.hpp>
+#include <vkcv/Handles.hpp>
+
+namespace vkcv::upscaling {
+	
+	class Upscaling {
+	protected:
+		Core& m_core;
+	
+	public:
+		Upscaling(Core& core);
+		
+		~Upscaling() = default;
+		
+		virtual void recordUpscaling(const CommandStreamHandle& cmdStream,
+									 const ImageHandle& input,
+							 		 const ImageHandle& output) = 0;
+	
+	};
+	
+}
diff --git a/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
new file mode 100644
index 00000000..9c36acf5
--- /dev/null
+++ b/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
@@ -0,0 +1,13 @@
+
+#include "vkcv/upscaling/BilinearUpscaling.hpp"
+
+namespace vkcv::upscaling {
+	
+	BilinearUpscaling::BilinearUpscaling(Core &core) : Upscaling(core) {}
+	
+	void BilinearUpscaling::recordUpscaling(const CommandStreamHandle &cmdStream, const ImageHandle &input,
+											const ImageHandle &output) {
+		m_core.recordBlitImage(cmdStream, input, output, SamplerFilterType::LINEAR);
+	}
+
+}
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index df7b8e8e..460a6d0b 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -152,7 +152,7 @@ namespace vkcv::upscaling {
 	}
 	
 	FSRUpscaling::FSRUpscaling(Core& core) :
-	m_core(core),
+	Upscaling(core),
 	m_easuPipeline(),
 	m_rcasPipeline(),
 	m_easuDescriptorSet(m_core.createDescriptorSet(getDescriptorBindings())),
diff --git a/modules/upscaling/src/vkcv/upscaling/Upscaling.cpp b/modules/upscaling/src/vkcv/upscaling/Upscaling.cpp
new file mode 100644
index 00000000..b0c3dee9
--- /dev/null
+++ b/modules/upscaling/src/vkcv/upscaling/Upscaling.cpp
@@ -0,0 +1,8 @@
+
+#include "vkcv/upscaling/Upscaling.hpp"
+
+namespace vkcv::upscaling {
+	
+	Upscaling::Upscaling(Core &core) : m_core(core) {}
+	
+}
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 4d8d5d1e..e7f9caa4 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -12,6 +12,7 @@
 #include "ShadowMapping.hpp"
 #include "BloomAndFlares.hpp"
 #include <vkcv/upscaling/FSRUpscaling.hpp>
+#include <vkcv/upscaling/BilinearUpscaling.hpp>
 
 int main(int argc, const char** argv) {
 	const char* applicationName = "Voxelization";
@@ -558,6 +559,10 @@ int main(int argc, const char** argv) {
 	bool fsrMipLoadBiasFlag = true;
 	bool fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag;
 	
+	vkcv::upscaling::BilinearUpscaling upscaling1 (core);
+	
+	bool bilinearUpscaling = false;
+	
 	vkcv::gui::GUI gui(core, window);
 
 	glm::vec2   lightAnglesDegree               = glm::vec2(90.f, 0.f);
@@ -826,7 +831,11 @@ int main(int argc, const char** argv) {
 		core.prepareImageForStorage(cmdStream, swapBuffer2);
 		core.prepareImageForSampling(cmdStream, swapBuffer);
 		
-		upscaling.recordUpscaling(cmdStream, swapBuffer, swapBuffer2);
+		if (bilinearUpscaling) {
+			upscaling1.recordUpscaling(cmdStream, swapBuffer, swapBuffer2);
+		} else {
+			upscaling.recordUpscaling(cmdStream, swapBuffer, swapBuffer2);
+		}
 		
 		core.prepareImageForStorage(cmdStream, swapchainInput);
 		core.prepareImageForSampling(cmdStream, swapBuffer2);
@@ -891,8 +900,9 @@ int main(int argc, const char** argv) {
 			float fsrSharpness = upscaling.getSharpness();
 			
 			ImGui::Combo("FSR Quality Mode", &fsrModeIndex, fsrModeNames.data(), fsrModeNames.size());
-			ImGui::DragFloat("FSR Sharpness", &fsrSharpness, 0.01, 0.0f, 1.0f);
+			ImGui::DragFloat("FSR Sharpness", &fsrSharpness, 0.001, 0.0f, 1.0f);
 			ImGui::Checkbox("FSR Mip Lod Bias", &fsrMipLoadBiasFlag);
+			ImGui::Checkbox("Bilinear Upscaling", &bilinearUpscaling);
 			
 			if ((fsrModeIndex >= 0) && (fsrModeIndex <= 4)) {
 				fsrMode = static_cast<vkcv::upscaling::FSRQualityMode>(fsrModeIndex);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 00b59da8..54bdab0e 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -610,4 +610,54 @@ namespace vkcv
 		}, nullptr);
 	}
 	
+	void Core::recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
+							   SamplerFilterType filterType) {
+		recordCommandsToStream(cmdStream, [&](const vk::CommandBuffer cmdBuffer) {
+			m_ImageManager->recordImageLayoutTransition(
+					src, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer
+			);
+			
+			m_ImageManager->recordImageLayoutTransition(
+					dst, vk::ImageLayout::eTransferDstOptimal, cmdBuffer
+			);
+			
+			const std::array<vk::Offset3D, 2> offsets = {
+					vk::Offset3D(0, 0, 0),
+					vk::Offset3D(0, 0, 1)
+			};
+			
+			const bool srcDepth = isDepthFormat(m_ImageManager->getImageFormat(src));
+			const bool dstDepth = isDepthFormat(m_ImageManager->getImageFormat(dst));
+			
+			const vk::ImageBlit blit = vk::ImageBlit(
+					vk::ImageSubresourceLayers(
+							srcDepth?
+							vk::ImageAspectFlagBits::eDepth :
+							vk::ImageAspectFlagBits::eColor,
+							0, 0, 1
+					),
+					offsets,
+					vk::ImageSubresourceLayers(
+							dstDepth?
+							vk::ImageAspectFlagBits::eDepth :
+							vk::ImageAspectFlagBits::eColor,
+							0, 0, 1
+					),
+					offsets
+			);
+			
+			cmdBuffer.blitImage(
+					m_ImageManager->getVulkanImage(src),
+					vk::ImageLayout::eTransferSrcOptimal,
+					m_ImageManager->getVulkanImage(dst),
+					vk::ImageLayout::eTransferDstOptimal,
+					1,
+					&blit,
+					filterType == SamplerFilterType::LINEAR?
+					vk::Filter::eLinear :
+					vk::Filter::eNearest
+			);
+		}, nullptr);
+	}
+	
 }
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 646b3211..4d994221 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -13,6 +13,8 @@
 #include "vkcv/ImageConfig.hpp"
 
 namespace vkcv {
+	
+	bool isDepthImageFormat(vk::Format format);
 
 	class ImageManager
 	{
-- 
GitLab