From d74f8366ab948426fa60146c0d34bda26a627651 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Mon, 7 Feb 2022 11:17:55 +0100
Subject: [PATCH] Simplified shader compilation for shader programs

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 .../include/vkcv/shader/Compiler.hpp          |  7 +++
 .../src/vkcv/shader/Compiler.cpp              | 21 +++++++
 projects/bindless_textures/src/main.cpp       | 14 ++---
 projects/first_mesh/src/main.cpp              | 14 ++---
 projects/first_scene/src/main.cpp             | 13 ++---
 projects/first_triangle/src/main.cpp          | 13 ++---
 projects/wobble_bobble/src/main.cpp           | 57 ++++---------------
 7 files changed, 56 insertions(+), 83 deletions(-)

diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
index 5b119ca5..d4be7384 100644
--- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
@@ -6,10 +6,12 @@
 
 #include <vkcv/Event.hpp>
 #include <vkcv/ShaderStage.hpp>
+#include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::shader {
 	
 	typedef typename event_function<ShaderStage, const std::filesystem::path&>::type ShaderCompiledFunction;
+	typedef typename event_function<ShaderProgram&>::type ShaderProgramCompiledFunction;
 	
 	class Compiler {
 	private:
@@ -25,6 +27,11 @@ namespace vkcv::shader {
 							 const ShaderCompiledFunction& compiled,
 							 const std::filesystem::path& includePath, bool update) = 0;
 		
+		void compileProgram(ShaderProgram& program,
+							const std::unordered_map<ShaderStage, const std::filesystem::path>& stages,
+							const ShaderProgramCompiledFunction& compiled,
+							const std::filesystem::path& includePath = "", bool update = false);
+		
 		std::string getDefine(const std::string& name) const;
 		
 		void setDefine(const std::string& name, const std::string& value);
diff --git a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
index f5ec0435..1467bf22 100644
--- a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
+++ b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
@@ -3,6 +3,27 @@
 
 namespace vkcv::shader {
 	
+	void Compiler::compileProgram(ShaderProgram& program,
+								  const std::unordered_map<ShaderStage, const std::filesystem::path>& stages,
+								  const ShaderProgramCompiledFunction& compiled,
+								  const std::filesystem::path& includePath, bool update) {
+		for (const auto& stage : stages) {
+			compile(
+				stage.first,
+				stage.second,
+				[&program](ShaderStage shaderStage, const std::filesystem::path& path) {
+					program.addShader(shaderStage, path);
+				},
+				includePath,
+				update
+			);
+		}
+		
+		if (compiled) {
+			compiled(program);
+		}
+	}
+	
 	std::string Compiler::getDefine(const std::string &name) const {
 		return m_defines.at(name);
 	}
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index aa228b81..6aa0a9d6 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -123,18 +123,12 @@ int main(int argc, const char** argv) {
 	vkcv::ShaderProgram firstMeshProgram;
 	vkcv::shader::GLSLCompiler compiler;
 	
-	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"),
-					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		firstMeshProgram.addShader(shaderStage, path);
-	});
-	
-	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"),
-					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		firstMeshProgram.addShader(shaderStage, path);
-	});
+	compiler.compileProgram(firstMeshProgram, {
+		{ vkcv::ShaderStage::VERTEX, "resources/shaders/shader.vert" },
+		{ vkcv::ShaderStage::FRAGMENT, "resources/shaders/shader.frag" }
+	}, nullptr);
  
 	auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
