diff --git a/modules/shader_compiler/CMakeLists.txt b/modules/shader_compiler/CMakeLists.txt
index 1389e1a91866ddfaa9e273fabdc50fa0aa5dee5f..bd85c7d8e235591273d205a7c7314181b831a401 100644
--- a/modules/shader_compiler/CMakeLists.txt
+++ b/modules/shader_compiler/CMakeLists.txt
@@ -13,8 +13,14 @@ set(vkcv_shader_compiler_sources
 		${vkcv_shader_compiler_include}/vkcv/shader/Compiler.hpp
 		${vkcv_shader_compiler_source}/vkcv/shader/Compiler.cpp
 		
+		${vkcv_shader_compiler_include}/vkcv/shader/GlslangCompiler.hpp
+		${vkcv_shader_compiler_source}/vkcv/shader/GlslangCompiler.cpp
+		
 		${vkcv_shader_compiler_include}/vkcv/shader/GLSLCompiler.hpp
 		${vkcv_shader_compiler_source}/vkcv/shader/GLSLCompiler.cpp
+		
+		${vkcv_shader_compiler_include}/vkcv/shader/HLSLCompiler.hpp
+		${vkcv_shader_compiler_source}/vkcv/shader/HLSLCompiler.cpp
 )
 
 filter_headers(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include} vkcv_shader_compiler_headers)
diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
index f62190753ec440c7d732551b6229276c5a42cfc1..8096e9e22c7e7df4d48e0e658fa3e70842bb7db6 100644
--- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
@@ -41,6 +41,7 @@ namespace vkcv::shader {
         /**
          * Compile a shader from source 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] shaderSource Source of shader
          * @param[in] compiled Shader compilation event
@@ -55,20 +56,24 @@ namespace vkcv::shader {
          * 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
          */
-		virtual void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath,
+		virtual void compile(ShaderStage shaderStage,
+							 const std::filesystem::path& shaderPath,
 							 const ShaderCompiledFunction& compiled,
-							 const std::filesystem::path& includePath, bool update) = 0;
+							 const std::filesystem::path& includePath,
+							 bool update) = 0;
 		
 		/**
          * Compile a shader program from a specific map of given file paths for
          * target pipeline stages with a custom shader include path and an event
          * function called if the compilation completes.
+         *
          * @param[in,out] program Shader program
          * @param[in] stages Shader pipeline stages
          * @param[in] compiled Shader program compilation event
@@ -76,19 +81,24 @@ namespace vkcv::shader {
          * @param[in] update Flag to update shaders during runtime
          */
 		void compileProgram(ShaderProgram& program,
-							const std::unordered_map<ShaderStage, const std::filesystem::path>& stages,
+							const std::unordered_map<ShaderStage,
+							const std::filesystem::path>& stages,
 							const ShaderProgramCompiledFunction& compiled,
-							const std::filesystem::path& includePath = "", bool update = false);
+							const std::filesystem::path& includePath = "",
+							bool update = false);
 		
 		/**
          * Return the definition value of a macro for shader compilation.
+         *
          * @param[in] name Macro definition name
          * @return Macro definition value
          */
+		[[nodiscard]]
 		std::string getDefine(const std::string& name) const;
 
         /**
          * Set a macro for shader compilation.
+         *
          * @param[in] name Macro definition name
          * @param[in] value Macro definition value
          */
diff --git a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
index 0cb3a39436675e722f818643808b769189165793..48b3024fc62fc3c2f9a0975384298d82d3e8b3ea 100644
--- a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
@@ -3,7 +3,7 @@
 #include <filesystem>
 
 #include <vkcv/ShaderStage.hpp>
