From a7694ca02d6292a6bce4e31b134bbbc2bf242ff3 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Sat, 17 Jul 2021 14:44:20 +0200
Subject: [PATCH] [#100] Added include path to shader compiler, allowed
 compiling glsl from string and created base for upscaling module

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 .gitmodules                                   |  3 +
 modules/CMakeLists.txt                        |  1 +
 .../include/vkcv/shader/Compiler.hpp          |  7 +-
 .../include/vkcv/shader/GLSLCompiler.hpp      |  9 ++-
 .../src/vkcv/shader/GLSLCompiler.cpp          | 65 ++++++++++++-------
 modules/upscaling/CMakeLists.txt              | 30 +++++++++
 modules/upscaling/config/FidelityFX_FSR.cmake |  6 ++
 .../include/vkcv/upscaling/FSRUpscaling.hpp   |  7 ++
 modules/upscaling/lib/FidelityFX-FSR          |  1 +
 .../src/vkcv/upscaling/FSRUpscaling.cpp       | 13 ++++
 10 files changed, 116 insertions(+), 26 deletions(-)
 create mode 100644 modules/upscaling/CMakeLists.txt
 create mode 100644 modules/upscaling/config/FidelityFX_FSR.cmake
 create mode 100644 modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
 create mode 160000 modules/upscaling/lib/FidelityFX-FSR
 create mode 100644 modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp

diff --git a/.gitmodules b/.gitmodules
index cfa32fb4..1e5c26de 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,3 +28,6 @@
 [submodule "lib/VulkanMemoryAllocator-Hpp"]
 	path = lib/VulkanMemoryAllocator-Hpp
 	url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git
+[submodule "modules/upscaling/lib/FidelityFX-FSR"]
+	path = modules/upscaling/lib/FidelityFX-FSR
+	url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 802200ad..a17dd669 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -7,3 +7,4 @@ add_subdirectory(material)
 add_subdirectory(scene)
 add_subdirectory(shader_compiler)
 add_subdirectory(testing)
+add_subdirectory(upscaling)
diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
index d7b7af71..df22f23e 100644
--- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
@@ -9,8 +9,13 @@ namespace vkcv::shader {
 	class Compiler {
 	private:
 	public:
+		virtual bool compileSource(ShaderStage shaderStage, const char* shaderSource,
+								   const ShaderCompiledFunction& compiled,
+								   const std::filesystem::path& includePath) = 0;
+		
 		virtual void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath,
-							 const ShaderCompiledFunction& compiled, bool update = false) = 0;
+							 const ShaderCompiledFunction& compiled,
+							 const std::filesystem::path& includePath, bool update) = 0;
 		
 	};
 	
