diff --git a/CMakeLists.txt b/CMakeLists.txt
index da150fcbeafec3be555d4bbefdab37dbdedf277f..2a0858b970dead0233261c4f3c126a0bf64732f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,9 +34,9 @@ set(vkcv_flags ${CMAKE_CXX_FLAGS})
 if (vkcv_build_debug)
 	if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 		#set(vkcv_flags ${vkcv_flags} " -Weverything")
-		set(vkcv_flags ${vkcv_flags} " -Wextra -Wall")
+		set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -Wno-unused-parameter")
 	elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-		set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic")
+		set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic -Wno-unused-parameter")
 	else()
 		set(vkcv_flags ${vkcv_flags} " -W4")
 	endif()
diff --git a/config/Sources.cmake b/config/Sources.cmake
index 7f94800e45b70b19158481f52a3d696588737297..606dc4c97d62ed284d5967707e07237ebd2f7580 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -51,11 +51,15 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/ShaderProgram.hpp
 		${vkcv_source}/vkcv/ShaderProgram.cpp
 
-		${vkcv_include}/vkcv/PipelineConfig.hpp
+		${vkcv_include}/vkcv/GraphicsPipelineConfig.hpp
+		${vkcv_include}/vkcv/ComputePipelineConfig.hpp
+
+		${vkcv_source}/vkcv/ComputePipelineManager.hpp
+		${vkcv_source}/vkcv/ComputePipelineManager.cpp
+
+		${vkcv_source}/vkcv/GraphicsPipelineManager.hpp
+		${vkcv_source}/vkcv/GraphicsPipelineManager.cpp
 
-		${vkcv_source}/vkcv/PipelineManager.hpp
-		${vkcv_source}/vkcv/PipelineManager.cpp
-        
         ${vkcv_include}/vkcv/CommandResources.hpp
         ${vkcv_source}/vkcv/CommandResources.cpp
         
diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a99d75e6a0e4ec332588e7ff48a7d1ca112eccb4
--- /dev/null
+++ b/include/vkcv/ComputePipelineConfig.hpp
@@ -0,0 +1,17 @@
+#pragma once
+/**
+ * @authors Mark Mints
+ * @file src/vkcv/ComputePipelineConfig.hpp
+ * @brief Compute Pipeline Config Struct to hand over required information to Pipeline Creation.
+ */
+
+#include <vector>
+#include "ShaderProgram.hpp"
+
+namespace vkcv
+{
+    struct ComputePipelineConfig {
+        ShaderProgram&                          m_ShaderProgram;
+        std::vector<vk::DescriptorSetLayout>  	m_DescriptorSetLayouts;
+    };
+}
\ No newline at end of file
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index adaa1cd4dfba51b6fa5b722950fc9ce444463584..d6e47d26e5c26dab7929ac5905938c2ac0c80125 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -14,7 +14,8 @@
 #include "Handles.hpp"
 #include "Buffer.hpp"
 #include "Image.hpp"
-#include "PipelineConfig.hpp"
+#include "GraphicsPipelineConfig.hpp"
+#include "ComputePipelineConfig.hpp"
 #include "CommandResources.hpp"
 #include "SyncResources.hpp"
 #include "Result.hpp"
@@ -33,7 +34,8 @@ namespace vkcv
 
     // forward declarations
     class PassManager;
-    class PipelineManager;
+    class GraphicsPipelineManager;
+    class ComputePipelineManager;
     class DescriptorManager;
     class BufferManager;
     class SamplerManager;
@@ -65,15 +67,16 @@ namespace vkcv
 
         Context m_Context;
 
-        std::unique_ptr<PassManager>            m_PassManager;
-        std::unique_ptr<PipelineManager>        m_PipelineManager;
-        std::unique_ptr<DescriptorManager>      m_DescriptorManager;
-        std::unique_ptr<BufferManager>          m_BufferManager;
-        std::unique_ptr<SamplerManager>         m_SamplerManager;
-        std::unique_ptr<ImageManager>           m_ImageManager;
-        std::unique_ptr<CommandStreamManager>   m_CommandStreamManager;
-		std::unique_ptr<WindowManager>          m_WindowManager;
-		std::unique_ptr<SwapchainManager>       m_SwapchainManager;
+        std::unique_ptr<PassManager>             m_PassManager;
+        std::unique_ptr<GraphicsPipelineManager> m_PipelineManager;
+        std::unique_ptr<ComputePipelineManager>  m_ComputePipelineManager;
+        std::unique_ptr<DescriptorManager>       m_DescriptorManager;
+        std::unique_ptr<BufferManager>           m_BufferManager;
+        std::unique_ptr<SamplerManager>          m_SamplerManager;
+        std::unique_ptr<ImageManager>            m_ImageManager;
+        std::unique_ptr<CommandStreamManager>    m_CommandStreamManager;
+        std::unique_ptr<WindowManager>           m_WindowManager;
+        std::unique_ptr<SwapchainManager>        m_SwapchainManager;
 
 		CommandResources    m_CommandResources;
 		SyncResources       m_SyncResources;
@@ -154,20 +157,17 @@ namespace vkcv
          * @return True if pipeline creation was successful, False if not
          */
         [[nodiscard]]
-        PipelineHandle createGraphicsPipeline(const PipelineConfig &config);
+		GraphicsPipelineHandle createGraphicsPipeline(const GraphicsPipelineConfig &config);
 
         /**
          * Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle.
          * Fixed Functions for pipeline are set with standard values.
          *
-         * @param shader program that hold the compiles compute shader
-         * @param handle a handle to return the created vulkan handle
+         * @param config Contains the compiles compute shader and the corresponding descriptor set layout
          * @return True if pipeline creation was successful, False if not
          */
         [[nodiscard]]