-#include "Compiler.hpp"
+#include "GlslangCompiler.hpp"
 
 namespace vkcv::shader {
 
@@ -22,7 +22,7 @@ namespace vkcv::shader {
     /**
      * A class to handle GLSL runtime shader compilation.
      */
-	class GLSLCompiler : public Compiler {
+	class GLSLCompiler : public GlslangCompiler {
 	private:
 		GLSLCompileTarget m_target;
 		
@@ -32,65 +32,22 @@ namespace vkcv::shader {
          *
          * @param[in] target Compile target (optional)
          */
-		GLSLCompiler(GLSLCompileTarget target = GLSLCompileTarget::UNKNOWN);
-
-        /**
-         * The copy-constructor of a runtime GLSL shader compiler instance.
-         * @param[in] other Other instance of a GLSL shader compiler instance
-         */
-		GLSLCompiler(const GLSLCompiler& other);
-
-        /**
-         * The move-constructor of a runtime GLSL shader compiler instance.
-         * @param[out] other Other instance of a GLSL shader compiler instance
-         */
-		GLSLCompiler(GLSLCompiler&& other) = default;
-
-        /**
-         * The destructor of a runtime GLSL shader compiler instance.
-         */
-		~GLSLCompiler();
-
-        /**
-         * The copy-operator of a runtime GLSL shader compiler instance.
-         * @param[in] other Other instance of a GLSL shader compiler instance
-         * @return Reference to this instance
-         */
-		GLSLCompiler& operator=(const GLSLCompiler& other);
-
-        /**
-         * The copy-operator of a runtime GLSL shader compiler instance.
-         * @param[out] other Other instance of a GLSL shader compiler instance
-         * @return Reference to this instance
-         */
-        GLSLCompiler& operator=(GLSLCompiler&& other) = default;
+		explicit GLSLCompiler(GLSLCompileTarget target = GLSLCompileTarget::UNKNOWN);
 
         /**
          * Compile a GLSL shader from source 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] shaderSource Source of shader
          * @param[in] compiled Shader compilation event
          * @param[in] includePath Include path for shaders
          * @return Result if the compilation succeeds
          */
-		bool compileSource(ShaderStage shaderStage, const char* shaderSource,
+		bool compileSource(ShaderStage shaderStage,
+						   const char* shaderSource,
 						   const ShaderCompiledFunction& compiled,
 						   const std::filesystem::path& includePath = "") override;
-
-        /**
-         * Compile a GLSL 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/include/vkcv/shader/GlslangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..79a86cf580f1de30e20e9b4e7eaff37f4896cddb
--- /dev/null
+++ b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp
@@ -0,0 +1,102 @@
+#pragma once
+
+#include <filesystem>
+
+#include <vkcv/ShaderStage.hpp>
+#include "Compiler.hpp"
+
+namespace vkcv::shader {
+	
+	/**
+     * @addtogroup vkcv_shader
+     * @{
+     */
+	
+	/**
+	 * An abstract class to handle Glslang runtime shader compilation.
+	 */
+	class GlslangCompiler : public Compiler {
+	protected:
+		/**
+		 *
+		 *
+		 * @param[in] shaderPath Filepath of shader
+		 * @param[out] spirv
+		 * @return
+		 */
+		static bool writeSpirvCode(const std::filesystem::path &shaderPath,
+								   const std::vector<uint32_t>& spirv);
+		
+		/**
+		 *
+		 *
+		 * @param[in] shaderPath Filepath of shader
+		 * @return
+		 */
+		static std::vector<char> readShaderCode(const std::filesystem::path &shaderPath);
+		
+	public:
+		/**
+		 * The constructor of a runtime Glslang shader compiler instance.
+		 *
+		 * @param[in] target Compile target (optional)
+		 */
+		GlslangCompiler();
+		
+		/**
+		 * The copy-constructor of a runtime Glslang shader compiler instance.
+		 *
+		 * @param[in] other Other instance of a Glslang shader compiler instance
+		 */
+		GlslangCompiler(const GlslangCompiler& other);
+		
+		/**
+		 * The move-constructor of a runtime Glslang shader compiler instance.
+		 *
+		 * @param[out] other Other instance of a Glslang shader compiler instance
+		 */
+		GlslangCompiler(GlslangCompiler&& other) = default;
+		
+		/**
+		 * The destructor of a runtime Glslang shader compiler instance.
+		 */
+		~GlslangCompiler();
+		
+		/**
+		 * The copy-operator of a runtime Glslang shader compiler instance.
+		 *
+		 * @param[in] other Other instance of a Glslang shader compiler instance
+		 * @return Reference to this instance
+		 */
+		GlslangCompiler& operator=(const GlslangCompiler& other);
+		
+		/**
+		 * The copy-operator of a runtime Glslang shader compiler instance.
+		 *
+		 * @param[out] other Other instance of a Glslang shader compiler instance
+		 * @return Reference to this instance
+		 */
+		GlslangCompiler& operator=(GlslangCompiler&& 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/include/vkcv/shader/HLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/HLSLCompiler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9baf2cbfdd7ad65fe5bb050e8749c39e96d83d4e
--- /dev/null
+++ b/modules/shader_compiler/include/vkcv/shader/HLSLCompiler.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <filesystem>
+
+#include <vkcv/ShaderStage.hpp>
+#include "GlslangCompiler.hpp"
+
+namespace vkcv::shader {
+	
+	/**
+	 * @addtogroup vkcv_shader
+	 * @{
+	 */
+	
+	enum class HLSLCompileTarget {
+		UNKNOWN
+	};
+	
+	/**
+	 * A class to handle HLSL runtime shader compilation.
+	 */
+	class HLSLCompiler : public GlslangCompiler {
+	private:
+		HLSLCompileTarget m_target;
+	
+	public:
+		/**
+		 * The constructor of a runtime HLSL shader compiler instance.
+		 *
+		 * @param[in] target Compile target (optional)
+		 */
+		explicit HLSLCompiler(HLSLCompileTarget target = HLSLCompileTarget::UNKNOWN);
+		
+		/**
+		 * Compile a HLSL shader from source 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] shaderSource Source of shader
+		 * @param[in] compiled Shader compilation event
+		 * @param[in] includePath Include path for shaders
+		 * @return Result if the compilation succeeds
+		 */
+		bool compileSource(ShaderStage shaderStage,
+						   const char* shaderSource,
+						   const ShaderCompiledFunction& compiled,
+						   const std::filesystem::path& includePath = "") override;
+		
+	};
+	
+	/** @} */
+	
+}
diff --git a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
index 78a82113f89bd54914471d64fee6e11700548431..0f423557be7b91999dafce089abec6b98a538228 100644
--- a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
+++ b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp
@@ -1,7 +1,6 @@
 
 #include "vkcv/shader/GLSLCompiler.hpp"
 
-#include <fstream>
 #include <sstream>
 #include <glslang/SPIRV/GlslangToSpv.h>
 #include <glslang/StandAlone/DirStackFileIncluder.h>
@@ -11,34 +10,8 @@
 
 namespace vkcv::shader {
 	
-	static uint32_t s_CompilerCount = 0;
-	
-	GLSLCompiler::GLSLCompiler(GLSLCompileTarget target) :
-		Compiler(),
-		m_target(target) {
-		if (s_CompilerCount == 0) {
-			glslang::InitializeProcess();
-		}
-		
-		s_CompilerCount++;
-	}
-	
-	GLSLCompiler::GLSLCompiler(const GLSLCompiler &other) : Compiler(other) {
-		s_CompilerCount++;
-	}
-	
-	GLSLCompiler::~GLSLCompiler() {
-		s_CompilerCount--;
-		
-		if (s_CompilerCount == 0) {
-			glslang::FinalizeProcess();
-		}
-	}
-	
-	GLSLCompiler &GLSLCompiler::operator=(const GLSLCompiler &other) {
-		s_CompilerCount++;
-		return *this;
-	}
+	GLSLCompiler::GLSLCompiler(GLSLCompileTarget target)
+	: GlslangCompiler(), m_target(target) {}
 	
 	constexpr EShLanguage findShaderLanguage(ShaderStage shaderStage) {
 		switch (shaderStage) {
@@ -168,56 +141,19 @@ namespace vkcv::shader {
 		resources.maxTaskWorkGroupSizeY_NV = 1;
 		resources.maxTaskWorkGroupSizeZ_NV = 1;
 		resources.maxMeshViewCountNV = 4;
-		resources.limits.nonInductiveForLoops = 1;
-		resources.limits.whileLoops = 1;
-		resources.limits.doWhileLoops = 1;
-		resources.limits.generalUniformIndexing = 1;
-		resources.limits.generalAttributeMatrixVectorIndexing = 1;
-		resources.limits.generalVaryingIndexing = 1;
-		resources.limits.generalSamplerIndexing = 1;
-		resources.limits.generalVariableIndexing = 1;
-		resources.limits.generalConstantMatrixVectorIndexing = 1;
-	}
-	
-	static std::vector<char> readShaderCode(const std::filesystem::path &shaderPath) {
-		std::ifstream file (shaderPath.string(), std::ios::ate);
-		
-		if (!file.is_open()) {
-			vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str());
-			return std::vector<char>{};
-		}
-		
-		std::streamsize fileSize = file.tellg();
-		std::vector<char> buffer (fileSize + 1);
-		
-		file.seekg(0);
-		file.read(buffer.data(), fileSize);
-		file.close();
-		
-		buffer[fileSize] = '\0';
-		return buffer;
+		resources.limits.nonInductiveForLoops = true;
+		resources.limits.whileLoops = true;
+		resources.limits.doWhileLoops = true;
+		resources.limits.generalUniformIndexing = true;
+		resources.limits.generalAttributeMatrixVectorIndexing = true;
+		resources.limits.generalVaryingIndexing = true;
+		resources.limits.generalSamplerIndexing = true;
+		resources.limits.generalVariableIndexing = true;
+		resources.limits.generalConstantMatrixVectorIndexing = true;
 	}
 	
-	static bool writeSpirvCode(const std::filesystem::path &shaderPath, const std::vector<uint32_t>& spirv) {
-		std::ofstream file (shaderPath.string(), std::ios::out | std::ios::binary);
-		
-		if (!file.is_open()) {
-			vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str());
-			return false;
-		}
-		
-		const auto fileSize = static_cast<std::streamsize>(
-				sizeof(uint32_t) * spirv.size()
-		);
-		
-		file.seekp(0);
-		file.write(reinterpret_cast<const char*>(spirv.data()), fileSize);
-		file.close();
-		
-		return true;
-	}
-	
-	bool GLSLCompiler::compileSource(ShaderStage shaderStage, const char* shaderSource,
+	bool GLSLCompiler::compileSource(ShaderStage shaderStage,
+									 const char* shaderSource,
 									 const ShaderCompiledFunction &compiled,
 									 const std::filesystem::path& includePath) {
 		const EShLanguage language = findShaderLanguage(shaderStage);
@@ -334,25 +270,4 @@ namespace vkcv::shader {
 		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/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ee6952b067d182a5a92a034b07d695cbac7606b
--- /dev/null
+++ b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp
@@ -0,0 +1,100 @@
+
+#include "vkcv/shader/GlslangCompiler.hpp"
+
+#include <vkcv/Logger.hpp>
+
+#include <fstream>
+#include <glslang/SPIRV/GlslangToSpv.h>
+
+namespace vkcv::shader {
+	
+	static uint32_t s_CompilerCount = 0;
+	
+	GlslangCompiler::GlslangCompiler() : Compiler() {
+		if (s_CompilerCount == 0) {
+			glslang::InitializeProcess();
+		}
+		
+		s_CompilerCount++;
+	}
+	
+	GlslangCompiler::GlslangCompiler(const GlslangCompiler &other) : Compiler(other) {
+		s_CompilerCount++;
+	}
+	
+	GlslangCompiler::~GlslangCompiler() {
+		s_CompilerCount--;
+		
+		if (s_CompilerCount == 0) {
+			glslang::FinalizeProcess();
+		}
+	}
+	
+	GlslangCompiler &GlslangCompiler::operator=(const GlslangCompiler &other) {
+		s_CompilerCount++;
+		return *this;
+	}
+	
+	bool GlslangCompiler::writeSpirvCode(const std::filesystem::path &shaderPath,
+										 const std::vector<uint32_t>& spirv) {
+		std::ofstream file (shaderPath.string(), std::ios::out | std::ios::binary);
+		
+		if (!file.is_open()) {
+			vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str());
+			return false;
+		}
+		
+		const auto fileSize = static_cast<std::streamsize>(
+				sizeof(uint32_t) * spirv.size()
+		);
+		
+		file.seekp(0);
+		file.write(reinterpret_cast<const char*>(spirv.data()), fileSize);
+		file.close();
+		
+		return true;
+	}
+	
+	std::vector<char> GlslangCompiler::readShaderCode(const std::filesystem::path &shaderPath) {
+		std::ifstream file (shaderPath.string(), std::ios::ate);
+		
+		if (!file.is_open()) {
+			vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str());
+			return std::vector<char>{};
+		}
+		
+		std::streamsize fileSize = file.tellg();
+		std::vector<char> buffer (fileSize + 1);
+		
+		file.seekg(0);
+		file.read(buffer.data(), fileSize);
+		file.close();
+		
+		buffer[fileSize] = '\0';
+		return buffer;
+	}
+	
+	void GlslangCompiler::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/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6724d008d34e45ac6cbcdde7ec523de25f2bbef1
--- /dev/null
+++ b/modules/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp
@@ -0,0 +1,265 @@
+
+#include "vkcv/shader/HLSLCompiler.hpp"
+
+#include <sstream>
+#include <glslang/SPIRV/GlslangToSpv.h>
+#include <glslang/StandAlone/DirStackFileIncluder.h>
+
+#include <vkcv/File.hpp>
+#include <vkcv/Logger.hpp>
+
+namespace vkcv::shader {
+	
+	HLSLCompiler::HLSLCompiler(HLSLCompileTarget target)
+			: GlslangCompiler(), m_target(target) {}
+	
+	constexpr EShLanguage findShaderLanguage(ShaderStage shaderStage) {
+		switch (shaderStage) {
+			case ShaderStage::VERTEX:
+				return EShLangVertex;
+			case ShaderStage::TESS_CONTROL:
+				return EShLangTessControl;
+			case ShaderStage::TESS_EVAL:
+				return EShLangTessEvaluation;
+			case ShaderStage::GEOMETRY:
+				return EShLangGeometry;
+			case ShaderStage::FRAGMENT:
+				return EShLangFragment;
+			case ShaderStage::COMPUTE:
+				return EShLangCompute;
+			case ShaderStage::TASK:
+				return EShLangTaskNV;
+			case ShaderStage::MESH:
+				return EShLangMeshNV;
+			case ShaderStage::RAY_GEN:
+				return EShLangRayGen;
+			case ShaderStage::RAY_CLOSEST_HIT:
+				return EShLangClosestHit;
+			case ShaderStage::RAY_MISS:
+				return EShLangMiss;
+			case ShaderStage::RAY_INTERSECTION:
+				return EShLangIntersect;
+			case ShaderStage::RAY_ANY_HIT:
+				return EShLangAnyHit;
+			case ShaderStage::RAY_CALLABLE:
+				return EShLangCallable;
+			default:
+				return EShLangCount;
+		}
+	}
+	
+	static void initResources(TBuiltInResource& resources) {
+		resources.maxLights = 32;
+		resources.maxClipPlanes = 6;
+		resources.maxTextureUnits = 32;
+		resources.maxTextureCoords = 32;
+		resources.maxVertexAttribs = 64;
+		resources.maxVertexUniformComponents = 4096;
+		resources.maxVaryingFloats = 64;
+		resources.maxVertexTextureImageUnits = 32;
+		resources.maxCombinedTextureImageUnits = 80;
+		resources.maxTextureImageUnits = 32;
+		resources.maxFragmentUniformComponents = 4096;
+		resources.maxDrawBuffers = 32;
+		resources.maxVertexUniformVectors = 128;
+		resources.maxVaryingVectors = 8;
+		resources.maxFragmentUniformVectors = 16;
+		resources.maxVertexOutputVectors = 16;
+		resources.maxFragmentInputVectors = 15;
+		resources.minProgramTexelOffset = -8;
+		resources.maxProgramTexelOffset = 7;
+		resources.maxClipDistances = 8;
+		resources.maxComputeWorkGroupCountX = 65535;
+		resources.maxComputeWorkGroupCountY = 65535;
+		resources.maxComputeWorkGroupCountZ = 65535;
+		resources.maxComputeWorkGroupSizeX = 1024;
+		resources.maxComputeWorkGroupSizeY = 1024;
+		resources.maxComputeWorkGroupSizeZ = 64;
+		resources.maxComputeUniformComponents = 1024;
+		resources.maxComputeTextureImageUnits = 16;
+		resources.maxComputeImageUniforms = 8;
+		resources.maxComputeAtomicCounters = 8;
+		resources.maxComputeAtomicCounterBuffers = 1;
+		resources.maxVaryingComponents = 60;
+		resources.maxVertexOutputComponents = 64;
+		resources.maxGeometryInputComponents = 64;
+		resources.maxGeometryOutputComponents = 128;
+		resources.maxFragmentInputComponents = 128;
+		resources.maxImageUnits = 8;
+		resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
+		resources.maxCombinedShaderOutputResources = 8;
+		resources.maxImageSamples = 0;
+		resources.maxVertexImageUniforms = 0;
+		resources.maxTessControlImageUniforms = 0;
+		resources.maxTessEvaluationImageUniforms = 0;
+		resources.maxGeometryImageUniforms = 0;
+		resources.maxFragmentImageUniforms = 8;
+		resources.maxCombinedImageUniforms = 8;
+		resources.maxGeometryTextureImageUnits = 16;
+		resources.maxGeometryOutputVertices = 256;
+		resources.maxGeometryTotalOutputComponents = 1024;
+		resources.maxGeometryUniformComponents = 1024;
+		resources.maxGeometryVaryingComponents = 64;
+		resources.maxTessControlInputComponents = 128;
+		resources.maxTessControlOutputComponents = 128;
+		resources.maxTessControlTextureImageUnits = 16;
+		resources.maxTessControlUniformComponents = 1024;
+		resources.maxTessControlTotalOutputComponents = 4096;
+		resources.maxTessEvaluationInputComponents = 128;
+		resources.maxTessEvaluationOutputComponents = 128;
+		resources.maxTessEvaluationTextureImageUnits = 16;
+		resources.maxTessEvaluationUniformComponents = 1024;
+		resources.maxTessPatchComponents = 120;
+		resources.maxPatchVertices = 32;
+		resources.maxTessGenLevel = 64;
+		resources.maxViewports = 16;
+		resources.maxVertexAtomicCounters = 0;
+		resources.maxTessControlAtomicCounters = 0;
+		resources.maxTessEvaluationAtomicCounters = 0;
+		resources.maxGeometryAtomicCounters = 0;
+		resources.maxFragmentAtomicCounters = 8;
+		resources.maxCombinedAtomicCounters = 8;
+		resources.maxAtomicCounterBindings = 1;
+		resources.maxVertexAtomicCounterBuffers = 0;
+		resources.maxTessControlAtomicCounterBuffers = 0;
+		resources.maxTessEvaluationAtomicCounterBuffers = 0;
+		resources.maxGeometryAtomicCounterBuffers = 0;
+		resources.maxFragmentAtomicCounterBuffers = 1;
+		resources.maxCombinedAtomicCounterBuffers = 1;
+		resources.maxAtomicCounterBufferSize = 16384;
+		resources.maxTransformFeedbackBuffers = 4;
+		resources.maxTransformFeedbackInterleavedComponents = 64;
+		resources.maxCullDistances = 8;
+		resources.maxCombinedClipAndCullDistances = 8;
+		resources.maxSamples = 4;
+		resources.maxMeshOutputVerticesNV = 256;
+		resources.maxMeshOutputPrimitivesNV = 512;
+		resources.maxMeshWorkGroupSizeX_NV = 32;
+		resources.maxMeshWorkGroupSizeY_NV = 1;
+		resources.maxMeshWorkGroupSizeZ_NV = 1;
+		resources.maxTaskWorkGroupSizeX_NV = 32;
+		resources.maxTaskWorkGroupSizeY_NV = 1;
+		resources.maxTaskWorkGroupSizeZ_NV = 1;
+		resources.maxMeshViewCountNV = 4;
+		resources.limits.nonInductiveForLoops = true;
+		resources.limits.whileLoops = true;
+		resources.limits.doWhileLoops = true;
+		resources.limits.generalUniformIndexing = true;
+		resources.limits.generalAttributeMatrixVectorIndexing = true;
+		resources.limits.generalVaryingIndexing = true;
+		resources.limits.generalSamplerIndexing = true;
+		resources.limits.generalVariableIndexing = true;
+		resources.limits.generalConstantMatrixVectorIndexing = true;
+	}
+	
+	bool HLSLCompiler::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");
+			return false;
+		}
+		
+		glslang::TShader shader (language);
+		switch (m_target) {
+			default:
+				break;
+		}
+		
+		glslang::TProgram program;
+		std::string source (shaderSource);
+		
+		if (!m_defines.empty()) {
+			std::ostringstream defines;
+			for (const auto& define : m_defines) {
+				defines << "#define " << define.first << " " << define.second << std::endl;
+			}
+			
+			size_t pos = source.find("#version") + 8;
+			if (pos >= source.length()) {
+				pos = 0;
+			}
+			
+			const size_t epos = source.find_last_of("#extension", pos) + 10;
+			if (epos < source.length()) {
+				pos = epos;
+			}
+			
+			const auto defines_str = defines.str();
+			
+			pos = source.find('\n', pos) + 1;
+			source = source.insert(pos, defines_str);
+		}
+		
+		const char *shaderStrings [1];
+		shaderStrings[0] = source.c_str();
+		
+		shader.setStrings(shaderStrings, 1);
+		
+		TBuiltInResource resources = {};
+		initResources(resources);
+		
+		const auto messages = (EShMessages)(
+				EShMsgSpvRules |
+				EShMsgVulkanRules
+		);
+		
+		std::string preprocessedHLSL;
+		
+		DirStackFileIncluder includer;
+		includer.pushExternalLocalDirectory(includePath.string());
+		
+		if (!shader.preprocess(&resources, 100, ENoProfile,
+							   false, false,
+							   messages, &preprocessedHLSL, includer)) {
+			vkcv_log(LogLevel::ERROR, "Shader preprocessing failed {\n%s\n%s\n}",
+					 shader.getInfoLog(), shader.getInfoDebugLog());
+			return false;
+		}
+		
+		const char* preprocessedCString = preprocessedHLSL.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}",
+					 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}",
+					 shader.getInfoLog(), shader.getInfoDebugLog());
+			return false;
+		}
+		
+		const glslang::TIntermediate* intermediate = program.getIntermediate(language);
+		
+		if (!intermediate) {
+			vkcv_log(LogLevel::ERROR, "No valid intermediate representation");
+			return false;
+		}
+		
+		std::vector<uint32_t> spirv;
+		glslang::GlslangToSpv(*intermediate, spirv);
+		
+		const std::filesystem::path tmp_path = generateTemporaryFilePath();
+		
+		if (!writeSpirvCode(tmp_path, spirv)) {
+			vkcv_log(LogLevel::ERROR, "Spir-V could not be written to disk");
+			return false;
+		}
+		
+		if (compiled) {
+			compiled(shaderStage, tmp_path);
+		}
+		
+		std::filesystem::remove(tmp_path);
+		return true;
+	}
+	
+}