From a7496fd7b11461f0e37a12a1b518e03ada92e4b5 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Tue, 23 Jul 2024 02:19:48 +0200
Subject: [PATCH] Add generic SlangCompiler class

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 modules/shader_compiler/CMakeLists.txt        |  3 +
 .../include/vkcv/shader/SlangCompiler.hpp     | 81 +++++++++++++++++++
 .../src/vkcv/shader/SlangCompiler.cpp         | 67 +++++++++++++++
 3 files changed, 151 insertions(+)
 create mode 100644 modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp
 create mode 100644 modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp

diff --git a/modules/shader_compiler/CMakeLists.txt b/modules/shader_compiler/CMakeLists.txt
index ed1b7abd..b7452fe1 100644
--- a/modules/shader_compiler/CMakeLists.txt
+++ b/modules/shader_compiler/CMakeLists.txt
@@ -30,6 +30,9 @@ set(vkcv_shader_compiler_sources
 
 		${vkcv_shader_compiler_include}/vkcv/shader/LLVMCompiler.hpp
 		${vkcv_shader_compiler_source}/vkcv/shader/LLVMCompiler.cpp
+
+		${vkcv_shader_compiler_include}/vkcv/shader/SlangCompiler.hpp
+		${vkcv_shader_compiler_source}/vkcv/shader/SlangCompiler.cpp
 )
 
 filter_headers(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include} vkcv_shader_compiler_headers)
diff --git a/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp
new file mode 100644
index 00000000..3c13bbd1
--- /dev/null
+++ b/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <filesystem>
+
+#include <vkcv/ShaderStage.hpp>
+#include "Compiler.hpp"
+
+namespace vkcv::shader {
+	
+  /**
+    * @addtogroup vkcv_shader
+    * @{
+    */
+	
+	/**
+	 * An abstract class to handle Slang runtime shader compilation.
+	 */
+	class SlangCompiler : public Compiler {
+	public:
+		/**
+		 * The constructor of a runtime Slang shader compiler instance.
+		 */
+		SlangCompiler();
+		
+		/**
+		 * The copy-constructor of a runtime Slang shader compiler instance.
+		 *
+		 * @param[in] other Other instance of a Slang shader compiler instance
+		 */
+		SlangCompiler(const SlangCompiler& other);
+		
+		/**
+		 * The move-constructor of a runtime Slang shader compiler instance.
+		 *
+		 * @param[out] other Other instance of a Slang shader compiler instance
+		 */
+		SlangCompiler(SlangCompiler&& other) = default;
+		
+		/**
+		 * The destructor of a runtime Slang shader compiler instance.
+		 */
+		~SlangCompiler();
+		
+		/**
+		 * The copy-operator of a runtime Slang shader compiler instance.
+		 *
+		 * @param[in] other Other instance of a Slang shader compiler instance
+		 * @return Reference to this instance
+		 */
+		SlangCompiler& operator=(const SlangCompiler& other);
+		
+		/**
+		 * The copy-operator of a runtime Slang shader compiler instance.
+		 *
+		 * @param[out] other Other instance of a Slang shader compiler instance
+		 * @return Reference to this instance
+		 */
+		SlangCompiler& operator=(SlangCompiler&& other) = default;
+		
+		/**
+         * Compile a shader from a specific file path for a target stage with
+         * a custom shader include path and an event function called if the
+         * compilation completes.
+         *
+         * @param[in] shaderStage Shader pipeline stage
+         * @param[in] shaderPath Filepath of shader
+         * @param[in] compiled Shader compilation event
+         * @param[in] includePath Include path for shaders
+         * @param[in] update Flag to update shaders during runtime
+         */
+		void compile(ShaderStage shaderStage,
+					 const std::filesystem::path& shaderPath,
+					 const ShaderCompiledFunction& compiled,
+					 const std::filesystem::path& includePath = "",
+					 bool update = false) override;
+		
+	};
+	
+	/** @} */
+
+}
diff --git a/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp
new file mode 100644
index 00000000..ffc295b7
--- /dev/null
+++ b/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp
@@ -0,0 +1,67 @@
+
+#include "vkcv/shader/SlangCompiler.hpp"
+
+#include <vkcv/File.hpp>
+#include <vkcv/Logger.hpp>
+
+#include <slang.h>
+
+namespace vkcv::shader {
+	
+	static uint32_t s_CompilerCount = 0;
+  static slang::IGlobalSession* s_GlobalSession = nullptr;
+	
+	SlangCompiler::SlangCompiler() : Compiler() {
+		if (s_CompilerCount == 0) {
+      slang::createGlobalSession(&s_GlobalSession);
+		}
+		
+		s_CompilerCount++;
+	}
+	
+	SlangCompiler::SlangCompiler(const SlangCompiler &other) : Compiler(other) {
+		s_CompilerCount++;
+	}
+	
+	SlangCompiler::~SlangCompiler() {
+		s_CompilerCount--;
+
+    if ((s_CompilerCount == 0) && (s_GlobalSession != nullptr)) {
+      spDestroySession(s_GlobalSession);
+      s_GlobalSession = nullptr;
+    }
+	}
+	
+	SlangCompiler &SlangCompiler::operator=(const SlangCompiler &other) {
+		s_CompilerCount++;
+		return *this;
+	}
+	
+	void SlangCompiler::compile(ShaderStage shaderStage,
+								  const std::filesystem::path &shaderPath,
+								  const ShaderCompiledFunction &compiled,
+								  const std::filesystem::path &includePath,
+								  bool update) {
+		std::string shaderCode;
+		bool result = readTextFromFile(shaderPath, shaderCode);
+		
+		if (!result) {
+			vkcv_log(LogLevel::ERROR, "Loading shader failed: (%s)", shaderPath.string().c_str());
+		}
+		
+		if (!includePath.empty()) {
+			result = compileSource(shaderStage, shaderCode, compiled, includePath);
+		} else {
+			result = compileSource(shaderStage, shaderCode, 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
+		}
+	}
+	
+}
-- 
GitLab