diff --git a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
index 7105d93a..0a72c357 100644
--- a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
@@ -7,7 +7,7 @@
 
 namespace vkcv::shader {
 	
-	class GLSLCompiler {
+	class GLSLCompiler : Compiler {
 	private:
 	public:
 		GLSLCompiler();
@@ -20,8 +20,13 @@ namespace vkcv::shader {
 		GLSLCompiler& operator=(const GLSLCompiler& other);
 		GLSLCompiler& operator=(GLSLCompiler&& other) = default;
 		
+		bool compileSource(ShaderStage shaderStage, const char* shaderSource,
+						   const ShaderCompiledFunction& compiled,
+						   const std::filesystem::path& includePath);
+		
 		void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath,
-					 const ShaderCompiledFunction& compiled, bool update = false);
+					 const ShaderCompiledFunction& compiled,
+					 const std::filesystem::path& includePath = "", bool update = false) override;
 		
 	};
 	
diff --git a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
index ec358188..846df8b0 100644
--- a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
+++ b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
@@ -197,22 +197,21 @@ namespace vkcv::shader {
 		return true;
 	}
 	
-	void GLSLCompiler::compile(ShaderStage shaderStage, const std::filesystem::path &shaderPath,
-							   const ShaderCompiledFunction& compiled, bool update) {
+	bool GLSLCompiler::compileSource(ShaderStage shaderStage, const char* shaderSource,
+									 const ShaderCompiledFunction &compiled,
+									 const std::filesystem::path& includePath) {
 		const EShLanguage language = findShaderLanguage(shaderStage);
 		
 		if (language == EShLangCount) {
-			vkcv_log(LogLevel::ERROR, "Shader stage not supported (%s)", shaderPath.string().c_str());
-			return;
+			vkcv_log(LogLevel::ERROR, "Shader stage not supported");
+			return false;
 		}
 		
-		const std::vector<char> code = readShaderCode(shaderPath);
-		
 		glslang::TShader shader (language);
 		glslang::TProgram program;
 		
 		const char *shaderStrings [1];
-		shaderStrings[0] = code.data();
+		shaderStrings[0] = shaderSource;
 		
 		shader.setStrings(shaderStrings, 1);
 		
@@ -222,41 +221,43 @@ namespace vkcv::shader {
 		const auto messages = (EShMessages)(
 			EShMsgSpvRules |
 			EShMsgVulkanRules
-			);
+		);
 
 		std::string preprocessedGLSL;
 
 		DirStackFileIncluder includer;
-		includer.pushExternalLocalDirectory(shaderPath.parent_path().string());
+		includer.pushExternalLocalDirectory(includePath.string());
 
-		if (!shader.preprocess(&resources, 100, ENoProfile, false, false, messages, &preprocessedGLSL, includer)) {
-			vkcv_log(LogLevel::ERROR, "Shader parsing failed {\n%s\n%s\n} (%s)",
-				shader.getInfoLog(), shader.getInfoDebugLog(), shaderPath.string().c_str());
-			return;
+		if (!shader.preprocess(&resources, 100, ENoProfile,
+							   false, false,
+							   messages, &preprocessedGLSL, includer)) {
+			vkcv_log(LogLevel::ERROR, "Shader preprocessing failed {\n%s\n%s\n}",
+				shader.getInfoLog(), shader.getInfoDebugLog());
+			return false;
 		}
 		
 		const char* preprocessedCString = preprocessedGLSL.c_str();
 		shader.setStrings(&preprocessedCString, 1);
 
 		if (!shader.parse(&resources, 100, false, messages)) {
-			vkcv_log(LogLevel::ERROR, "Shader parsing failed {\n%s\n%s\n} (%s)",
-					 shader.getInfoLog(), shader.getInfoDebugLog(), shaderPath.string().c_str());
-			return;
+			vkcv_log(LogLevel::ERROR, "Shader parsing failed {\n%s\n%s\n}",
+					 shader.getInfoLog(), shader.getInfoDebugLog());
+			return false;
 		}
 		
 		program.addShader(&shader);
 		
 		if (!program.link(messages)) {
-			vkcv_log(LogLevel::ERROR, "Shader linking failed {\n%s\n%s\n} (%s)",
-					 shader.getInfoLog(), shader.getInfoDebugLog(), shaderPath.string().c_str());
-			return;
+			vkcv_log(LogLevel::ERROR, "Shader linking failed {\n%s\n%s\n}",
+					 shader.getInfoLog(), shader.getInfoDebugLog());
+			return false;
 		}
 		
 		const glslang::TIntermediate* intermediate = program.getIntermediate(language);
 		
 		if (!intermediate) {
-			vkcv_log(LogLevel::ERROR, "No valid intermediate representation (%s)", shaderPath.string().c_str());
-			return;
+			vkcv_log(LogLevel::ERROR, "No valid intermediate representation");
+			return false;
 		}
 		
 		std::vector<uint32_t> spirv;
@@ -265,8 +266,8 @@ namespace vkcv::shader {
 		const std::filesystem::path tmp_path (std::tmpnam(nullptr));
 		
 		if (!writeSpirvCode(tmp_path, spirv)) {
-			vkcv_log(LogLevel::ERROR, "Spir-V could not be written to disk (%s)", shaderPath.string().c_str());
-			return;
+			vkcv_log(LogLevel::ERROR, "Spir-V could not be written to disk");
+			return false;
 		}
 		
 		if (compiled) {
@@ -274,6 +275,24 @@ namespace vkcv::shader {
 		}
 		
 		std::filesystem::remove(tmp_path);
+		return true;
+	}
+	
+	void GLSLCompiler::compile(ShaderStage shaderStage, const std::filesystem::path &shaderPath,
+							   const ShaderCompiledFunction& compiled,
+							   const std::filesystem::path& includePath, bool update) {
+		const std::vector<char> code = readShaderCode(shaderPath);
+		bool result;
+		
+		if (!includePath.empty()) {
+			result = compileSource(shaderStage, code.data(), compiled, includePath);
+		} else {
+			result = compileSource(shaderStage, code.data(), compiled, shaderPath.parent_path());
+		}
+		
+		if (!result) {
+			vkcv_log(LogLevel::ERROR, "Shader compilation failed: (%s)", shaderPath.string().c_str());
+		}
 		
 		if (update) {
 			// TODO: Shader hot compilation during runtime
diff --git a/modules/upscaling/CMakeLists.txt b/modules/upscaling/CMakeLists.txt
new file mode 100644
index 00000000..92a4798f
--- /dev/null
+++ b/modules/upscaling/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.16)
+project(vkcv_upscaling)
+
+# setting c++ standard for the project
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+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/FSRUpscaling.hpp
+		${vkcv_upscaling_source}/vkcv/upscaling/FSRUpscaling.cpp
+)
+
+# adding source files to the project
+add_library(vkcv_upscaling STATIC ${vkcv_upscaling_sources})
+
+# Setup some path variables to load libraries
+set(vkcv_upscaling_lib lib)
+set(vkcv_upscaling_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_upscaling_lib})
+
+# Check and load GLSLANG
+include(config/FidelityFX_FSR.cmake)
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(vkcv_upscaling SYSTEM BEFORE PRIVATE ${vkcv_upscaling_includes} ${vkcv_include} ${vkcv_shader_compiler_include})
+
+# add the own include directory for public headers
+target_include_directories(vkcv_upscaling BEFORE PUBLIC ${vkcv_upscaling_include})
diff --git a/modules/upscaling/config/FidelityFX_FSR.cmake b/modules/upscaling/config/FidelityFX_FSR.cmake
new file mode 100644
index 00000000..0d34f951
--- /dev/null
+++ b/modules/upscaling/config/FidelityFX_FSR.cmake
@@ -0,0 +1,6 @@
+
+if (EXISTS "${vkcv_upscaling_lib_path}/FidelityFX-FSR")
+	list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR/ffx-fsr)
+else()
+	message(WARNING "FidelityFX-FSR is required..! Update the submodules!")
+endif ()
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
new file mode 100644
index 00000000..e8c236cf
--- /dev/null
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace vkcv::upscaling {
+
+
+
+}
diff --git a/modules/upscaling/lib/FidelityFX-FSR b/modules/upscaling/lib/FidelityFX-FSR
new file mode 160000
index 00000000..a3b53ee0
--- /dev/null
+++ b/modules/upscaling/lib/FidelityFX-FSR
@@ -0,0 +1 @@
+Subproject commit a3b53ee03ce1b23280a6d1dd7dacbb0a3f6ed9c1
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
new file mode 100644
index 00000000..ad9dbd3c
--- /dev/null
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -0,0 +1,13 @@
+
+#include "vkcv/upscaling/FSRUpscaling.hpp"
+
+#include <stdint.h>
+#include <math.h>
+
+#define A_CPU 1
+#include <ffx_a.h>
+#include <ffx_fsr1.h>
+
+namespace vkcv::upscaling {
+
+}
-- 
GitLab