-        PipelineHandle createComputePipeline(
-            const ShaderProgram &shaderProgram,
-            const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
+        ComputePipelineHandle createComputePipeline(const ComputePipelineConfig &config);
 
         /**
          * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
@@ -325,7 +325,7 @@ namespace vkcv
 		void recordDrawcallsToCmdStream(
 			const CommandStreamHandle&      cmdStreamHandle,
 			const PassHandle&               renderpassHandle,
-			const PipelineHandle            pipelineHandle,
+			const GraphicsPipelineHandle    &pipelineHandle,
 			const PushConstants             &pushConstants,
 			const std::vector<DrawcallInfo> &drawcalls,
 			const std::vector<ImageHandle>  &renderTargets,
@@ -334,7 +334,7 @@ namespace vkcv
 		void recordMeshShaderDrawcalls(
 			const CommandStreamHandle&              cmdStreamHandle,
 			const PassHandle&                       renderpassHandle,
-			const PipelineHandle                    pipelineHandle,
+			const GraphicsPipelineHandle            &pipelineHandle,
 			const PushConstants&                    pushConstantData,
             const std::vector<MeshShaderDrawcall>&  drawcalls,
 			const std::vector<ImageHandle>&         renderTargets,
@@ -342,7 +342,7 @@ namespace vkcv
 
 		void recordComputeDispatchToCmdStream(
 			CommandStreamHandle cmdStream,
-			PipelineHandle computePipeline,
+            ComputePipelineHandle computePipeline,
 			const uint32_t dispatchCount[3],
 			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
 			const PushConstants& pushConstants);
@@ -355,7 +355,7 @@ namespace vkcv
 
 		void recordComputeIndirectDispatchToCmdStream(
 			const CommandStreamHandle               cmdStream,
-			const PipelineHandle                    computePipeline,
+			const ComputePipelineHandle             computePipeline,
 			const vkcv::BufferHandle                buffer,
 			const size_t                            bufferArgOffset,
 			const std::vector<DescriptorSetUsage>&  descriptorSetUsages,
@@ -405,7 +405,8 @@ namespace vkcv
 	
 		void setDebugLabel(const BufferHandle &handle, const std::string &label);
 		void setDebugLabel(const PassHandle &handle, const std::string &label);
-		void setDebugLabel(const PipelineHandle &handle, const std::string &label);
+		void setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label);
+		void setDebugLabel(const ComputePipelineHandle &handle, const std::string &label);
 		void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label);
 		void setDebugLabel(const SamplerHandle &handle, const std::string &label);
 		void setDebugLabel(const ImageHandle &handle, const std::string &label);
diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp
index cf945d7498fec83f0b128294caa3ba267b69a6b3..600abc9e975ca9ed902fbc27c285315d0d6c0a9a 100644
--- a/include/vkcv/FeatureManager.hpp
+++ b/include/vkcv/FeatureManager.hpp
@@ -117,6 +117,10 @@ namespace vkcv {
 			featureFunction(features);
 			
 			if (!checkSupport(features, required)) {
+				if (required) {
+					throw std::runtime_error("Required feature is not supported!");
+				}
+				
 				return false;
 			}
 			
diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp
similarity index 91%
rename from include/vkcv/PipelineConfig.hpp
rename to include/vkcv/GraphicsPipelineConfig.hpp
index 5e6dbaa3306f8d2aa6fc44d7dd1fadd9b79be3b4..6d466c4aa3893049eb0b3e770c2e4dde6b6199e3 100644
--- a/include/vkcv/PipelineConfig.hpp
+++ b/include/vkcv/GraphicsPipelineConfig.hpp
@@ -1,8 +1,8 @@
 #pragma once
 /**
  * @authors Mara Vogt, Mark Mints
- * @file src/vkcv/Pipeline.hpp
- * @brief Pipeline class to handle shader stages
+ * @file src/vkcv/PipelineConfig.hpp
+ * @brief Graphics Pipeline Config Struct to hand over required information to Pipeline Creation
  */
 
 #include <vector>
@@ -22,7 +22,7 @@ namespace vkcv {
     // alternatively we could expose the blend factors directly
     enum class BlendMode{ None, Additive };
 
-    struct PipelineConfig {
+    struct GraphicsPipelineConfig {
         ShaderProgram                         	m_ShaderProgram;
         uint32_t                              	m_Width;
 		uint32_t                              	m_Height;
diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp
index c68d4bd4b5c76add61e6cb0c236c4e160f42fab2..1e6091c97dbe8dfc31013b653f175acede76070b 100644
--- a/include/vkcv/Handles.hpp
+++ b/include/vkcv/Handles.hpp
@@ -73,11 +73,17 @@ namespace vkcv
 		using Handle::Handle;
 	};
 	
-	class PipelineHandle : public Handle {
-		friend class PipelineManager;
+	class GraphicsPipelineHandle : public Handle {
+		friend class GraphicsPipelineManager;
 	private:
 		using Handle::Handle;
 	};
+
+    class ComputePipelineHandle : public Handle {
+        friend class ComputePipelineManager;
+    private:
+        using Handle::Handle;
+    };
 	
 	class DescriptorSetHandle : public Handle {
 		friend class DescriptorManager;
@@ -99,6 +105,7 @@ namespace vkcv
 
 	class ImageHandle : public Handle {
 		friend class ImageManager;
+	private:
 		using Handle::Handle;
 	public:
 		[[nodiscard]]
diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp
index 0dfa7811f0a7cca9107676438c0c66ade4519828..095c5e278e9e3f76544e884bdb87cea10770307a 100644
--- a/modules/scene/include/vkcv/scene/Scene.hpp
+++ b/modules/scene/include/vkcv/scene/Scene.hpp
@@ -58,7 +58,7 @@ namespace vkcv::scene {
 		void recordDrawcalls(CommandStreamHandle       		  &cmdStream,
 							 const camera::Camera			  &camera,
 							 const PassHandle                 &pass,
-							 const PipelineHandle             &pipeline,
+							 const GraphicsPipelineHandle     &pipeline,
 							 size_t							  pushConstantsSizePerDrawcall,
 							 const RecordMeshDrawcallFunction &record,
 							 const std::vector<ImageHandle>   &renderTargets,
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index f4318f42ddd2a14b6f87eefdd46d20df5fc98c44..cd02004f56ea3dfddcd20618b7859a0699d92d71 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -112,7 +112,7 @@ namespace vkcv::scene {
 	void Scene::recordDrawcalls(CommandStreamHandle       		 &cmdStream,
 								const camera::Camera			 &camera,
 								const PassHandle                 &pass,
-								const PipelineHandle             &pipeline,
+								const GraphicsPipelineHandle     &pipeline,
 								size_t							 pushConstantsSizePerDrawcall,
 								const RecordMeshDrawcallFunction &record,
 								const std::vector<ImageHandle>   &renderTargets,
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index 241544c79545384d14a2599fb718cd3992455705..4d3316718bf995f5cc8ccddde8c74575beba7745 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -30,10 +30,12 @@ namespace vkcv::upscaling {
 	
 	class FSRUpscaling : public Upscaling {
 	private:
-		PipelineHandle m_easuPipeline;
-		PipelineHandle m_rcasPipeline;
+
+		ComputePipelineHandle m_easuPipeline;
+		ComputePipelineHandle m_rcasPipeline;
 
 		DescriptorSetLayoutHandle m_easuDescriptorSetLayout;
+
 		DescriptorSetHandle m_easuDescriptorSet;
 
 		DescriptorSetLayoutHandle m_rcasDescriptorSetLayout;
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 88436c148d711638554f82a0cfb7be2dc81c998e..e4aae60b595d50d7e859199079714e91f5e5a694 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -1,4 +1,3 @@
-
 #include "vkcv/upscaling/FSRUpscaling.hpp"
 
 #include <stdint.h>
@@ -226,13 +225,14 @@ namespace vkcv::upscaling {
 		{
 			ShaderProgram program;
 			compileFSRShader(easuCompiler, [&program](vkcv::ShaderStage shaderStage,
-					const std::filesystem::path& path) {
+				const std::filesystem::path& path) {
 				program.addShader(shaderStage, path);
 			});
-			
-			m_easuPipeline = m_core.createComputePipeline(program, {
-				m_core.getDescriptorSetLayout(m_easuDescriptorSetLayout).vulkanHandle
+
+			m_easuPipeline = m_core.createComputePipeline({ program, 
+				{m_core.getDescriptorSetLayout(m_easuDescriptorSetLayout).vulkanHandle} 
 			});
+
 			
 			DescriptorWrites writes;
 			writes.uniformBufferWrites.emplace_back(
@@ -250,11 +250,11 @@ namespace vkcv::upscaling {
 					const std::filesystem::path& path) {
 				program.addShader(shaderStage, path);
 			});
-			
-			m_rcasPipeline = m_core.createComputePipeline(program, {
-			    m_core.getDescriptorSetLayout(m_rcasDescriptorSetLayout).vulkanHandle
-			});
-			
+
+			m_rcasPipeline = m_core.createComputePipeline({ program, {
+				m_core.getDescriptorSetLayout(m_rcasDescriptorSetLayout).vulkanHandle
+			}});
+
 			DescriptorWrites writes;
 			writes.uniformBufferWrites.emplace_back(
 					0, m_rcasConstants.getHandle(),true
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index e381cab6315bdb86a6c28ba0fa4b0a6388c50a38..5ef277dfedbfa823a2b6fa55c5a6303117ddaa52 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -109,7 +109,7 @@ int main(int argc, const char** argv) {
 
 	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(setLayoutHandle);
 
-	const vkcv::PipelineConfig firstMeshPipelineConfig {
+	const vkcv::GraphicsPipelineConfig firstMeshPipelineConfig {
         firstMeshProgram,
         UINT32_MAX,
         UINT32_MAX,
@@ -118,7 +118,7 @@ int main(int argc, const char** argv) {
 		{ core.getDescriptorSetLayout(setLayoutHandle).vulkanHandle },
 		true
 	};
-	vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
+	vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
 	
 	if (!firstMeshPipeline) {
 		std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl;
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index cf238375c4107ecbc1fc7f587734d51a41255752..4891fecbf8e0fc5dee3f9930b477aa03115916d2 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -78,7 +78,7 @@ int main(int argc, const char** argv) {
 	
 	const auto& material0 = scene.getMaterial(0);
 
-	const vkcv::PipelineConfig scenePipelineDefinition{
+	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
 		sceneShaderProgram,
 		UINT32_MAX,
 		UINT32_MAX,
@@ -86,7 +86,7 @@ int main(int argc, const char** argv) {
 		{sceneLayout},
 		{ core.getDescriptorSetLayout(material0.getDescriptorSetLayout()).vulkanHandle },
 		true };
-	vkcv::PipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
+	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
 	
 	if (!scenePipeline) {
 		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index cad1a54a6de599ddc3d2c911a6deca53a634faab..1725b5c84dea931fe785880e3cd423cbb5f04a46 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -59,7 +59,7 @@ int main(int argc, const char** argv) {
 	
 	const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 
-	const vkcv::PipelineConfig trianglePipelineDefinition {
+	const vkcv::GraphicsPipelineConfig trianglePipelineDefinition {
 		triangleShaderProgram,
 		swapchainExtent.width,
 		swapchainExtent.height,
@@ -69,7 +69,7 @@ int main(int argc, const char** argv) {
 		false
 	};
 
-	vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
+	vkcv::GraphicsPipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
 
 	if (!trianglePipeline)
 	{
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index 8b2db80a002a520571c91aa157bde685203bd96a..d4afc61c7421bd45c773bbdbc3da796b868869d2 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -4,6 +4,21 @@
 #include <vkcv/gui/GUI.hpp>
 #include <functional>
 
+const char* MotionVectorVisualisationModeLabels[6] = {
+		"None",
+		"Full resolution",
+		"Max tile",
+		"Tile neighbourhood max",
+		"Min Tile",
+		"Tile neighbourhood min"
+};
+
+const char* MotionBlurModeLabels[3] = {
+		"Default",
+		"Disabled",
+		"Tile visualisation"
+};
+
 App::App() : 
 	m_applicationName("Indirect Dispatch"),
 	m_windowWidth(AppConfig::defaultWindowWidth),
diff --git a/projects/indirect_dispatch/src/App.hpp b/projects/indirect_dispatch/src/App.hpp
index 9c2d43bd762ecbaa57a27edd6dd6499edb3593af..a35c2342c4c90e39b089a7c33a73c3aa7ce8a83f 100644
--- a/projects/indirect_dispatch/src/App.hpp
+++ b/projects/indirect_dispatch/src/App.hpp
@@ -12,8 +12,8 @@ public:
 private:
 	const char* m_applicationName;
 
-	int m_windowWidth;
-	int m_windowHeight;
+	uint32_t m_windowWidth;
+	uint32_t m_windowHeight;
 
 	vkcv::Core                  m_core;
 	vkcv::WindowHandle          m_windowHandle;
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 729072cfabd2c7ac109b121ac4bc5e0304b9662e..e1b29ad5990d371535794fa72a1d80e2b653045b 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -131,7 +131,7 @@ bool loadGraphicPass(
 	}
 
 
-	vkcv::PipelineConfig pipelineConfig{
+	vkcv::GraphicsPipelineConfig pipelineConfig{
 		shaderProgram,
 		UINT32_MAX,
 		UINT32_MAX,
@@ -258,9 +258,9 @@ bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, Comput
 
 	outComputePass->descriptorSetLayout = core.createDescriptorSetLayout(shaderProgram.getReflectedDescriptors().at(0));
 	outComputePass->descriptorSet = core.createDescriptorSet(outComputePass->descriptorSetLayout);
-	outComputePass->pipeline = core.createComputePipeline(
+	outComputePass->pipeline = core.createComputePipeline({
 		shaderProgram,
-		{ core.getDescriptorSetLayout(outComputePass->descriptorSetLayout).vulkanHandle });
+		{ core.getDescriptorSetLayout(outComputePass->descriptorSetLayout).vulkanHandle }});
 
 	if (!outComputePass->pipeline) {
 		vkcv_log(vkcv::LogLevel::ERROR, "Compute shader pipeline creation failed");
diff --git a/projects/indirect_dispatch/src/AppSetup.hpp b/projects/indirect_dispatch/src/AppSetup.hpp
index 162a6c6126f39adb85da7e419ef4e5b9793dc5ad..b0ade4317b125fea581016bf9924cd740a443c35 100644
--- a/projects/indirect_dispatch/src/AppSetup.hpp
+++ b/projects/indirect_dispatch/src/AppSetup.hpp
@@ -8,14 +8,14 @@ struct AppRenderTargets {
 };
 
 struct GraphicPassHandles {
-	vkcv::PipelineHandle                pipeline;
+	vkcv::GraphicsPipelineHandle        pipeline;
 	vkcv::PassHandle                    renderPass;
 	vkcv::DescriptorSetLayoutHandle     descriptorSetLayout;
 	vkcv::DescriptorSetHandle           descriptorSet;
 };
 
 struct ComputePassHandles {
-	vkcv::PipelineHandle                pipeline;
+	vkcv::ComputePipelineHandle         pipeline;
 	vkcv::DescriptorSetLayoutHandle     descriptorSetLayout;
 	vkcv::DescriptorSetHandle           descriptorSet;
 };
@@ -33,10 +33,10 @@ bool loadImage(vkcv::Core& core, const std::filesystem::path& path, vkcv::ImageH
 
 bool loadGraphicPass(
 	vkcv::Core& core,
-	const std::filesystem::path vertexPath,
-	const std::filesystem::path fragmentPath,
+	std::filesystem::path vertexPath,
+	std::filesystem::path fragmentPath,
 	const vkcv::PassConfig&     passConfig,
-	const vkcv::DepthTest       depthTest,
+	vkcv::DepthTest       		depthTest,
 	GraphicPassHandles*         outPassHandles);
 
 bool loadMeshPass  (vkcv::Core& core, GraphicPassHandles* outHandles);
diff --git a/projects/indirect_dispatch/src/MotionBlur.hpp b/projects/indirect_dispatch/src/MotionBlur.hpp
index b50f0af60d566dc0e4fc00c31b7b834e11679bf5..4e6003799237f69f4a422dd9c20f99255fe711fa 100644
--- a/projects/indirect_dispatch/src/MotionBlur.hpp
+++ b/projects/indirect_dispatch/src/MotionBlur.hpp
@@ -13,25 +13,12 @@ enum class eMotionVectorVisualisationMode : int {
 	MinTileNeighbourhood    = 5,
 	OptionCount             = 6 };
 
-static const char* MotionVectorVisualisationModeLabels[6] = {
-	"None",
-	"Full resolution",
-	"Max tile",
-	"Tile neighbourhood max",
-	"Min Tile",
-	"Tile neighbourhood min"};
-
 enum class eMotionBlurMode : int {
 	Default             = 0,
 	Disabled            = 1,
 	TileVisualisation   = 2,
 	OptionCount         = 3 };
 
-static const char* MotionBlurModeLabels[3] = {
-	"Default",
-	"Disabled",
-	"Tile visualisation" };
-
 class MotionBlur {
 public:
 
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 0bd279130f35d4c67fa61a1c00469ffa93c2bd5c..0ee16b99822e0c8fbeaf58af57f02255493b0fb5 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -205,7 +205,7 @@ int main(int argc, const char** argv) {
 
 	auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 	
-	const vkcv::PipelineConfig bunnyPipelineDefinition {
+	const vkcv::GraphicsPipelineConfig bunnyPipelineDefinition {
 			bunnyShaderProgram,
 			swapchainExtent.width,
 			swapchainExtent.height,
@@ -226,7 +226,7 @@ int main(int argc, const char** argv) {
 	vertexShaderDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, matrixBuffer.getHandle()) };
 	core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
 
-	vkcv::PipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
+	vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
 
 	if (!bunnyPipeline)
 	{
@@ -255,7 +255,7 @@ int main(int argc, const char** argv) {
 	vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet(meshShaderDescriptorSetLayout);
 	const vkcv::VertexLayout meshShaderLayout(bindings);
 
-	const vkcv::PipelineConfig meshShaderPipelineDefinition{
+	const vkcv::GraphicsPipelineConfig meshShaderPipelineDefinition{
 		meshShaderProgram,
 		swapchainExtent.width,
 		swapchainExtent.height,
@@ -265,7 +265,7 @@ int main(int argc, const char** argv) {
 		false
 	};
 
-	vkcv::PipelineHandle meshShaderPipeline = core.createGraphicsPipeline(meshShaderPipelineDefinition);
+	vkcv::GraphicsPipelineHandle meshShaderPipeline = core.createGraphicsPipeline(meshShaderPipelineDefinition);
 
 	if (!meshShaderPipeline)
 	{
diff --git a/projects/particle_simulation/src/BloomAndFlares.cpp b/projects/particle_simulation/src/BloomAndFlares.cpp
index 68a553574eddd668f7c0360b91d4da448c5b8cf8..d0f25122c443eef847ce190c099eef95e8ecc0c8 100644
--- a/projects/particle_simulation/src/BloomAndFlares.cpp
+++ b/projects/particle_simulation/src/BloomAndFlares.cpp
@@ -36,8 +36,9 @@ BloomAndFlares::BloomAndFlares(
 		m_DownsampleDescSets.push_back(
 		        p_Core->createDescriptorSet(m_DownsampleDescSetLayouts.back()));
     }
-    m_DownsamplePipe = p_Core->createComputePipeline(
-            dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle });
+
+    m_DownsamplePipe = p_Core->createComputePipeline({
+        dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }});
 
     // UPSAMPLE
     vkcv::ShaderProgram usProg;
@@ -54,8 +55,9 @@ BloomAndFlares::BloomAndFlares(
         m_UpsampleDescSets.push_back(
                 p_Core->createDescriptorSet(m_UpsampleDescSetLayouts.back()));
     }
-    m_UpsamplePipe = p_Core->createComputePipeline(
-            usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle });
+
+    m_UpsamplePipe = p_Core->createComputePipeline({
+            usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }});
 
     // LENS FEATURES
     vkcv::ShaderProgram lensProg;
@@ -65,10 +67,11 @@ BloomAndFlares::BloomAndFlares(
                      {
                          lensProg.addShader(shaderStage, path);
                      });
+
     m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0));
     m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout);
-    m_LensFlarePipe = p_Core->createComputePipeline(
-            lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle });
+    m_LensFlarePipe = p_Core->createComputePipeline({
+            lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle }});
 
     // COMPOSITE
     vkcv::ShaderProgram compProg;
@@ -78,10 +81,11 @@ BloomAndFlares::BloomAndFlares(
                      {
                          compProg.addShader(shaderStage, path);
                      });
+
     m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0));
     m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout);
-    m_CompositePipe = p_Core->createComputePipeline(
-            compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle });
+    m_CompositePipe = p_Core->createComputePipeline({
+            compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle }});
 }
 
 void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream,
diff --git a/projects/particle_simulation/src/BloomAndFlares.hpp b/projects/particle_simulation/src/BloomAndFlares.hpp
index 21f69f43511fabb920fd85c9e07f3fd0e5a355f3..2692034db51cf341e7ede2a26f5724c92dccbfed 100644
--- a/projects/particle_simulation/src/BloomAndFlares.hpp
+++ b/projects/particle_simulation/src/BloomAndFlares.hpp
@@ -24,20 +24,19 @@ private:
     vkcv::Image m_Blur;
     vkcv::Image m_LensFeatures;
 
-
-    vkcv::PipelineHandle                            m_DownsamplePipe;
+    vkcv::ComputePipelineHandle                     m_DownsamplePipe;
     std::vector<vkcv::DescriptorSetLayoutHandle>    m_DownsampleDescSetLayouts;
     std::vector<vkcv::DescriptorSetHandle>          m_DownsampleDescSets; // per mip desc set
 
-    vkcv::PipelineHandle                            m_UpsamplePipe;
+    vkcv::ComputePipelineHandle                     m_UpsamplePipe;
     std::vector<vkcv::DescriptorSetLayoutHandle>    m_UpsampleDescSetLayouts;
     std::vector<vkcv::DescriptorSetHandle>          m_UpsampleDescSets;   // per mip desc set
 
-    vkcv::PipelineHandle                            m_LensFlarePipe;
+    vkcv::ComputePipelineHandle                     m_LensFlarePipe;
     vkcv::DescriptorSetLayoutHandle                 m_LensFlareDescSetLayout;
     vkcv::DescriptorSetHandle                       m_LensFlareDescSet;
 
-    vkcv::PipelineHandle                            m_CompositePipe;
+    vkcv::ComputePipelineHandle                     m_CompositePipe;
     vkcv::DescriptorSetLayoutHandle                 m_CompositeDescSetLayout;
     vkcv::DescriptorSetHandle                       m_CompositeDescSet;
 
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index afb1c177805d5a06202c7d5a267ecf99e05bef6a..ddbe6195e66e78504d4bccb32b3b09ff680ab414 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -115,7 +115,7 @@ int main(int argc, const char **argv) {
 
     const vkcv::VertexLayout particleLayout(bindings);
 
-    vkcv::PipelineConfig particlePipelineDefinition{
+    vkcv::GraphicsPipelineConfig particlePipelineDefinition{
             particleShaderProgram,
             UINT32_MAX,
             UINT32_MAX,
@@ -131,9 +131,9 @@ int main(int argc, const char **argv) {
 
     vertexBuffer.fill(vertices);
 
-    vkcv::PipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition);
+    vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition);
 
-    vkcv::PipelineHandle computePipeline = core.createComputePipeline(computeShaderProgram, {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} );
+    vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline({ computeShaderProgram, {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} });
 
     vkcv::Buffer<glm::vec4> color = core.createBuffer<glm::vec4>(
             vkcv::BufferType::UNIFORM,
@@ -236,9 +236,9 @@ int main(int argc, const char **argv) {
 
     vkcv::DescriptorSetLayoutHandle tonemappingDescriptorLayout = core.createDescriptorSetLayout(tonemappingShader.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout);
-    vkcv::PipelineHandle tonemappingPipe = core.createComputePipeline(
+    vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({
         tonemappingShader, 
-        { core.getDescriptorSetLayout(tonemappingDescriptorLayout).vulkanHandle });
+        { core.getDescriptorSetLayout(tonemappingDescriptorLayout).vulkanHandle }});
 
     std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f);
     std::default_random_engine rdmEngine;
diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp
index 6a7eae3b90e83722a7a1c45ed95e96d4291b28ec..d47f61d0dc7fea4e38508b7b1d6c040595e2944a 100644
--- a/projects/voxelization/src/BloomAndFlares.cpp
+++ b/projects/voxelization/src/BloomAndFlares.cpp
@@ -49,8 +49,10 @@ BloomAndFlares::BloomAndFlares(
                 );
         m_DownsampleDescSets.push_back(p_Core->createDescriptorSet(m_DownsampleDescSetLayouts.back()));
     }
-    m_DownsamplePipe = p_Core->createComputePipeline(
-            dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle });
+
+    m_DownsamplePipe = p_Core->createComputePipeline({
+        dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }
+    });
 
     // UPSAMPLE
     vkcv::ShaderProgram usProg;
@@ -74,8 +76,9 @@ BloomAndFlares::BloomAndFlares(
                 p_Core->createDescriptorSet(m_UpsampleLensFlareDescSetLayouts.back()));
     }
 
-    m_UpsamplePipe = p_Core->createComputePipeline(
-            usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle });
+    m_UpsamplePipe = p_Core->createComputePipeline({
+        usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }
+    });
 
     // LENS FEATURES
     vkcv::ShaderProgram lensProg;
@@ -85,10 +88,12 @@ BloomAndFlares::BloomAndFlares(
                      {
                          lensProg.addShader(shaderStage, path);
                      });
+
     m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0));
     m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout);
     m_LensFlarePipe = p_Core->createComputePipeline(
-            lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle });
+        { lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle } });
+
 
     // COMPOSITE
     vkcv::ShaderProgram compProg;
@@ -102,7 +107,7 @@ BloomAndFlares::BloomAndFlares(
     m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0));
     m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout);
     m_CompositePipe = p_Core->createComputePipeline(
-            compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle });
+        { compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle } });
 
     // radial LUT
     const auto texture = vkcv::asset::loadTexture("assets/RadialLUT.png");
@@ -318,9 +323,9 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea
             static_cast<uint32_t>(glm::ceil(dispatchCountY)),
             1
     };
-	
-	vkcv::PushConstants pushConstants (sizeof(cameraForward));
-	pushConstants.appendDrawcall(cameraForward);
+
+    vkcv::PushConstants pushConstants(sizeof(cameraForward));
+    pushConstants.appendDrawcall(cameraForward);
 
     // bloom composite dispatch
     p_Core->recordComputeDispatchToCmdStream(
@@ -348,6 +353,4 @@ void BloomAndFlares::updateImageDimensions(uint32_t width, uint32_t height)
     p_Core->getContext().getDevice().waitIdle();
     m_Blur = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false);
     m_LensFeatures = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false);
-}
-
-
+}
\ No newline at end of file
diff --git a/projects/voxelization/src/BloomAndFlares.hpp b/projects/voxelization/src/BloomAndFlares.hpp
index 133a82cbe85a2fd4fd9965874a36faa5369013b9..3d63d9f37b4733eaea170a3e4561774c0d53208b 100644
--- a/projects/voxelization/src/BloomAndFlares.hpp
+++ b/projects/voxelization/src/BloomAndFlares.hpp
@@ -29,22 +29,22 @@ private:
     vkcv::Image m_radialLut;
     vkcv::Image m_lensDirt;
 
-    vkcv::PipelineHandle                            m_DownsamplePipe;
+    vkcv::ComputePipelineHandle                     m_DownsamplePipe;
     std::vector<vkcv::DescriptorSetLayoutHandle>    m_DownsampleDescSetLayouts;
     std::vector<vkcv::DescriptorSetHandle>          m_DownsampleDescSets; // per mip desc set
 
     std::vector<vkcv::DescriptorSetLayoutHandle>    m_UpsampleLensFlareDescSetLayouts;
     std::vector<vkcv::DescriptorSetHandle>          m_UpsampleLensFlareDescSets; // per mip desc set
 
-    vkcv::PipelineHandle                            m_UpsamplePipe;
+    vkcv::ComputePipelineHandle                     m_UpsamplePipe;
     std::vector<vkcv::DescriptorSetLayoutHandle>    m_UpsampleDescSetLayouts;
     std::vector<vkcv::DescriptorSetHandle>          m_UpsampleDescSets;   // per mip desc set
 
-    vkcv::PipelineHandle                            m_LensFlarePipe;
+    vkcv::ComputePipelineHandle                            m_LensFlarePipe;
     vkcv::DescriptorSetLayoutHandle                 m_LensFlareDescSetLayout;
     vkcv::DescriptorSetHandle                       m_LensFlareDescSet;
 
-    vkcv::PipelineHandle                            m_CompositePipe;
+    vkcv::ComputePipelineHandle                     m_CompositePipe;
     vkcv::DescriptorSetLayoutHandle                 m_CompositeDescSetLayout;
     vkcv::DescriptorSetHandle                       m_CompositeDescSet;
 
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 3f764618da0d3736dcd4cae212e95faeb834d68a..d8041c1e9935d148ded8fb1ca8f0e4d8b79fce71 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -166,7 +166,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	m_shadowMapPass = corePtr->createPass(shadowPassConfig);
 
 	// pipeline
-	vkcv::PipelineConfig shadowPipeConfig{
+	vkcv::GraphicsPipelineConfig shadowPipeConfig{
 		shadowShader,
 		shadowMapResolution,
 		shadowMapResolution,
@@ -189,9 +189,10 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 
 	// depth to moments
 	vkcv::ShaderProgram depthToMomentsShader    = loadDepthToMomentsShader();
+
 	m_depthToMomentsDescriptorSetLayout         = corePtr->createDescriptorSetLayout(depthToMomentsShader.getReflectedDescriptors().at(0));
 	m_depthToMomentsDescriptorSet               = corePtr->createDescriptorSet(m_depthToMomentsDescriptorSetLayout);
-	m_depthToMomentsPipe                        = corePtr->createComputePipeline(depthToMomentsShader, { corePtr->getDescriptorSetLayout(m_depthToMomentsDescriptorSetLayout).vulkanHandle });
+    m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { corePtr->getDescriptorSetLayout(m_depthToMomentsDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::DescriptorWrites depthToMomentDescriptorWrites;
 	depthToMomentDescriptorWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) };
@@ -203,7 +204,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	vkcv::ShaderProgram shadowBlurXShader   = loadShadowBlurXShader();
 	m_shadowBlurXDescriptorSetLayout        = corePtr->createDescriptorSetLayout(shadowBlurXShader.getReflectedDescriptors().at(0));
 	m_shadowBlurXDescriptorSet              = corePtr->createDescriptorSet(m_shadowBlurXDescriptorSetLayout);
-	m_shadowBlurXPipe                       = corePtr->createComputePipeline(shadowBlurXShader, { corePtr->getDescriptorSetLayout(m_shadowBlurXDescriptorSetLayout).vulkanHandle });
+	m_shadowBlurXPipe                       = corePtr->createComputePipeline({ shadowBlurXShader, { corePtr->getDescriptorSetLayout(m_shadowBlurXDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::DescriptorWrites shadowBlurXDescriptorWrites;
 	shadowBlurXDescriptorWrites.sampledImageWrites   = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) };
@@ -215,9 +216,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	vkcv::ShaderProgram shadowBlurYShader   = loadShadowBlurYShader();
 	m_shadowBlurYDescriptorSetLayout        = corePtr->createDescriptorSetLayout(shadowBlurYShader.getReflectedDescriptors().at(0));
 	m_shadowBlurYDescriptorSet              = corePtr->createDescriptorSet(m_shadowBlurYDescriptorSetLayout);
-	m_shadowBlurYPipe                       = corePtr->createComputePipeline(shadowBlurYShader, { corePtr->getDescriptorSetLayout(m_shadowBlurYDescriptorSetLayout).vulkanHandle });
+    m_shadowBlurYPipe                       = corePtr->createComputePipeline({ shadowBlurYShader, { corePtr->getDescriptorSetLayout(m_shadowBlurYDescriptorSetLayout).vulkanHandle }});
 
-	vkcv::DescriptorWrites shadowBlurYDescriptorWrites;
+    vkcv::DescriptorWrites shadowBlurYDescriptorWrites;
 	shadowBlurYDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) };
 	shadowBlurYDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
 	shadowBlurYDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp
index 7f77b5bf8c35b2784dc58ec9ce664a0e32e640c0..7de83b800ce073f5541a889b87a7f0cd763ffa69 100644
--- a/projects/voxelization/src/ShadowMapping.hpp
+++ b/projects/voxelization/src/ShadowMapping.hpp
@@ -44,17 +44,17 @@ private:
 	vkcv::Buffer<LightInfo>             m_lightInfoBuffer;
 
 	vkcv::PassHandle                    m_shadowMapPass;
-	vkcv::PipelineHandle                m_shadowMapPipe;
+	vkcv::GraphicsPipelineHandle        m_shadowMapPipe;
 
-	vkcv::PipelineHandle                m_depthToMomentsPipe;
+	vkcv::ComputePipelineHandle         m_depthToMomentsPipe;
 	vkcv::DescriptorSetLayoutHandle     m_depthToMomentsDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_depthToMomentsDescriptorSet;
 
-	vkcv::PipelineHandle                m_shadowBlurXPipe;
+	vkcv::ComputePipelineHandle         m_shadowBlurXPipe;
 	vkcv::DescriptorSetLayoutHandle     m_shadowBlurXDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_shadowBlurXDescriptorSet;
 
-	vkcv::PipelineHandle                m_shadowBlurYPipe;
+	vkcv::ComputePipelineHandle         m_shadowBlurYPipe;
 	vkcv::DescriptorSetLayoutHandle     m_shadowBlurYDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_shadowBlurYDescriptorSet;
 };
\ No newline at end of file
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 783eb8b2edf4ad9310295a1f716ec3394c2b4c2e..3cbff0df84757fb370a0372ddd45a9df401d4b60 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -83,12 +83,12 @@ Voxelization::Voxelization(
 	vkcv::SamplerHandle voxelSampler,
 	vkcv::Multisampling msaa)
 	:
-	m_corePtr(corePtr), 
-	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
+	m_corePtr(corePtr),
 	m_voxelImageIntermediate(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
+	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
+	m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)),
 	m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)),
-	m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)),
-	m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){
+	m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)) {
 
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
 
@@ -104,7 +104,7 @@ Voxelization::Voxelization(
 	vkcv::DescriptorSetLayoutHandle dummyPerMeshDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelizationShader.getReflectedDescriptors().at(1));
 	vkcv::DescriptorSetHandle dummyPerMeshDescriptorSet = m_corePtr->createDescriptorSet(dummyPerMeshDescriptorSetLayout);
 
-	const vkcv::PipelineConfig voxelizationPipeConfig{
+	const vkcv::GraphicsPipelineConfig voxelizationPipeConfig{
 		voxelizationShader,
 		voxelResolution,
 		voxelResolution,
@@ -150,7 +150,7 @@ Voxelization::Voxelization(
 	voxelVisualisationPassDefinition.msaa = msaa;
 	m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition);
 
-	vkcv::PipelineConfig voxelVisualisationPipeConfig{
+	vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig{
 		voxelVisualisationShader,
 		0,
 		0,
@@ -164,8 +164,8 @@ Voxelization::Voxelization(
 	m_visualisationPipe = m_corePtr->createGraphicsPipeline(voxelVisualisationPipeConfig);
 
 	std::vector<uint16_t> voxelIndexData;
-	for (int i = 0; i < voxelCount; i++) {
-		voxelIndexData.push_back(i);
+	for (uint32_t i = 0; i < voxelCount; i++) {
+		voxelIndexData.push_back(static_cast<uint16_t>(i));
 	}
 
 	const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle);
@@ -174,9 +174,9 @@ Voxelization::Voxelization(
 
 	m_voxelResetDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(resetVoxelShader.getReflectedDescriptors().at(0));
 	m_voxelResetDescriptorSet = m_corePtr->createDescriptorSet(m_voxelResetDescriptorSetLayout);
-	m_voxelResetPipe = m_corePtr->createComputePipeline(
+	m_voxelResetPipe = m_corePtr->createComputePipeline({
 		resetVoxelShader,
-		{ m_corePtr->getDescriptorSetLayout(m_voxelResetDescriptorSetLayout).vulkanHandle });
+		{ m_corePtr->getDescriptorSetLayout(m_voxelResetDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::DescriptorWrites resetVoxelWrites;
 	resetVoxelWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
@@ -187,9 +187,9 @@ Voxelization::Voxelization(
 
 	m_bufferToImageDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(bufferToImageShader.getReflectedDescriptors().at(0));
 	m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(m_bufferToImageDescriptorSetLayout);
-	m_bufferToImagePipe = m_corePtr->createComputePipeline(
+	m_bufferToImagePipe = m_corePtr->createComputePipeline({
 		bufferToImageShader,
-		{ m_corePtr->getDescriptorSetLayout(m_bufferToImageDescriptorSetLayout).vulkanHandle });
+		{ m_corePtr->getDescriptorSetLayout(m_bufferToImageDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::DescriptorWrites bufferToImageDescriptorWrites;
 	bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
@@ -201,9 +201,9 @@ Voxelization::Voxelization(
 
 	m_secondaryBounceDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(secondaryBounceShader.getReflectedDescriptors().at(0));
 	m_secondaryBounceDescriptorSet = m_corePtr->createDescriptorSet(m_secondaryBounceDescriptorSetLayout);
-	m_secondaryBouncePipe = m_corePtr->createComputePipeline(
+	m_secondaryBouncePipe = m_corePtr->createComputePipeline({
 		secondaryBounceShader,
-		{ m_corePtr->getDescriptorSetLayout(m_secondaryBounceDescriptorSetLayout).vulkanHandle });
+		{ m_corePtr->getDescriptorSetLayout(m_secondaryBounceDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::DescriptorWrites secondaryBounceDescriptorWrites;
 	secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp
index b332cca0effec7b34f85b4fa83626658d986232a..d5f41123b527f2919dec678d0337ee25ea6fa2c6 100644
--- a/projects/voxelization/src/Voxelization.hpp
+++ b/projects/voxelization/src/Voxelization.hpp
@@ -57,22 +57,22 @@ private:
 
 	vkcv::Image                         m_dummyRenderTarget;
 	vkcv::PassHandle                    m_voxelizationPass;
-	vkcv::PipelineHandle                m_voxelizationPipe;
+	vkcv::GraphicsPipelineHandle        m_voxelizationPipe;
 	vkcv::DescriptorSetLayoutHandle     m_voxelizationDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_voxelizationDescriptorSet;
 
-	vkcv::PipelineHandle                m_voxelResetPipe;
+	vkcv::ComputePipelineHandle         m_voxelResetPipe;
 	vkcv::DescriptorSetLayoutHandle     m_voxelResetDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_voxelResetDescriptorSet;
 
-	vkcv::PipelineHandle                m_bufferToImagePipe;
+	vkcv::ComputePipelineHandle         m_bufferToImagePipe;
 	vkcv::DescriptorSetLayoutHandle     m_bufferToImageDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_bufferToImageDescriptorSet;
 
 	vkcv::PassHandle                    m_visualisationPass;
-	vkcv::PipelineHandle                m_visualisationPipe;
+	vkcv::GraphicsPipelineHandle        m_visualisationPipe;
 
-	vkcv::PipelineHandle                m_secondaryBouncePipe;
+	vkcv::ComputePipelineHandle         m_secondaryBouncePipe;
 	vkcv::DescriptorSetLayoutHandle     m_secondaryBounceDescriptorSetLayout;
 	vkcv::DescriptorSetHandle           m_secondaryBounceDescriptorSet;
 
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 1411e327216e1045847c66c7f40446a2ebbbb1bb..a7798813a52429d31f207ae24af6a3effb90c17c 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -300,7 +300,7 @@ int main(int argc, const char** argv) {
 
 	auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 	
-	vkcv::PipelineConfig prepassPipelineConfig{
+	vkcv::GraphicsPipelineConfig prepassPipelineConfig{
 		depthPrepassShader,
 		swapchainExtent.width,
 		swapchainExtent.height,
@@ -315,10 +315,10 @@ int main(int argc, const char** argv) {
 	prepassPipelineConfig.m_depthTest       = vkcv::DepthTest::LessEqual;
 	prepassPipelineConfig.m_alphaToCoverage = true;
 
-	vkcv::PipelineHandle prepassPipeline = core.createGraphicsPipeline(prepassPipelineConfig);
+	vkcv::GraphicsPipelineHandle prepassPipeline = core.createGraphicsPipeline(prepassPipelineConfig);
 
 	// forward pipeline
-	vkcv::PipelineConfig forwardPipelineConfig {
+	vkcv::GraphicsPipelineConfig forwardPipelineConfig {
 		forwardProgram,
 		swapchainExtent.width,
 		swapchainExtent.height,
@@ -334,7 +334,7 @@ int main(int argc, const char** argv) {
 	forwardPipelineConfig.m_depthTest       = vkcv::DepthTest::Equal;
 	forwardPipelineConfig.m_depthWrite      = false;
 	
-	vkcv::PipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
+	vkcv::GraphicsPipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
 	
 	if (!forwardPipeline) {
 		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
@@ -373,7 +373,7 @@ int main(int argc, const char** argv) {
 		skyShader.addShader(shaderStage, path);
 	});
 
-	vkcv::PipelineConfig skyPipeConfig;
+	vkcv::GraphicsPipelineConfig skyPipeConfig;
 	skyPipeConfig.m_ShaderProgram       = skyShader;
 	skyPipeConfig.m_Width               = swapchainExtent.width;
 	skyPipeConfig.m_Height              = swapchainExtent.height;
@@ -384,7 +384,7 @@ int main(int argc, const char** argv) {
 	skyPipeConfig.m_multisampling       = msaa;
 	skyPipeConfig.m_depthWrite          = false;
 
-	vkcv::PipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
+	vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
 
 	// render targets
 	vkcv::ImageHandle depthBuffer           = core.createImage(
@@ -451,12 +451,13 @@ int main(int argc, const char** argv) {
 		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 		tonemappingProgram.addShader(shaderStage, path);
 	});
+
 	vkcv::DescriptorSetLayoutHandle tonemappingDescriptorSetLayout = core.createDescriptorSetLayout(
 	        tonemappingProgram.getReflectedDescriptors().at(0));
 	vkcv::DescriptorSetHandle tonemappingDescriptorSet = core.createDescriptorSet(tonemappingDescriptorSetLayout);
-	vkcv::PipelineHandle tonemappingPipeline = core.createComputePipeline(
+	vkcv::ComputePipelineHandle tonemappingPipeline = core.createComputePipeline({
 		tonemappingProgram,
-		{ core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle });
+		{ core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }});
 	
 	// tonemapping compute shader
 	vkcv::ShaderProgram postEffectsProgram;
@@ -464,12 +465,13 @@ int main(int argc, const char** argv) {
 		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 		postEffectsProgram.addShader(shaderStage, path);
 	});
+
 	vkcv::DescriptorSetLayoutHandle postEffectsDescriptorSetLayout = core.createDescriptorSetLayout(
 	        postEffectsProgram.getReflectedDescriptors().at(0));
 	vkcv::DescriptorSetHandle postEffectsDescriptorSet = core.createDescriptorSet(postEffectsDescriptorSetLayout);
-	vkcv::PipelineHandle postEffectsPipeline = core.createComputePipeline(
+	vkcv::ComputePipelineHandle postEffectsPipeline = core.createComputePipeline({
 			postEffectsProgram,
-			{ core.getDescriptorSetLayout(postEffectsDescriptorSetLayout).vulkanHandle });
+			{ core.getDescriptorSetLayout(postEffectsDescriptorSetLayout).vulkanHandle }});
 
 	// resolve compute shader
 	vkcv::ShaderProgram resolveProgram;
@@ -477,12 +479,13 @@ int main(int argc, const char** argv) {
 		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 		resolveProgram.addShader(shaderStage, path);
 	});
+
 	vkcv::DescriptorSetLayoutHandle resolveDescriptorSetLayout = core.createDescriptorSetLayout(
-	        resolveProgram.getReflectedDescriptors().at(0));
+		resolveProgram.getReflectedDescriptors().at(0));
 	vkcv::DescriptorSetHandle resolveDescriptorSet = core.createDescriptorSet(resolveDescriptorSetLayout);
-	vkcv::PipelineHandle resolvePipeline = core.createComputePipeline(
+	vkcv::ComputePipelineHandle resolvePipeline = core.createComputePipeline({
 		resolveProgram,
-		{ core.getDescriptorSetLayout(resolveDescriptorSetLayout).vulkanHandle });
+		{ core.getDescriptorSetLayout(resolveDescriptorSetLayout).vulkanHandle }});
 
 	vkcv::SamplerHandle resolveSampler = core.createSampler(
 		vkcv::SamplerFilterType::NEAREST,
@@ -960,7 +963,7 @@ int main(int argc, const char** argv) {
 					newForwardProgram.addShader(shaderStage, path);
 				});
 				forwardPipelineConfig.m_ShaderProgram = newForwardProgram;
-				vkcv::PipelineHandle newPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
+				vkcv::GraphicsPipelineHandle newPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
 
 				if (newPipeline) {
 					forwardPipeline = newPipeline;
@@ -973,9 +976,10 @@ int main(int argc, const char** argv) {
 					[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 					newProgram.addShader(shaderStage, path);
 				});
-				vkcv::PipelineHandle newPipeline = core.createComputePipeline(
+
+				vkcv::ComputePipelineHandle newPipeline = core.createComputePipeline({
 					newProgram,
-					{ core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle });
+					{ core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }});
 
 				if (newPipeline) {
 					tonemappingPipeline = newPipeline;
diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f090b6dbe7e05f488958c072a758fbf2d2938ab5
--- /dev/null
+++ b/src/vkcv/ComputePipelineManager.cpp
@@ -0,0 +1,118 @@
+#include "ComputePipelineManager.hpp"
+
+namespace vkcv
+{
+
+    ComputePipelineManager::ComputePipelineManager(vk::Device device) noexcept :
+            m_Device{device},
+            m_Pipelines{}
+    {}
+
+    ComputePipelineManager::~ComputePipelineManager() noexcept
+    {
+        for (uint64_t id = 0; id < m_Pipelines.size(); id++) {
+            destroyPipelineById(id);
+        }
+    }
+
+    vk::Pipeline ComputePipelineManager::getVkPipeline(const ComputePipelineHandle &handle) const
+    {
+        const uint64_t id = handle.getId();
+
+        if (id >= m_Pipelines.size()) {
+            return nullptr;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        return pipeline.m_handle;
+    }
+
+    vk::PipelineLayout ComputePipelineManager::getVkPipelineLayout(const ComputePipelineHandle &handle) const
+    {
+        const uint64_t id = handle.getId();
+
+        if (id >= m_Pipelines.size()) {
+            return nullptr;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        return pipeline.m_layout;
+    }
+
+    ComputePipelineHandle ComputePipelineManager::createComputePipeline(const ComputePipelineConfig& config) {
+
+        // Temporally handing over the Shader Program instead of a pipeline config
+        vk::ShaderModule computeModule{};
+        if (createShaderModule(computeModule, config.m_ShaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess)
+            return ComputePipelineHandle();
+
+        vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo(
+                {},
+                vk::ShaderStageFlagBits::eCompute,
+                computeModule,
+                "main",
+                nullptr
+        );
+
+        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, config.m_DescriptorSetLayouts);
+
+        const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize();
+        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
+        if (pushConstantSize > 0) {
+            pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
+            pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
+        }
+
+        vk::PipelineLayout vkPipelineLayout{};
+        if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) !=
+            vk::Result::eSuccess) {
+            m_Device.destroy(computeModule);
+            return ComputePipelineHandle();
+        }
+
+        vk::ComputePipelineCreateInfo computePipelineCreateInfo{};
+        computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo;
+        computePipelineCreateInfo.layout = vkPipelineLayout;
+
+        vk::Pipeline vkPipeline;
+        if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline) !=
+            vk::Result::eSuccess) {
+            m_Device.destroy(computeModule);
+            return ComputePipelineHandle();
+        }
+
+        m_Device.destroy(computeModule);
+
+        const uint64_t id = m_Pipelines.size();
+        m_Pipelines.push_back({vkPipeline, vkPipelineLayout});
+
+        return ComputePipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
+    }
+
+    void vkcv::ComputePipelineManager::destroyPipelineById(uint64_t id) {
+        if (id >= m_Pipelines.size()) {
+            return;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        if (pipeline.m_handle) {
+            m_Device.destroy(pipeline.m_handle);
+            pipeline.m_handle = nullptr;
+        }
+
+        if (pipeline.m_layout) {
+            m_Device.destroy(pipeline.m_layout);
+            pipeline.m_layout = nullptr;
+        }
+    }
+
+    vk::Result ComputePipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage)
+    {
+        std::vector<char> code = shaderProgram.getShader(stage).shaderCode;
+        vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
+        return m_Device.createShaderModule(&moduleInfo, nullptr, &module);
+    }
+}
\ No newline at end of file
diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..527243e6ec43850d416a7d929e01351454c40086
--- /dev/null
+++ b/src/vkcv/ComputePipelineManager.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+/**
+ * @authors Mark Mints
+ * @file src/vkcv/ComputePipelineManager.hpp
+ * @brief Creation and handling of Compute Pipelines
+ */
+
+#include <vulkan/vulkan.hpp>
+#include <vector>
+
+#include "vkcv/Handles.hpp"
+#include "vkcv/ShaderProgram.hpp"
+#include "vkcv/ComputePipelineConfig.hpp"
+
+namespace vkcv
+{
+
+    class ComputePipelineManager
+    {
+    public:
+        ComputePipelineManager() = delete; // no default ctor
+        explicit ComputePipelineManager(vk::Device device) noexcept; // ctor
+        ~ComputePipelineManager() noexcept; // dtor
+
+        ComputePipelineManager(const ComputePipelineManager &other) = delete; // copy-ctor
+        ComputePipelineManager(ComputePipelineManager &&other) = delete; // move-ctor;
+
+        ComputePipelineManager & operator=(const ComputePipelineManager &other) = delete; // copy-assign op
+        ComputePipelineManager & operator=(ComputePipelineManager &&other) = delete; // move-assign op
+
+        /**
+        * Returns a vk::Pipeline object by handle.
+        * @param handle Directing to the requested pipeline.
+        * @return vk::Pipeline.
+        */
+        [[nodiscard]]
+        vk::Pipeline getVkPipeline(const ComputePipelineHandle &handle) const;
+
+        /**
+         * Returns a vk::PipelineLayout object by handle.
+         * @param handle Directing to the requested pipeline.
+         * @return vk::PipelineLayout.
+         */
+        [[nodiscard]]
+        vk::PipelineLayout getVkPipelineLayout(const ComputePipelineHandle &handle) const;
+
+        /**
+         * Creates a Compute Pipeline based on the set shader stages in the Config Struct.
+         * This function is wrapped in /src/vkcv/Core.cpp by Core::createComputePipeline(const ComputePipelineConfig &config).
+         * On application level it is necessary first to fill a ComputePipelineConfig Struct.
+         * @param config Hands over all needed information for pipeline creation.
+         * @return A Handler to the created Compute Pipeline Object.
+         */
+        ComputePipelineHandle createComputePipeline(const ComputePipelineConfig& config);
+
+    private:
+        struct ComputePipeline {
+            vk::Pipeline m_handle;
+            vk::PipelineLayout m_layout;
+        };
+
+        vk::Device m_Device;
+        std::vector<ComputePipeline> m_Pipelines;
+
+        void destroyPipelineById(uint64_t id);
+
+        vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage);
+
+    };
+
+}
diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp
index 906c6fe73c206048e5b06d03f3bf6a02ffdaf13b..01f6039eba5646bc99780415b7c41f0a02d65fe6 100644
--- a/src/vkcv/Context.cpp
+++ b/src/vkcv/Context.cpp
@@ -123,16 +123,17 @@ namespace vkcv
 	/**
 	 * @brief All existing physical devices will be evaluated by deviceScore.
 	 * @param instance The instance
-	 * @return The optimal physical device
+	 * @param physicalDevice The optimal physical device
+	 * @return Returns if a suitable GPU is found as physical device
 	 * @see Context.deviceScore
 	*/
-	vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance)
+	bool pickPhysicalDevice(const vk::Instance& instance, vk::PhysicalDevice& physicalDevice)
 	{
-		vk::PhysicalDevice phyDevice;
-		std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
+		const std::vector<vk::PhysicalDevice>& devices = instance.enumeratePhysicalDevices();
 		
 		if (devices.empty()) {
-			throw std::runtime_error("failed to find GPUs with Vulkan support!");
+			vkcv_log(LogLevel::ERROR, "Failed to find GPUs with Vulkan support");
+			return false;
 		}
 		
 		int max_score = -1;
@@ -140,15 +141,16 @@ namespace vkcv
 			int score = deviceScore(device);
 			if (score > max_score) {
 				max_score = score;
-				phyDevice = device;
+				physicalDevice = device;
 			}
 		}
 		
 		if (max_score == -1) {
-			throw std::runtime_error("failed to find a suitable GPU!");
+			vkcv_log(LogLevel::ERROR, "Failed to find a suitable GPU");
+			return false;
+		} else {
+			return true;
 		}
-		
-		return phyDevice;
 	}
 	
 	/**
@@ -260,7 +262,11 @@ namespace vkcv
 		vk::Instance instance = vk::createInstance(instanceCreateInfo);
 		
 		std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
-		vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance);
+		vk::PhysicalDevice physicalDevice;
+		
+		if (!pickPhysicalDevice(instance, physicalDevice)) {
+			throw std::runtime_error("Picking suitable GPU as physical device failed!");
+		}
 		
 		FeatureManager featureManager (physicalDevice);
 		
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index ccbdf85f63cf5bc598d18511028ec1f154bf6fd2..21435c818451d1bea796b862cbb57ebeea8f0abd 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -8,7 +8,8 @@
 
 #include "vkcv/Core.hpp"
 #include "PassManager.hpp"
-#include "PipelineManager.hpp"
+#include "GraphicsPipelineManager.hpp"
+#include "ComputePipelineManager.hpp"
 #include "vkcv/BufferManager.hpp"
 #include "SamplerManager.hpp"
 #include "ImageManager.hpp"
@@ -51,7 +52,8 @@ namespace vkcv
     Core::Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
             m_Context(std::move(context)),
             m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)},
-            m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
+            m_PipelineManager{std::make_unique<GraphicsPipelineManager>(m_Context.m_Device)},
+            m_ComputePipelineManager{std::make_unique<ComputePipelineManager>(m_Context.m_Device)},
             m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)),
             m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())},
             m_SamplerManager(std::unique_ptr<SamplerManager>(new SamplerManager(m_Context.m_Device))),
@@ -75,17 +77,15 @@ namespace vkcv
 		destroyCommandResources(m_Context.getDevice(), m_CommandResources);
 		destroySyncResources(m_Context.getDevice(), m_SyncResources);
 	}
-
-    PipelineHandle Core::createGraphicsPipeline(const PipelineConfig &config)
+	
+	GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config)
     {
         return m_PipelineManager->createPipeline(config, *m_PassManager);
     }
 
-    PipelineHandle Core::createComputePipeline(
-        const ShaderProgram &shaderProgram, 
-        const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts)
+    ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config)
     {
-        return m_PipelineManager->createComputePipeline(shaderProgram, descriptorSetLayouts);
+        return m_ComputePipelineManager->createComputePipeline(config);
     }
 
     PassHandle Core::createPass(const PassConfig &config)
@@ -265,7 +265,7 @@ namespace vkcv
 	void Core::recordDrawcallsToCmdStream(
 		const CommandStreamHandle&      cmdStreamHandle,
 		const PassHandle&               renderpassHandle,
-		const PipelineHandle            pipelineHandle, 
+		const GraphicsPipelineHandle    &pipelineHandle,
         const PushConstants             &pushConstantData,
         const std::vector<DrawcallInfo> &drawcalls,
 		const std::vector<ImageHandle>  &renderTargets,
@@ -310,7 +310,7 @@ namespace vkcv
 
 			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
 
-			const PipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
+			const GraphicsPipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
 			if (pipeConfig.m_UseDynamicViewport) {
 				recordDynamicViewport(cmdBuffer, width, height);
 			}
@@ -333,7 +333,7 @@ namespace vkcv
 	void Core::recordMeshShaderDrawcalls(
 		const CommandStreamHandle&                          cmdStreamHandle,
 		const PassHandle&                                   renderpassHandle,
-		const PipelineHandle                                pipelineHandle,
+		const GraphicsPipelineHandle                        &pipelineHandle,
 		const PushConstants&                                pushConstantData,
 		const std::vector<MeshShaderDrawcall>&              drawcalls,
 		const std::vector<ImageHandle>&                     renderTargets,
@@ -378,7 +378,7 @@ namespace vkcv
 
 			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
 
-			const PipelineConfig& pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
+			const GraphicsPipelineConfig& pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
 			if (pipeConfig.m_UseDynamicViewport) {
 				recordDynamicViewport(cmdBuffer, width, height);
 			}
@@ -407,16 +407,16 @@ namespace vkcv
 
 	void Core::recordComputeDispatchToCmdStream(
 		CommandStreamHandle cmdStreamHandle,
-		PipelineHandle computePipeline,
+		ComputePipelineHandle computePipeline,
 		const uint32_t dispatchCount[3],
 		const std::vector<DescriptorSetUsage>& descriptorSetUsages,
 		const PushConstants& pushConstants) {
 
 		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
 
-			const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline);
+			const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline);
 
-			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline));
+			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline));
 			for (const auto& usage : descriptorSetUsages) {
 				cmdBuffer.bindDescriptorSets(
 					vk::PipelineBindPoint::eCompute,
@@ -485,7 +485,7 @@ namespace vkcv
 	
 	void Core::recordComputeIndirectDispatchToCmdStream(
 		const CommandStreamHandle               cmdStream,
-		const PipelineHandle                    computePipeline,
+		const ComputePipelineHandle             computePipeline,
 		const vkcv::BufferHandle                buffer,
 		const size_t                            bufferArgOffset,
 		const std::vector<DescriptorSetUsage>&  descriptorSetUsages,
@@ -493,9 +493,9 @@ namespace vkcv
 
 		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
 
-			const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline);
+			const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline);
 
-			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline));
+			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline));
 			for (const auto& usage : descriptorSetUsages) {
 				cmdBuffer.bindDescriptorSets(
 					vk::PipelineBindPoint::eCompute,
@@ -907,7 +907,7 @@ namespace vkcv
 		);
 	}
 	
-	void Core::setDebugLabel(const PipelineHandle &handle, const std::string &label) {
+	void Core::setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label) {
 		if (!handle) {
 			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
 			return;
@@ -923,6 +923,22 @@ namespace vkcv
 		);
 	}
 	
+	void Core::setDebugLabel(const ComputePipelineHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::ePipeline,
+				uint64_t(static_cast<VkPipeline>(
+								 m_ComputePipelineManager->getVkPipeline(handle)
+						 )),
+				label
+		);
+	}
+	
 	void Core::setDebugLabel(const DescriptorSetHandle &handle, const std::string &label) {
 		if (!handle) {
 			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index 60e2b6622b36e170963ccc3c86dc6f9ac58f2761..b8d50c21c288735fa621d7d158493e0eb4fab4b0 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -49,7 +49,7 @@ namespace vkcv
 
     DescriptorSetLayoutHandle DescriptorManager::createDescriptorSetLayout(const DescriptorBindings &setBindingsMap)
     {
-        for (auto i = 0; i < m_DescriptorSetLayouts.size(); i++)
+        for (size_t i = 0; i < m_DescriptorSetLayouts.size(); i++)
         {
             if(m_DescriptorSetLayouts[i].descriptorBindings.size() != setBindingsMap.size())
                 continue;
@@ -296,7 +296,7 @@ namespace vkcv
 	}
 
 	void DescriptorManager::destroyDescriptorSetLayoutById(uint64_t id) {
-	    if (id >= m_DescriptorSets.size()) {
+	    if (id >= m_DescriptorSetLayouts.size()) {
 	        vkcv_log(LogLevel::ERROR, "Invalid id");
 	        return;
 	    }
diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp
index 18307999bb28ed60791a801b952619eeeba51a53..cfe8464d3fe3d0eedda2182e8e678e93c13dbf7a 100644
--- a/src/vkcv/FeatureManager.cpp
+++ b/src/vkcv/FeatureManager.cpp
@@ -395,6 +395,10 @@ m_physicalDevice.getFeatures2(&query)
 					 extension.c_str());
 			
 			delete[] clone;
+			if (required) {
+				throw std::runtime_error("Required extension is not supported!");
+			}
+			
 			return false;
 		}
 		
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb7dd31dddd3a5c0742f95e8429175724aa26454
--- /dev/null
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -0,0 +1,681 @@
+#include "GraphicsPipelineManager.hpp"
+#include "vkcv/Image.hpp"
+#include "vkcv/Logger.hpp"
+
+namespace vkcv
+{
+	
+	GraphicsPipelineManager::GraphicsPipelineManager(vk::Device device) noexcept :
+            m_Device{device},
+            m_Pipelines{}
+    {}
+	
+	GraphicsPipelineManager::~GraphicsPipelineManager() noexcept
+    {
+        for (uint64_t id = 0; id < m_Pipelines.size(); id++) {
+            destroyPipelineById(id);
+        }
+    }
+
+    // currently assuming default 32 bit formats, no lower precision or normalized variants supported
+    vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) {
+        switch (format) {
+            case VertexAttachmentFormat::FLOAT:
+                return vk::Format::eR32Sfloat;
+            case VertexAttachmentFormat::FLOAT2:
+                return vk::Format::eR32G32Sfloat;
+            case VertexAttachmentFormat::FLOAT3:
+                return vk::Format::eR32G32B32Sfloat;
+            case VertexAttachmentFormat::FLOAT4:
+                return vk::Format::eR32G32B32A32Sfloat;
+            case VertexAttachmentFormat::INT:
+                return vk::Format::eR32Sint;
+            case VertexAttachmentFormat::INT2:
+                return vk::Format::eR32G32Sint;
+            case VertexAttachmentFormat::INT3:
+                return vk::Format::eR32G32B32Sint;
+            case VertexAttachmentFormat::INT4:
+                return vk::Format::eR32G32B32A32Sint;
+            default:
+            vkcv_log(LogLevel::WARNING, "Unknown vertex format");
+                return vk::Format::eUndefined;
+        }
+    }
+
+    vk::PrimitiveTopology primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) {
+        switch (topology) {
+            case(PrimitiveTopology::PointList):
+                return vk::PrimitiveTopology::ePointList;
+            case(PrimitiveTopology::LineList):
+                return vk::PrimitiveTopology::eLineList;
+            case(PrimitiveTopology::TriangleList):
+                return vk::PrimitiveTopology::eTriangleList;
+            default:
+            vkcv_log(LogLevel::ERROR, "Unknown primitive topology type");
+                return vk::PrimitiveTopology::eTriangleList;
+        }
+    }
+
+    vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) {
+        switch (depthTest) {
+            case(DepthTest::None):
+                return vk::CompareOp::eAlways;
+            case(DepthTest::Less):
+                return vk::CompareOp::eLess;
+            case(DepthTest::LessEqual):
+                return vk::CompareOp::eLessOrEqual;
+            case(DepthTest::Greater):
+                return vk::CompareOp::eGreater;
+            case(DepthTest::GreatherEqual):
+                return vk::CompareOp::eGreaterOrEqual;
+            case(DepthTest::Equal):
+                return vk::CompareOp::eEqual;
+            default:
+                vkcv_log(LogLevel::ERROR, "Unknown depth test enum");
+                return vk::CompareOp::eAlways;
+        }
+    }
+
+    vk::ShaderStageFlagBits shaderStageToVkShaderStage(ShaderStage stage) {
+        switch (stage) {
+            case ShaderStage::VERTEX:
+                return vk::ShaderStageFlagBits::eVertex;
+            case ShaderStage::FRAGMENT:
+                return vk::ShaderStageFlagBits::eFragment;
+            case ShaderStage::GEOMETRY:
+                return vk::ShaderStageFlagBits::eGeometry;
+            case ShaderStage::TESS_CONTROL:
+                return vk::ShaderStageFlagBits::eTessellationControl;
+            case ShaderStage::TESS_EVAL:
+                return vk::ShaderStageFlagBits::eTessellationEvaluation;
+            case ShaderStage::COMPUTE:
+                return vk::ShaderStageFlagBits::eCompute;
+            case ShaderStage::TASK:
+                return vk::ShaderStageFlagBits::eTaskNV;
+            case ShaderStage::MESH:
+                return vk::ShaderStageFlagBits::eMeshNV;
+            default:
+                vkcv_log(LogLevel::ERROR, "Unknown shader stage");
+                return vk::ShaderStageFlagBits::eAll;
+        }
+    }
+
+    bool createPipelineShaderStageCreateInfo(
+            const ShaderProgram&          shaderProgram,
+            ShaderStage                         stage,
+            vk::Device                          device,
+            vk::PipelineShaderStageCreateInfo*  outCreateInfo) {
+
+        assert(outCreateInfo);
+        std::vector<char>           code = shaderProgram.getShader(stage).shaderCode;
+        vk::ShaderModuleCreateInfo  vertexModuleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
+        vk::ShaderModule            shaderModule;
+        if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess)
+            return false;
+
+        const static auto entryName = "main";
+
+        *outCreateInfo = vk::PipelineShaderStageCreateInfo(
+                {},
+                shaderStageToVkShaderStage(stage),
+                shaderModule,
+                entryName,
+                nullptr);
+        return true;
+    }
+	
+	/**
+	 * Fills Vertex Attribute and Binding Description with the corresponding objects form the Vertex Layout.
+	 * @param vertexAttributeDescriptions
+	 * @param vertexBindingDescriptions
+	 * @param existsVertexShader
+	 * @param config
+	 */
+	void fillVertexInputDescription(
+			std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
+			std::vector<vk::VertexInputBindingDescription>   &vertexBindingDescriptions,
+			const bool existsVertexShader,
+			const GraphicsPipelineConfig &config) {
+		
+		if (existsVertexShader) {
+			const VertexLayout& layout = config.m_VertexLayout;
+			
+			// iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer
+			for (const auto& vertexBinding : layout.vertexBindings)
+			{
+				vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation,
+													   vertexBinding.stride,
+													   vk::VertexInputRate::eVertex);
+				
+				// iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex
+				for (const auto& vertexAttachment : vertexBinding.vertexAttachments)
+				{
+					vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation,
+															 vertexBinding.bindingLocation,
+															 vertexFormatToVulkanFormat(vertexAttachment.format),
+															 vertexAttachment.offset % vertexBinding.stride);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Creates a Pipeline Vertex Input State Create Info Struct and fills it with Attribute and Binding data.
+	 * @param vertexAttributeDescriptions
+	 * @param vertexBindingDescriptions
+	 * @return Pipeline Vertex Input State Create Info Struct
+	 */
+	vk::PipelineVertexInputStateCreateInfo createPipelineVertexInputStateCreateInfo(
+			std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
+			std::vector<vk::VertexInputBindingDescription>   &vertexBindingDescriptions) {
+		
+		vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
+				{},
+				vertexBindingDescriptions.size(),
+				vertexBindingDescriptions.data(),
+				vertexAttributeDescriptions.size(),
+				vertexAttributeDescriptions.data()
+		);
+		return pipelineVertexInputStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Input Assembly State Create Info Struct with 'Primitive Restart' disabled.
+	 * @param config provides data for primitive topology.
+	 * @return Pipeline Input Assembly State Create Info Struct
+	 */
+	vk::PipelineInputAssemblyStateCreateInfo createPipelineInputAssemblyStateCreateInfo(const GraphicsPipelineConfig &config) {
+		vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
+				{},
+				primitiveTopologyToVulkanPrimitiveTopology(config.m_PrimitiveTopology),
+				false
+		);
+		
+		return pipelineInputAssemblyStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Viewport State Create Info Struct with default set viewport and scissor settings.
+	 * @param config provides with and height of the output window
+	 * @return Pipeline Viewport State Create Info Struct
+	 */
+	vk::PipelineViewportStateCreateInfo createPipelineViewportStateCreateInfo(const GraphicsPipelineConfig &config) {
+		static vk::Viewport viewport;
+		static vk::Rect2D scissor;
+		
+		viewport = vk::Viewport(
+				0.f, 0.f,
+				static_cast<float>(config.m_Width),
+				static_cast<float>(config.m_Height),
+				0.f, 1.f
+		);
+		
+		scissor = vk::Rect2D(
+				{ 0,0 },
+				{ config.m_Width, config.m_Height }
+		);
+		
+		vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
+				{},
+				1,
+				&viewport,
+				1,
+				&scissor
+		);
+		
+		return pipelineViewportStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Rasterization State Create Info Struct with default values set to:
+	 * Rasterizer Discard: Disabled
+	 * Polygon Mode: Fill
+	 * Front Face: Counter Clockwise
+	 * Depth Bias: Disabled
+	 * Line Width: 1.0
+	 * Depth Clamping and Culling Mode ist set by the Pipeline Config
+	 * @param config sets Depth Clamping and Culling Mode
+	 * @return Pipeline Rasterization State Create Info Struct
+	 */
+	vk::PipelineRasterizationStateCreateInfo createPipelineRasterizationStateCreateInfo(const GraphicsPipelineConfig &config) {
+		vk::CullModeFlags cullMode;
+		switch (config.m_culling) {
+			case CullMode::None:
+				cullMode = vk::CullModeFlagBits::eNone;
+				break;
+			case CullMode::Front:
+				cullMode = vk::CullModeFlagBits::eFront;
+				break;
+			case CullMode::Back:
+				cullMode = vk::CullModeFlagBits::eBack;
+				break;
+			default:
+			vkcv_log(LogLevel::ERROR, "Unknown CullMode");
+				cullMode = vk::CullModeFlagBits::eNone;
+		}
+		
+		vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo (
+				{},
+				config.m_EnableDepthClamping,
+				false,
+				vk::PolygonMode::eFill,
+				cullMode,
+				vk::FrontFace::eCounterClockwise,
+				false,
+				0.f,
+				0.f,
+				0.f,
+				1.f
+		);
+		
+		static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization;
+		
+		if (config.m_UseConservativeRasterization) {
+			conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT(
+					{},
+					vk::ConservativeRasterizationModeEXT::eOverestimate,
+					0.f
+			);
+			
+			pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization;
+		}
+		
+		return pipelineRasterizationStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Multisample State Create Info Struct.
+	 * @param config set MSAA Sample Count Flag
+	 * @return Pipeline Multisample State Create Info Struct
+	 */
+	vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config) {
+		vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
+				{},
+				msaaToVkSampleCountFlag(config.m_multisampling),
+				false,
+				0.f,
+				nullptr,
+				config.m_alphaToCoverage,
+				false
+		);
+		
+		return pipelineMultisampleStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Color Blend State Create Info Struct.
+	 * Currently only one blend mode is supported! There for, blending is set to additive.
+	 * @param config sets blend mode
+	 * @return
+	 */
+	vk::PipelineColorBlendStateCreateInfo createPipelineColorBlendStateCreateInfo(const GraphicsPipelineConfig &config) {
+		// currently set to additive, if not disabled
+		// BlendFactors must be set as soon as additional BlendModes are added
+		static vk::PipelineColorBlendAttachmentState colorBlendAttachmentState (
+				config.m_blendMode != BlendMode::None,
+				vk::BlendFactor::eOne,
+				vk::BlendFactor::eOne,
+				vk::BlendOp::eAdd,
+				vk::BlendFactor::eOne,
+				vk::BlendFactor::eOne,
+				vk::BlendOp::eAdd,
+				vk::ColorComponentFlags(
+						VK_COLOR_COMPONENT_R_BIT |
+						VK_COLOR_COMPONENT_G_BIT |
+						VK_COLOR_COMPONENT_B_BIT |
+						VK_COLOR_COMPONENT_A_BIT
+				)
+		);
+		
+		vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(
+				{},
+				false,
+				vk::LogicOp::eClear,
+				1,	//TODO: hardcoded to one
+				&colorBlendAttachmentState,
+				{ 1.f,1.f,1.f,1.f }
+		);
+		
+		return pipelineColorBlendStateCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Layout Create Info Struct.
+	 * @param config sets Push Constant Size and Descriptor Layouts.
+	 * @return Pipeline Layout Create Info Struct
+	 */
+	vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(const GraphicsPipelineConfig &config) {
+		static vk::PushConstantRange pushConstantRange;
+		
+		const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize();
+		pushConstantRange = vk::PushConstantRange(
+				vk::ShaderStageFlagBits::eAll, 0, pushConstantSize
+		);
+		
+		vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo(
+				{},
+				(config.m_DescriptorLayouts),
+				(pushConstantRange)
+		);
+		
+		if (pushConstantSize == 0) {
+			pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
+		}
+		
+		return pipelineLayoutCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Depth Stencil State Create Info Struct.
+	 * @param config sets if depth test in enabled or not.
+	 * @return Pipeline Layout Create Info Struct
+	 */
+	vk::PipelineDepthStencilStateCreateInfo createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) {
+		const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo(
+				vk::PipelineDepthStencilStateCreateFlags(),
+				config.m_depthTest != DepthTest::None,
+				config.m_depthWrite,
+				depthTestToVkCompareOp(config.m_depthTest),
+				false,
+				false,
+				{},
+				{},
+				0.0f,
+				1.0f
+		);
+		
+		return pipelineDepthStencilCreateInfo;
+	}
+	
+	/**
+	 * Creates a Pipeline Dynamic State Create Info Struct.
+	 * @param config sets whenever a dynamic viewport is used or not.
+	 * @return Pipeline Dynamic State Create Info Struct
+	 */
+	vk::PipelineDynamicStateCreateInfo createPipelineDynamicStateCreateInfo(const GraphicsPipelineConfig &config) {
+		static std::vector<vk::DynamicState> dynamicStates;
+		dynamicStates.clear();
+		
+		if(config.m_UseDynamicViewport) {
+			dynamicStates.push_back(vk::DynamicState::eViewport);
+			dynamicStates.push_back(vk::DynamicState::eScissor);
+		}
+		
+		vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo(
+				{},
+				static_cast<uint32_t>(dynamicStates.size()),
+				dynamicStates.data()
+		);
+		
+		return dynamicStateCreateInfo;
+	}
+
+    GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager) {
+        const vk::RenderPass &pass = passManager.getVkPass(config.m_PassHandle);
+
+        const bool existsTaskShader     = config.m_ShaderProgram.existsShader(ShaderStage::TASK);
+        const bool existsMeshShader     = config.m_ShaderProgram.existsShader(ShaderStage::MESH);
+        const bool existsVertexShader   = config.m_ShaderProgram.existsShader(ShaderStage::VERTEX);
+        const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT);
+        const bool existsGeometryShader = config.m_ShaderProgram.existsShader(ShaderStage::GEOMETRY);
+        const bool validGeometryStages  = existsVertexShader || (existsTaskShader && existsMeshShader);
+
+        if (!validGeometryStages)
+        {
+            vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader");
+            return GraphicsPipelineHandle();
+        }
+
+        if (!existsFragmentShader) {
+            vkcv_log(LogLevel::ERROR, "Requires fragment shader code");
+            return GraphicsPipelineHandle();
+        }
+
+        std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
+        auto destroyShaderModules = [&shaderStages, this] {
+            for (auto stage : shaderStages) {
+                m_Device.destroyShaderModule(stage.module);
+            }
+            shaderStages.clear();
+        };
+
+        if (existsVertexShader) {
+            vk::PipelineShaderStageCreateInfo createInfo;
+            const bool success = createPipelineShaderStageCreateInfo(
+                    config.m_ShaderProgram,
+                    ShaderStage::VERTEX,
+                    m_Device,
+                    &createInfo);
+
+            if (success) {
+                shaderStages.push_back(createInfo);
+            }
+            else {
+                destroyShaderModules();
+                return GraphicsPipelineHandle();
+            }
+        }
+
+        if (existsTaskShader) {
+            vk::PipelineShaderStageCreateInfo createInfo;
+            const bool success = createPipelineShaderStageCreateInfo(
+                    config.m_ShaderProgram,
+                    ShaderStage::TASK,
+                    m_Device,
+                    &createInfo);
+
+            if (success) {
+                shaderStages.push_back(createInfo);
+            }
+            else {
+                destroyShaderModules();
+                return GraphicsPipelineHandle();
+            }
+        }
+
+        if (existsMeshShader) {
+            vk::PipelineShaderStageCreateInfo createInfo;
+            const bool success = createPipelineShaderStageCreateInfo(
+                    config.m_ShaderProgram,
+                    ShaderStage::MESH,
+                    m_Device,
+                    &createInfo);
+
+            if (success) {
+                shaderStages.push_back(createInfo);
+            }
+            else {
+                destroyShaderModules();
+                return GraphicsPipelineHandle();
+            }
+        }
+
+        {
+            vk::PipelineShaderStageCreateInfo createInfo;
+            const bool success = createPipelineShaderStageCreateInfo(
+                    config.m_ShaderProgram,
+                    ShaderStage::FRAGMENT,
+                    m_Device,
+                    &createInfo);
+
+            if (success) {
+                shaderStages.push_back(createInfo);
+            }
+            else {
+                destroyShaderModules();
+                return GraphicsPipelineHandle();
+            }
+        }
+
+        if (existsGeometryShader) {
+            vk::PipelineShaderStageCreateInfo createInfo;
+            const bool success = createPipelineShaderStageCreateInfo(
+                    config.m_ShaderProgram,
+                    ShaderStage::GEOMETRY,
+                    m_Device,
+                    &createInfo);
+
+            if (success) {
+                shaderStages.push_back(createInfo);
+            }
+            else {
+                destroyShaderModules();
+                return GraphicsPipelineHandle();
+            }
+        }
+
+        // vertex input state
+        // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers
+        std::vector<vk::VertexInputAttributeDescription>	vertexAttributeDescriptions;
+        std::vector<vk::VertexInputBindingDescription>		vertexBindingDescriptions;
+        fillVertexInputDescription(vertexAttributeDescriptions, vertexBindingDescriptions, existsVertexShader, config);
+
+        // Handover Containers to PipelineVertexInputStateCreateIngo Struct
+        vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo =
+                createPipelineVertexInputStateCreateInfo(vertexAttributeDescriptions,
+                                                         vertexBindingDescriptions);
+
+        // input assembly state
+        vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo =
+                createPipelineInputAssemblyStateCreateInfo(config);
+
+        // viewport state
+        vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo =
+                createPipelineViewportStateCreateInfo(config);
+
+        // rasterization state
+        vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo =
+                createPipelineRasterizationStateCreateInfo(config);
+
+        // multisample state
+        vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
+                createPipelineMultisampleStateCreateInfo(config);
+
+        // color blend state
+        vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo =
+                createPipelineColorBlendStateCreateInfo(config);
+
+        // Dynamic State
+        vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo =
+                createPipelineDynamicStateCreateInfo(config);
+
+        // pipeline layout
+        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo =
+                createPipelineLayoutCreateInfo(config);
+
+        vk::PipelineLayout vkPipelineLayout{};
+        if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) {
+            destroyShaderModules();
+            return GraphicsPipelineHandle();
+        }
+
+        // Depth Stencil
+        const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo =
+                createPipelineDepthStencilStateCreateInfo(config);
+
+        const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr;
+        const PassConfig& passConfig = passManager.getPassConfig(config.m_PassHandle);
+
+        for (const auto& attachment : passConfig.attachments) {
+            if (isDepthFormat(attachment.format)) {
+                p_depthStencilCreateInfo = &depthStencilCreateInfo;
+                break;
+            }
+        }
+
+        // Get all setting structs together and create the Pipeline
+        const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(
+                {},
+                static_cast<uint32_t>(shaderStages.size()),
+                shaderStages.data(),
+                &pipelineVertexInputStateCreateInfo,
+                &pipelineInputAssemblyStateCreateInfo,
+                nullptr,
+                &pipelineViewportStateCreateInfo,
+                &pipelineRasterizationStateCreateInfo,
+                &pipelineMultisampleStateCreateInfo,
+                p_depthStencilCreateInfo,
+                &pipelineColorBlendStateCreateInfo,
+                &dynamicStateCreateInfo,
+                vkPipelineLayout,
+                pass,
+                0,
+                {},
+                0
+        );
+
+        vk::Pipeline vkPipeline{};
+        if (m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess)
+        {
+            // Catch runtime error if the creation of the pipeline fails.
+            // Destroy everything to keep the memory clean.
+            destroyShaderModules();
+            return GraphicsPipelineHandle();
+        }
+
+        // Clean Up
+        destroyShaderModules();
+
+        // Hand over Handler to main Application
+        const uint64_t id = m_Pipelines.size();
+        m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, config });
+        return GraphicsPipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
+    }
+
+    vk::Pipeline GraphicsPipelineManager::getVkPipeline(const GraphicsPipelineHandle &handle) const
+    {
+        const uint64_t id = handle.getId();
+
+        if (id >= m_Pipelines.size()) {
+            return nullptr;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        return pipeline.m_handle;
+    }
+
+    vk::PipelineLayout GraphicsPipelineManager::getVkPipelineLayout(const GraphicsPipelineHandle &handle) const
+    {
+        const uint64_t id = handle.getId();
+
+        if (id >= m_Pipelines.size()) {
+            return nullptr;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        return pipeline.m_layout;
+    }
+
+    void GraphicsPipelineManager::destroyPipelineById(uint64_t id) {
+        if (id >= m_Pipelines.size()) {
+            return;
+        }
+
+        auto& pipeline = m_Pipelines[id];
+
+        if (pipeline.m_handle) {
+            m_Device.destroy(pipeline.m_handle);
+            pipeline.m_handle = nullptr;
+        }
+
+        if (pipeline.m_layout) {
+            m_Device.destroy(pipeline.m_layout);
+            pipeline.m_layout = nullptr;
+        }
+    }
+
+    const GraphicsPipelineConfig& GraphicsPipelineManager::getPipelineConfig(const GraphicsPipelineHandle &handle) const
+    {
+        const uint64_t id = handle.getId();
+
+        if (id >= m_Pipelines.size()) {
+            static GraphicsPipelineConfig dummyConfig;
+            vkcv_log(LogLevel::ERROR, "Invalid handle");
+            return dummyConfig;
+        }
+
+        return m_Pipelines[id].m_config;
+    }
+}
diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a08e64939dc967511095f22862c52de05148d7e9
--- /dev/null
+++ b/src/vkcv/GraphicsPipelineManager.hpp
@@ -0,0 +1,80 @@
+#pragma once
+
+/**
+ * @authors Mark Mints
+ * @file src/vkcv/PipelineManager.hpp
+ * @brief Creation and handling of Graphic Pipelines
+ */
+// TODO: Edit @brief: add graphics pipeline, but only then when the compute part is in an own class.
+// TODO: More authors? Do we need authors (general question)?
+
+#include <vulkan/vulkan.hpp>
+#include <vector>
+#include "vkcv/Handles.hpp"
+#include "vkcv/GraphicsPipelineConfig.hpp"
+#include "PassManager.hpp"
+
+namespace vkcv
+{
+    class GraphicsPipelineManager
+    {
+    public:
+		GraphicsPipelineManager() = delete; // no default ctor
+        explicit GraphicsPipelineManager(vk::Device device) noexcept; // ctor
+        ~GraphicsPipelineManager() noexcept; // dtor
+	
+		GraphicsPipelineManager(const GraphicsPipelineManager &other) = delete; // copy-ctor
+		GraphicsPipelineManager(GraphicsPipelineManager &&other) = delete; // move-ctor;
+	
+		GraphicsPipelineManager & operator=(const GraphicsPipelineManager &other) = delete; // copy-assign op
+		GraphicsPipelineManager & operator=(GraphicsPipelineManager &&other) = delete; // move-assign op
+
+        /**
+         * Creates a Graphics Pipeline based on the set shader stages in the Config Struct.
+         * This function is wrapped in /src/vkcv/Core.cpp by Core::createGraphicsPipeline(const PipelineConfig &config).
+         * Therefore the passManager is filled already by the overall context of an application.
+         * On application level it is necessary first to fill a PipelineConfig Struct.
+         * @param config Hands over all needed information for pipeline creation.
+         * @param passManager Hands over the corresponding render pass.
+         * @return A Handler to the created Graphics Pipeline Object.
+         */
+		GraphicsPipelineHandle createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager);
+
+        /**
+         * Returns a vk::Pipeline object by handle.
+         * @param handle Directing to the requested pipeline.
+         * @return vk::Pipeline.
+         */
+        [[nodiscard]]
+        vk::Pipeline getVkPipeline(const GraphicsPipelineHandle &handle) const;
+
+        /**
+         * Returns a vk::PipelineLayout object by handle.
+         * @param handle Directing to the requested pipeline.
+         * @return vk::PipelineLayout.
+         */
+        [[nodiscard]]
+        vk::PipelineLayout getVkPipelineLayout(const GraphicsPipelineHandle &handle) const;
+
+        /**
+         * Returns the corresponding Pipeline Config Struct of a pipeline object directed by the given Handler.
+         * @param handle Directing to the requested pipeline.
+         * @return Pipeline Config Struct
+         */
+        [[nodiscard]]
+        const GraphicsPipelineConfig &getPipelineConfig(const GraphicsPipelineHandle &handle) const;
+
+    private:
+        struct GraphicsPipeline {
+            vk::Pipeline m_handle;
+            vk::PipelineLayout m_layout;
+			GraphicsPipelineConfig m_config;
+        };
+
+        vk::Device m_Device;
+        std::vector<GraphicsPipeline> m_Pipelines;
+
+        void destroyPipelineById(uint64_t id);
+
+    };
+}
diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp
index e50f800a482460cdb81687c76f8b1318598f689c..5eb727c75f9ec7e6f4cc3fa8fd8118a1a05f036f 100644
--- a/src/vkcv/PassManager.cpp
+++ b/src/vkcv/PassManager.cpp
@@ -3,26 +3,6 @@
 
 namespace vkcv
 {
-    static vk::ImageLayout getVkLayoutFromAttachLayout(AttachmentLayout layout)
-    {
-        switch(layout)
-        {
-            case AttachmentLayout::GENERAL:
-                return vk::ImageLayout::eGeneral;
-            case AttachmentLayout::COLOR_ATTACHMENT:
-                return vk::ImageLayout::eColorAttachmentOptimal;
-            case AttachmentLayout::SHADER_READ_ONLY:
-                return vk::ImageLayout::eShaderReadOnlyOptimal;
-            case AttachmentLayout::DEPTH_STENCIL_ATTACHMENT:
-                return vk::ImageLayout::eDepthStencilAttachmentOptimal;
-            case AttachmentLayout::DEPTH_STENCIL_READ_ONLY:
-                return vk::ImageLayout::eDepthStencilReadOnlyOptimal;
-            case AttachmentLayout::PRESENTATION:
-                return vk::ImageLayout::ePresentSrcKHR;
-            default:
-                return vk::ImageLayout::eUndefined;
-        }
-    }
 
     static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op)
     {
diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp
deleted file mode 100644
index 244f6723f70e5ea938c005b74b286e192d68443c..0000000000000000000000000000000000000000
--- a/src/vkcv/PipelineManager.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-#include "PipelineManager.hpp"
-#include "vkcv/Image.hpp"
-#include "vkcv/Logger.hpp"
-
-namespace vkcv
-{
-
-    PipelineManager::PipelineManager(vk::Device device) noexcept :
-    m_Device{device},
-    m_Pipelines{}
-    {}
-
-    PipelineManager::~PipelineManager() noexcept
-    {
-    	for (uint64_t id = 0; id < m_Pipelines.size(); id++) {
-			destroyPipelineById(id);
-    	}
-    }
-
-	// currently assuming default 32 bit formats, no lower precision or normalized variants supported
-	vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) {
-		switch (format) {
-		case VertexAttachmentFormat::FLOAT:
-			return vk::Format::eR32Sfloat;
-		case VertexAttachmentFormat::FLOAT2:
-			return vk::Format::eR32G32Sfloat;
-		case VertexAttachmentFormat::FLOAT3:
-			return vk::Format::eR32G32B32Sfloat;
-		case VertexAttachmentFormat::FLOAT4:
-			return vk::Format::eR32G32B32A32Sfloat;
-		case VertexAttachmentFormat::INT:
-			return vk::Format::eR32Sint;
-		case VertexAttachmentFormat::INT2:
-			return vk::Format::eR32G32Sint;
-		case VertexAttachmentFormat::INT3:
-			return vk::Format::eR32G32B32Sint;
-		case VertexAttachmentFormat::INT4:
-			return vk::Format::eR32G32B32A32Sint;
-		default:
-			vkcv_log(LogLevel::WARNING, "Unknown vertex format");
-			return vk::Format::eUndefined;
-		}
-	}
-
-    vk::PrimitiveTopology primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) {
-        switch (topology) {
-            case(PrimitiveTopology::PointList):     return vk::PrimitiveTopology::ePointList;
-            case(PrimitiveTopology::LineList):      return vk::PrimitiveTopology::eLineList;
-            case(PrimitiveTopology::TriangleList):  return vk::PrimitiveTopology::eTriangleList;
-            default: std::cout << "Error: Unknown primitive topology type" << std::endl; return vk::PrimitiveTopology::eTriangleList;
-        }
-    }
-
-    vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) {
-        switch (depthTest) {
-            case(DepthTest::None):          return vk::CompareOp::eAlways;
-            case(DepthTest::Less):          return vk::CompareOp::eLess;
-            case(DepthTest::LessEqual):     return vk::CompareOp::eLessOrEqual;
-            case(DepthTest::Greater):       return vk::CompareOp::eGreater;
-            case(DepthTest::GreatherEqual): return vk::CompareOp::eGreaterOrEqual;
-            case(DepthTest::Equal):         return vk::CompareOp::eEqual;
-            default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown depth test enum"); return vk::CompareOp::eAlways;
-        }
-    }
-        
-	vk::ShaderStageFlagBits shaderStageToVkShaderStage(vkcv::ShaderStage stage) {
-		switch (stage) {
-            case vkcv::ShaderStage::VERTEX:         return vk::ShaderStageFlagBits::eVertex;
-            case vkcv::ShaderStage::FRAGMENT:       return vk::ShaderStageFlagBits::eFragment;
-            case vkcv::ShaderStage::GEOMETRY:       return vk::ShaderStageFlagBits::eGeometry;
-            case vkcv::ShaderStage::TESS_CONTROL:   return vk::ShaderStageFlagBits::eTessellationControl;
-            case vkcv::ShaderStage::TESS_EVAL:      return vk::ShaderStageFlagBits::eTessellationEvaluation;
-            case vkcv::ShaderStage::COMPUTE:        return vk::ShaderStageFlagBits::eCompute;
-            case vkcv::ShaderStage::TASK:           return vk::ShaderStageFlagBits::eTaskNV;
-            case vkcv::ShaderStage::MESH:           return vk::ShaderStageFlagBits::eMeshNV;
-            default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown shader stage"); return vk::ShaderStageFlagBits::eAll;
-		}
-	}
-
-    bool createPipelineShaderStageCreateInfo(
-        const vkcv::ShaderProgram&          shaderProgram, 
-        ShaderStage                         stage,
-        vk::Device                          device,
-        vk::PipelineShaderStageCreateInfo*  outCreateInfo) {
-
-        assert(outCreateInfo);
-        std::vector<char>           code = shaderProgram.getShader(stage).shaderCode;
-        vk::ShaderModuleCreateInfo  vertexModuleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
-        vk::ShaderModule            shaderModule;
-        if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess)
-            return false;
-
-        const static auto entryName = "main";
-
-        *outCreateInfo = vk::PipelineShaderStageCreateInfo(
-            {},
-            shaderStageToVkShaderStage(stage),
-            shaderModule,
-            entryName,
-            nullptr);
-        return true;
-    }
-
-    PipelineHandle PipelineManager::createPipeline(const PipelineConfig &config, PassManager& passManager)
-    {
-		const vk::RenderPass &pass = passManager.getVkPass(config.m_PassHandle);
-    	
-		const bool existsTaskShader = config.m_ShaderProgram.existsShader(ShaderStage::TASK);
-		const bool existsMeshShader = config.m_ShaderProgram.existsShader(ShaderStage::MESH);
-
-        const bool existsVertexShader = config.m_ShaderProgram.existsShader(ShaderStage::VERTEX);
-
-        const bool validGeometryStages = existsVertexShader || (existsTaskShader && existsMeshShader);
-
-        const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT);
-        if (!validGeometryStages)
-        {
-			vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader");
-            return PipelineHandle();
-        }
-        if (!existsFragmentShader) {
-            vkcv_log(LogLevel::ERROR, "Requires fragment shader code");
-            return PipelineHandle();
-        }
-
-        std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
-        auto destroyShaderModules = [&shaderStages, this] {
-            for (auto stage : shaderStages) {
-                m_Device.destroyShaderModule(stage.module);
-            }
-            shaderStages.clear();
-        };
-
-        if (existsVertexShader) {
-            vk::PipelineShaderStageCreateInfo createInfo;
-            const bool success = createPipelineShaderStageCreateInfo(
-                config.m_ShaderProgram, 
-                vkcv::ShaderStage::VERTEX, 
-                m_Device, 
-                &createInfo);
-
-            if (success) {
-                shaderStages.push_back(createInfo);
-            }
-            else {
-                destroyShaderModules();
-                return PipelineHandle();
-            }
-        }
-
-        if (existsTaskShader) {
-            vk::PipelineShaderStageCreateInfo createInfo;
-            const bool success = createPipelineShaderStageCreateInfo(
-                config.m_ShaderProgram,
-                vkcv::ShaderStage::TASK,
-                m_Device,
-                &createInfo);
-
-            if (success) {
-                shaderStages.push_back(createInfo);
-            }
-            else {
-                destroyShaderModules();
-                return PipelineHandle();
-            }
-        }
-
-        if (existsMeshShader) {
-            vk::PipelineShaderStageCreateInfo createInfo;
-            const bool success = createPipelineShaderStageCreateInfo(
-                config.m_ShaderProgram,
-                vkcv::ShaderStage::MESH,
-                m_Device,
-                &createInfo);
-
-            if (success) {
-                shaderStages.push_back(createInfo);
-            }
-            else {
-                destroyShaderModules();
-                return PipelineHandle();
-            }
-        }
-
-        // fragment shader stage
-        {
-            vk::PipelineShaderStageCreateInfo createInfo;
-            const bool success = createPipelineShaderStageCreateInfo(
-                config.m_ShaderProgram,
-                vkcv::ShaderStage::FRAGMENT,
-                m_Device,
-                &createInfo);
-
-            if (success) {
-                shaderStages.push_back(createInfo);
-            }
-            else {
-                destroyShaderModules();
-                return PipelineHandle();
-            }
-        }
-
-        // vertex input state
-
-        // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers
-        std::vector<vk::VertexInputAttributeDescription>	vertexAttributeDescriptions;
-		std::vector<vk::VertexInputBindingDescription>		vertexBindingDescriptions;
-
-		if (existsVertexShader) {
-			const VertexLayout& layout = config.m_VertexLayout;
-
-			// iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer
-			for (const auto& vertexBinding : layout.vertexBindings)
-			{
-				vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation,
-					vertexBinding.stride,
-					vk::VertexInputRate::eVertex);
-
-				// iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex
-				for (const auto& vertexAttachment : vertexBinding.vertexAttachments)
-				{
-					vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation,
-						vertexBinding.bindingLocation,
-						vertexFormatToVulkanFormat(vertexAttachment.format),
-						vertexAttachment.offset % vertexBinding.stride);
-
-				}
-			}
-
-		}
-
-        // Handover Containers to PipelineVertexInputStateCreateIngo Struct
-        vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
-                {},
-                vertexBindingDescriptions.size(),
-                vertexBindingDescriptions.data(),
-                vertexAttributeDescriptions.size(),
-                vertexAttributeDescriptions.data()
-        );
-
-        // input assembly state
-        vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
-            {},
-            primitiveTopologyToVulkanPrimitiveTopology(config.m_PrimitiveTopology),
-            false
-        );
-
-        // viewport state
-        vk::Viewport viewport(0.f, 0.f, static_cast<float>(config.m_Width), static_cast<float>(config.m_Height), 0.f, 1.f);
-        vk::Rect2D scissor({ 0,0 }, { config.m_Width, config.m_Height });
-        vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, &scissor);
-
-        vk::CullModeFlags cullMode;
-        switch (config.m_culling) {
-            case CullMode::None:    cullMode = vk::CullModeFlagBits::eNone;     break;
-            case CullMode::Front:   cullMode = vk::CullModeFlagBits::eFront;    break;
-            case CullMode::Back:    cullMode = vk::CullModeFlagBits::eBack;     break;
-			default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown CullMode"); cullMode = vk::CullModeFlagBits::eNone;
-        }
-
-        // rasterization state
-        vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(
-                {},
-                config.m_EnableDepthClamping,
-                false,
-                vk::PolygonMode::eFill,
-                cullMode,
-                vk::FrontFace::eCounterClockwise,
-                false,
-                0.f,
-                0.f,
-                0.f,
-                1.f
-        );
-        vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization;
-        if (config.m_UseConservativeRasterization) {
-            conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT(
-                {}, 
-                vk::ConservativeRasterizationModeEXT::eOverestimate,
-                0.f);
-            pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization;
-        }
-
-        // multisample state
-        vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
-                {},
-                msaaToVkSampleCountFlag(config.m_multisampling),
-                false,
-                0.f,
-                nullptr,
-                config.m_alphaToCoverage,
-                false
-        );
-
-        // color blend state
-        vk::ColorComponentFlags colorWriteMask(VK_COLOR_COMPONENT_R_BIT |
-                                               VK_COLOR_COMPONENT_G_BIT |
-                                               VK_COLOR_COMPONENT_B_BIT |
-                                               VK_COLOR_COMPONENT_A_BIT);
-
-        // currently set to additive, if not disabled
-        // BlendFactors must be set as soon as additional BlendModes are added
-        vk::PipelineColorBlendAttachmentState colorBlendAttachmentState(
-                config.m_blendMode != BlendMode::None,
-                vk::BlendFactor::eOne,
-                vk::BlendFactor::eOne,
-                vk::BlendOp::eAdd,
-                vk::BlendFactor::eOne,
-                vk::BlendFactor::eOne,
-                vk::BlendOp::eAdd,
-                colorWriteMask
-        );
-        vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(
-                {},
-                false,
-                vk::LogicOp::eClear,
-                1,	//TODO: hardcoded to one
-                &colorBlendAttachmentState,
-                { 1.f,1.f,1.f,1.f }
-        );
-
-		const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize();
-		const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, pushConstantSize);
-
-        // pipeline layout
-        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo(
-			{},
-			(config.m_DescriptorLayouts),
-			(pushConstantRange));
-		if (pushConstantSize == 0) {
-			pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
-		}
-
-
-        vk::PipelineLayout vkPipelineLayout{};
-        if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
-        {
-            destroyShaderModules();
-            return PipelineHandle();
-        }
-	
-		const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo(
-				vk::PipelineDepthStencilStateCreateFlags(),
-				config.m_depthTest != DepthTest::None,
-				config.m_depthWrite,
-				depthTestToVkCompareOp(config.m_depthTest),
-				false,
-				false,
-				{},
-				{},
-				0.0f,
-				1.0f
-		);
-	
-		const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr;
-		
-		const PassConfig& passConfig = passManager.getPassConfig(config.m_PassHandle);
-		
-		for (const auto& attachment : passConfig.attachments) {
-			if (isDepthFormat(attachment.format)) {
-				p_depthStencilCreateInfo = &depthStencilCreateInfo;
-				break;
-			}
-		}
-
-		std::vector<vk::DynamicState> dynamicStates = {};
-		if(config.m_UseDynamicViewport)
-        {
-		    dynamicStates.push_back(vk::DynamicState::eViewport);
-		    dynamicStates.push_back(vk::DynamicState::eScissor);
-        }
-
-        vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo(
-            {},
-            static_cast<uint32_t>(dynamicStates.size()),
-            dynamicStates.data());
-
-        const bool existsGeometryShader = config.m_ShaderProgram.existsShader(vkcv::ShaderStage::GEOMETRY);
-        if (existsGeometryShader) {
-            vk::PipelineShaderStageCreateInfo createInfo;
-            const bool success = createPipelineShaderStageCreateInfo(
-                config.m_ShaderProgram,
-                vkcv::ShaderStage::GEOMETRY,
-                m_Device,
-                &createInfo);
-
-            if (success) {
-                shaderStages.push_back(createInfo);
-            }
-            else {
-                destroyShaderModules();
-                return PipelineHandle();
-            }
-        }
-
-        const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(
-                {},
-                static_cast<uint32_t>(shaderStages.size()),
-                shaderStages.data(),
-                &pipelineVertexInputStateCreateInfo,
-                &pipelineInputAssemblyStateCreateInfo,
-                nullptr,
-                &pipelineViewportStateCreateInfo,
-                &pipelineRasterizationStateCreateInfo,
-                &pipelineMultisampleStateCreateInfo,
-				p_depthStencilCreateInfo,
-                &pipelineColorBlendStateCreateInfo,
-                &dynamicStateCreateInfo,
-                vkPipelineLayout,
-                pass,
-                0,
-                {},
-                0
-        );
-
-        vk::Pipeline vkPipeline{};
-        if (m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess)
-        {
-            destroyShaderModules();
-            return PipelineHandle();
-        }
-
-        destroyShaderModules();
-        
-        const uint64_t id = m_Pipelines.size();
-        m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, config });
-        return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
-    }
-
-    vk::Pipeline PipelineManager::getVkPipeline(const PipelineHandle &handle) const
-    {
-		const uint64_t id = handle.getId();
-	
-		if (id >= m_Pipelines.size()) {
-			return nullptr;
-		}
-	
-		auto& pipeline = m_Pipelines[id];
-	
-		return pipeline.m_handle;
-    }
-
-    vk::PipelineLayout PipelineManager::getVkPipelineLayout(const PipelineHandle &handle) const
-    {
-    	const uint64_t id = handle.getId();
-    	
-		if (id >= m_Pipelines.size()) {
-			return nullptr;
-		}
-	
-		auto& pipeline = m_Pipelines[id];
-    	
-        return pipeline.m_layout;
-    }
-    
-    void PipelineManager::destroyPipelineById(uint64_t id) {
-    	if (id >= m_Pipelines.size()) {
-    		return;
-    	}
-    	
-    	auto& pipeline = m_Pipelines[id];
-    	
-    	if (pipeline.m_handle) {
-			m_Device.destroy(pipeline.m_handle);
-			pipeline.m_handle = nullptr;
-    	}
-	
-		if (pipeline.m_layout) {
-			m_Device.destroy(pipeline.m_layout);
-			pipeline.m_layout = nullptr;
-		}
-    }
-
-    const PipelineConfig& PipelineManager::getPipelineConfig(const PipelineHandle &handle) const
-    {
-        const uint64_t id = handle.getId();
-        
-        if (id >= m_Pipelines.size()) {
-        	static PipelineConfig dummyConfig;
-			vkcv_log(LogLevel::ERROR, "Invalid handle");
-			return dummyConfig;
-        }
-        
-        return m_Pipelines[id].m_config;
-    }
-
-    PipelineHandle PipelineManager::createComputePipeline(
-        const ShaderProgram &shaderProgram, 
-        const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
-
-        // Temporally handing over the Shader Program instead of a pipeline config
-        vk::ShaderModule computeModule{};
-        if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess)
-            return PipelineHandle();
-
-        vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo(
-                {},
-                vk::ShaderStageFlagBits::eCompute,
-                computeModule,
-                "main",
-                nullptr
-        );
-
-        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts);
-
-        const size_t pushConstantSize = shaderProgram.getPushConstantSize();
-        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
-        if (pushConstantSize > 0) {
-            pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
-            pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
-        }
-
-        vk::PipelineLayout vkPipelineLayout{};
-        if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
-        {
-            m_Device.destroy(computeModule);
-            return PipelineHandle();
-        }
-
-        vk::ComputePipelineCreateInfo computePipelineCreateInfo{};
-        computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo;
-        computePipelineCreateInfo.layout = vkPipelineLayout;
-
-        vk::Pipeline vkPipeline;
-        if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline)!= vk::Result::eSuccess)
-        {
-            m_Device.destroy(computeModule);
-            return PipelineHandle();
-        }
-
-        m_Device.destroy(computeModule);
-
-        const uint64_t id = m_Pipelines.size();
-        m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, PipelineConfig() });
-
-        return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
-    }
-
-    // There is an issue for refactoring the Pipeline Manager.
-    // While including Compute Pipeline Creation, some private helper functions where introduced:
-
-    vk::Result PipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage)
-    {
-        std::vector<char> code = shaderProgram.getShader(stage).shaderCode;
-        vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
-        return m_Device.createShaderModule(&moduleInfo, nullptr, &module);
-    }
-}
diff --git a/src/vkcv/PipelineManager.hpp b/src/vkcv/PipelineManager.hpp
deleted file mode 100644
index b153eb4632b844e84b92953fe8abf6666a13e0c9..0000000000000000000000000000000000000000
--- a/src/vkcv/PipelineManager.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include <vulkan/vulkan.hpp>
-#include <vector>
-#include "vkcv/Handles.hpp"
-#include "vkcv/PipelineConfig.hpp"
-#include "PassManager.hpp"
-
-namespace vkcv
-{
-    class PipelineManager
-    {
-    private:
-    	struct Pipeline {
-			vk::Pipeline m_handle;
-			vk::PipelineLayout m_layout;
-			PipelineConfig m_config;
-    	};
-    	
-        vk::Device m_Device;
-        std::vector<Pipeline> m_Pipelines;
-        
-        void destroyPipelineById(uint64_t id);
-
-        vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage);
-
-    public:
-        PipelineManager() = delete; // no default ctor
-        explicit PipelineManager(vk::Device device) noexcept; // ctor
-        ~PipelineManager() noexcept; // dtor
-
-        PipelineManager(const PipelineManager &other) = delete; // copy-ctor
-        PipelineManager(PipelineManager &&other) = delete; // move-ctor;
-
-        PipelineManager & operator=(const PipelineManager &other) = delete; // copy-assign op
-        PipelineManager & operator=(PipelineManager &&other) = delete; // move-assign op
-
-        PipelineHandle createPipeline(const PipelineConfig &config, PassManager& passManager);
-
-        PipelineHandle createComputePipeline(
-            const ShaderProgram& shaderProgram,
-            const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts);
-
-        [[nodiscard]]
-        vk::Pipeline getVkPipeline(const PipelineHandle &handle) const;
-
-        [[nodiscard]]
-        vk::PipelineLayout getVkPipelineLayout(const PipelineHandle &handle) const;
-
-        [[nodiscard]]
-        const PipelineConfig &getPipelineConfig(const PipelineHandle &handle) const;
-    };
-}
diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp
index 2cfd0d7a832129b6f3bbdbeaf17494d0af3c928e..ff134041bdc6279d312df668cab448a50750f1c3 100644
--- a/src/vkcv/QueueManager.cpp
+++ b/src/vkcv/QueueManager.cpp
@@ -149,7 +149,8 @@ namespace vkcv {
                     }
                     break;
                 default:
-                    throw std::runtime_error("Invalid input for queue flag bits. Valid inputs are 'vk::QueueFlagBits::eGraphics', 'vk::QueueFlagBits::eCompute' and 'vk::QueueFlagBits::eTransfer'.");
+					vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", vk::to_string(qFlag).c_str());
+					break;
             }
         }
 
diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp
index 90f589266cf51cbb3ef98edb5d64362c0a650c14..483732927bc2cc507f0868226b65bf4d49e27048 100644
--- a/src/vkcv/Swapchain.cpp
+++ b/src/vkcv/Swapchain.cpp
@@ -73,12 +73,7 @@ namespace vkcv
      * @param window of the current application
      * @return chosen Extent for the surface
      */
-    vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){
-        vk::SurfaceCapabilitiesKHR surfaceCapabilities;
-        if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){
-            throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface.");
-        }
-        
+    vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) {
         int fb_width, fb_height;
         window.getFramebufferSize(fb_width, fb_height);
         
@@ -86,9 +81,17 @@ namespace vkcv
                 static_cast<uint32_t>(fb_width),
                 static_cast<uint32_t>(fb_height)
         };
-        
-        extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width));
-        extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height));
+	
+		vk::SurfaceCapabilitiesKHR surfaceCapabilities;
+		if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) {
+			vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved");
+			
+			extent2D.width = std::max(MIN_SWAPCHAIN_SIZE, extent2D.width);
+			extent2D.height = std::max(MIN_SWAPCHAIN_SIZE, extent2D.height);
+		} else {
+			extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width));
+			extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height));
+		}
 
         return extent2D;
     }