-
 	
 	std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
 		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index b8251342..3f4378a6 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -73,18 +73,12 @@ int main(int argc, const char** argv) {
 	vkcv::ShaderProgram firstMeshProgram;
 	vkcv::shader::GLSLCompiler compiler;
 	
-	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"),
-					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		firstMeshProgram.addShader(shaderStage, path);
-	});
-	
-	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"),
-					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		firstMeshProgram.addShader(shaderStage, path);
-	});
+	compiler.compileProgram(firstMeshProgram, {
+		{ vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" },
+		{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" }
+	}, nullptr);
  
 	auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
-
 	
 	std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
 		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 3ec5b976..3dd6fc40 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -61,15 +61,10 @@ int main(int argc, const char** argv) {
 	vkcv::ShaderProgram sceneShaderProgram;
 	vkcv::shader::GLSLCompiler compiler;
 	
-	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"),
-					 [&sceneShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		sceneShaderProgram.addShader(shaderStage, path);
-	});
-	
-	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"),
-					 [&sceneShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		sceneShaderProgram.addShader(shaderStage, path);
-	});
+	compiler.compileProgram(sceneShaderProgram, {
+		{ vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" },
+		{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" }
+	}, nullptr);
 
 	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 1725b5c8..b4ba9046 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -47,15 +47,10 @@ int main(int argc, const char** argv) {
 	vkcv::ShaderProgram triangleShaderProgram;
 	vkcv::shader::GLSLCompiler compiler;
 	
-	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"),
-					 [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		 triangleShaderProgram.addShader(shaderStage, path);
-	});
-	
-	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"),
-					 [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-		triangleShaderProgram.addShader(shaderStage, path);
-	});
+	compiler.compileProgram(triangleShaderProgram, {
+		{vkcv::ShaderStage::VERTEX, "shaders/shader.vert"},
+		{ vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" }
+	}, nullptr);
 	
 	const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index f9ebf984..96c367f2 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -433,57 +433,24 @@ int main(int argc, const char **argv) {
 	
 	vkcv::ShaderProgram gfxProgramGrid;
 	
-	compiler.compile(
-			vkcv::ShaderStage::VERTEX,
-			"shaders/grid.vert",
-			[&gfxProgramGrid](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramGrid.addShader(stage, path);
-			}
-	);
-	
-	compiler.compile(
-			vkcv::ShaderStage::FRAGMENT,
-			"shaders/grid.frag",
-			[&gfxProgramGrid](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramGrid.addShader(stage, path);
-			}
-	);
+	compiler.compileProgram(gfxProgramGrid, {
+			{ vkcv::ShaderStage::VERTEX, "shaders/grid.vert" },
+			{ vkcv::ShaderStage::FRAGMENT, "shaders/grid.frag" }
+	}, nullptr);
 	
 	vkcv::ShaderProgram gfxProgramParticles;
 	
-	compiler.compile(
-			vkcv::ShaderStage::VERTEX,
-			"shaders/particle.vert",
-			[&gfxProgramParticles](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramParticles.addShader(stage, path);
-			}
-	);
-	
-	compiler.compile(
-			vkcv::ShaderStage::FRAGMENT,
-			"shaders/particle.frag",
-			[&gfxProgramParticles](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramParticles.addShader(stage, path);
-			}
-	);
+	compiler.compileProgram(gfxProgramParticles, {
+		{ vkcv::ShaderStage::VERTEX, "shaders/particle.vert" },
+		{ vkcv::ShaderStage::FRAGMENT, "shaders/particle.frag" }
+	}, nullptr);
 	
 	vkcv::ShaderProgram gfxProgramLines;
 	
-	compiler.compile(
-			vkcv::ShaderStage::VERTEX,
-			"shaders/lines.vert",
-			[&gfxProgramLines](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramLines.addShader(stage, path);
-			}
-	);
-	
-	compiler.compile(
-			vkcv::ShaderStage::FRAGMENT,
-			"shaders/lines.frag",
-			[&gfxProgramLines](vkcv::ShaderStage stage, const std::filesystem::path& path) {
-				gfxProgramLines.addShader(stage, path);
-			}
-	);
+	compiler.compileProgram(gfxProgramLines, {
+			{ vkcv::ShaderStage::VERTEX, "shaders/lines.vert" },
+			{ vkcv::ShaderStage::FRAGMENT, "shaders/lines.frag" }
+	}, nullptr);
 	
 	vkcv::PassConfig passConfigGrid ({
 		vkcv::AttachmentDescription(
-- 
GitLab