diff --git a/config/Sources.cmake b/config/Sources.cmake
index ea9789752074a0f6b9f5c498c638ab1b13bc2d9d..a50be825150e69513d98ac9b0e7caaf3a699e013 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -42,6 +42,9 @@ set(vkcv_sources
 		${vkcv_source}/vkcv/ImageManager.hpp
 		${vkcv_source}/vkcv/ImageManager.cpp
 		
+		${vkcv_include}/vkcv/PipelineConfig.hpp
+		${vkcv_source}/vkcv/PipelineConfig.cpp
+		
 		${vkcv_include}/vkcv/Logger.hpp
 		
 		${vkcv_include}/vkcv/Surface.hpp
@@ -56,6 +59,8 @@ set(vkcv_sources
 		${vkcv_source}/vkcv/ShaderProgram.cpp
 
 		${vkcv_include}/vkcv/GraphicsPipelineConfig.hpp
+		${vkcv_source}/vkcv/GraphicsPipelineConfig.cpp
+		
 		${vkcv_include}/vkcv/ComputePipelineConfig.hpp
 
 		${vkcv_source}/vkcv/ComputePipelineManager.hpp
diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index be7cb66e97a68f9fd96bcf99495a1bda3db55078..2e2d675284079262654497e9d3f95a02e95d89b1 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -23,15 +23,16 @@ namespace vkcv {
 	public:
 		Buffer() : m_core(nullptr), m_handle() {};
 		
+		Buffer(Core* core, const BufferHandle& handle) : m_core(core), m_handle(handle) {}
+		
 		Buffer(const Buffer& other) = default;
 		Buffer(Buffer&& other) = default;
 		
+		~Buffer() = default;
+		
 		Buffer& operator=(const Buffer& other) = default;
 		Buffer& operator=(Buffer&& other) = default;
 		
-		Buffer(Core* core, const BufferHandle& handle) :
-		m_core(core), m_handle(handle) {}
-		
 		/**
 		 * @brief Returns the buffers handle.
 		 *
diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp
index ab458aa53704ccc1d5dbe2f1024d826b0b337f78..82f3eedf54bb80f11576a2aafcc7ba3b244e61ce 100644
--- a/include/vkcv/ComputePipelineConfig.hpp
+++ b/include/vkcv/ComputePipelineConfig.hpp
@@ -5,19 +5,15 @@
  * @brief Compute pipeline config struct to hand over required information to pipeline creation.
  */
 
-#include <vector>
-
-#include "Handles.hpp"
-#include "ShaderProgram.hpp"
+#include "PipelineConfig.hpp"
 
 namespace vkcv {
 	
 	/**
-	 * @brief Structure to configure a compute pipeline before its creation.
+	 * @brief Class to configure a compute pipeline before its creation.
 	 */
-    struct ComputePipelineConfig {
-        ShaderProgram&                          m_ShaderProgram;
-        std::vector<DescriptorSetLayoutHandle>	m_DescriptorSetLayouts;
-    };
+    class ComputePipelineConfig : public PipelineConfig {
+		using PipelineConfig::PipelineConfig;
+	};
 	
 }
\ No newline at end of file
diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp
index 85cabc135ddfa8e6e6762c16c269741e232cff4d..93fe553a84d53044fc138fa64948759c9cae4f24 100644
--- a/include/vkcv/GraphicsPipelineConfig.hpp
+++ b/include/vkcv/GraphicsPipelineConfig.hpp
@@ -2,14 +2,13 @@
 /**
  * @authors Mara Vogt, Mark Mints, Tobias Frisch
  * @file vkcv/GraphicsPipelineConfig.hpp
- * @brief Graphics Pipeline Config Struct to hand over required information to Pipeline Creation
+ * @brief Graphics pipeline config struct to hand over required information to pipeline creation.
  */
 
 #include <vector>
 #include <cstdint>
 
-#include "Handles.hpp"
-#include "ShaderProgram.hpp"
+#include "PipelineConfig.hpp"
 #include "VertexLayout.hpp"
 #include "ImageConfig.hpp"
 
@@ -58,26 +57,110 @@ namespace vkcv {
 	};
 	
 	/**
-	 * @brief Structure to configure a graphics pipeline before its creation.
+	 * @brief Class to configure a graphics pipeline before its creation.
 	 */
-    struct GraphicsPipelineConfig {
-        ShaderProgram                         	m_ShaderProgram;
-        uint32_t                              	m_Width;
-		uint32_t                              	m_Height;
-        PassHandle                            	m_PassHandle;
-        VertexLayout                          	m_VertexLayout;
-        std::vector<DescriptorSetLayoutHandle>	m_DescriptorLayouts;
-        bool                                  	m_UseDynamicViewport;
-        bool                                  	m_UseConservativeRasterization 	= false;
-        PrimitiveTopology                     	m_PrimitiveTopology 			= PrimitiveTopology::TriangleList;
-		BlendMode                             	m_blendMode 					= BlendMode::None;
-        bool                                    m_EnableDepthClamping           = false;
-        Multisampling                           m_multisampling                 = Multisampling::None;
-        CullMode                                m_culling                       = CullMode::None;
-        DepthTest                               m_depthTest                     = DepthTest::LessEqual;
-        bool                                    m_depthWrite                    = true;
-        bool                                    m_alphaToCoverage               = false;
-		uint32_t								m_tessellationControlPoints		= 0;
+    class GraphicsPipelineConfig : public PipelineConfig {
+	private:
+		PassHandle m_PassHandle;
+		VertexLayout m_VertexLayout;
+		
+        uint32_t m_Width;
+		uint32_t m_Height;
+		
+        bool 				m_UseConservativeRasterization 	= false;
+        PrimitiveTopology 	m_PrimitiveTopology 			= PrimitiveTopology::TriangleList;
+		BlendMode 			m_blendMode 					= BlendMode::None;
+        bool 				m_EnableDepthClamping 			= false;
+        Multisampling 		m_Multisampling 				= Multisampling::None;
+        CullMode 			m_Culling                       = CullMode::None;
+        DepthTest 			m_DepthTest                     = DepthTest::LessEqual;
+        bool 				m_DepthWrite 					= true;
+        bool 				m_AlphaToCoverage 				= false;
+		uint32_t 			m_TessellationControlPoints 	= 0;
+		
+	public:
+		GraphicsPipelineConfig();
+	
+		GraphicsPipelineConfig(const ShaderProgram& program,
+							   const PassHandle& pass,
+							   const VertexLayout& vertexLayout,
+							   const std::vector<DescriptorSetLayoutHandle>& layouts);
+	
+		GraphicsPipelineConfig(const GraphicsPipelineConfig &other) = default;
+		GraphicsPipelineConfig(GraphicsPipelineConfig &&other) = default;
+	
+		~GraphicsPipelineConfig() = default;
+	
+		GraphicsPipelineConfig& operator=(const GraphicsPipelineConfig &other) = default;
+		GraphicsPipelineConfig& operator=(GraphicsPipelineConfig &&other) = default;
+	
+		[[nodiscard]]
+		const PassHandle& getPass() const;
+	
+		[[nodiscard]]
+		const VertexLayout& getVertexLayout() const;
+	
+		[[nodiscard]]
+		uint32_t getWidth() const;
+	
+		[[nodiscard]]
+		uint32_t getHeight() const;
+		
+		void setResolution(uint32_t width, uint32_t height);
+		
+		[[nodiscard]]
+		bool isViewportDynamic() const;
+	
+		[[nodiscard]]
+		bool isUsingConservativeRasterization() const;
+		
+		void setUsingConservativeRasterization(bool conservativeRasterization);
+	
+		[[nodiscard]]
+		PrimitiveTopology getPrimitiveTopology() const;
+		
+		void setPrimitiveTopology(PrimitiveTopology primitiveTopology);
+	
+		[[nodiscard]]
+		BlendMode getBlendMode() const;
+		
+		void setBlendMode(BlendMode blendMode);
+	
+		[[nodiscard]]
+		bool isDepthClampingEnabled() const;
+		
+		void setDepthClampingEnabled(bool depthClamping);
+	
+		[[nodiscard]]
+		Multisampling getMultisampling() const;
+		
+		void setMultisampling(Multisampling multisampling);
+	
+		[[nodiscard]]
+		CullMode getCulling() const;
+		
+		void setCulling(CullMode cullMode);
+	
+		[[nodiscard]]
+		DepthTest getDepthTest() const;
+		
+		void setDepthTest(DepthTest depthTest);
+	
+		[[nodiscard]]
+		bool isWritingDepth() const;
+		
+		void setWritingDepth(bool writingDepth);
+	
+		[[nodiscard]]
+		bool isWritingAlphaToCoverage() const;
+		
+		void setWritingAlphaToCoverage(bool alphaToCoverage);
+		
+		[[nodiscard]]
+		uint32_t getTesselationControlPoints() const;
+		
+		void setTesselationControlPoints(uint32_t tessellationControlPoints);
+		
     };
 
 }
\ No newline at end of file
diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/PipelineConfig.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e53985f77a454891dd4d1fc69abcb2c0eb344912
--- /dev/null
+++ b/include/vkcv/PipelineConfig.hpp
@@ -0,0 +1,51 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/PipelineConfig.hpp
+ * @brief Pipeline config class to hand over required information to pipeline creation
+ */
+
+#include <vector>
+
+#include "Handles.hpp"
+#include "ShaderProgram.hpp"
+
+namespace vkcv {
+	
+	/**
+	 * @brief Class to configure a general pipeline before its creation.
+	 */
+	class PipelineConfig {
+	private:
+		ShaderProgram m_ShaderProgram;
+		std::vector<DescriptorSetLayoutHandle> m_DescriptorSetLayouts;
+		
+	public:
+		PipelineConfig();
+		
+		PipelineConfig(const ShaderProgram& program,
+					   const std::vector<DescriptorSetLayoutHandle>& layouts);
+		
+		PipelineConfig(const PipelineConfig &other) = default;
+		PipelineConfig(PipelineConfig &&other) = default;
+		
+		~PipelineConfig() = default;
+		
+		PipelineConfig& operator=(const PipelineConfig &other) = default;
+		PipelineConfig& operator=(PipelineConfig &&other) = default;
+		
+		void setShaderProgram(const ShaderProgram& program);
+		
+		[[nodiscard]]
+		const ShaderProgram& getShaderProgram() const;
+		
+		void addDescriptorSetLayout(const DescriptorSetLayoutHandle& layout);
+		
+		void addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle>& layouts);
+		
+		[[nodiscard]]
+		const std::vector<DescriptorSetLayoutHandle>& getDescriptorSetLayouts() const;
+		
+	};
+	
+}
diff --git a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
index 0ebcbb5d3ac13886bd4779e750897b104bad8303..fe97d6b9243bb976cc959ae850113cfa8c52bf15 100644
--- a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
+++ b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
@@ -13,6 +13,7 @@
 #include "SPDIntegration.glsl.hxx"
 #include "SPDIntegrationLinearSampler.glsl.hxx"
 
+#include <vkcv/ComputePipelineConfig.hpp>
 #include <vkcv/File.hpp>
 #include <vkcv/Logger.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -231,10 +232,10 @@ namespace vkcv::algorithm {
 			);
 		}
 		
-		m_pipeline = m_core.createComputePipeline({
+		m_pipeline = m_core.createComputePipeline(ComputePipelineConfig(
 			program,
 			{ m_descriptorSetLayout }
-		});
+		));
 		
 		uint32_t zeroes [m_globalCounter.getCount()];
 		memset(zeroes, 0, m_globalCounter.getSize());
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 9ea16b91b1217bc3cee9ee0bcd3562bda0f5f963..afc5833068573e8a76647a5f26e1c9b1ecbfb392 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -148,16 +148,14 @@ int main(int argc, const char** argv) {
     vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(adjustedBindings);
 	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
 
-	const vkcv::GraphicsPipelineConfig firstMeshPipelineConfig {
-        firstMeshProgram,
-        UINT32_MAX,
-        UINT32_MAX,
-        firstMeshPass,
-        {firstMeshLayout},
-		{ descriptorSetLayout },
-		true
-	};
-	vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
+	vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					firstMeshProgram,
+					firstMeshPass,
+					{ firstMeshLayout },
+					{ descriptorSetLayout }
+			)
+	);
 	
 	if (!firstMeshPipeline) {
 		std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl;
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 6bb34e8ebae552a45043411967164a6e23cc35f8..40a16aed5c2ab42113e9c432a5329eec8f457ebb 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -105,17 +105,15 @@ int main(int argc, const char** argv) {
 	vkcv::DescriptorSetLayoutHandle setLayoutHandleCopy = core.createDescriptorSetLayout(set0BindingsExplicitCopy);
 
 	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(setLayoutHandle);
-
-	const vkcv::GraphicsPipelineConfig firstMeshPipelineConfig {
-        firstMeshProgram,
-        UINT32_MAX,
-        UINT32_MAX,
-        firstMeshPass,
-        {firstMeshLayout},
-		{ setLayoutHandle },
-		true
-	};
-	vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
+	
+	vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					firstMeshProgram,
+					firstMeshPass,
+					{ firstMeshLayout },
+					{ setLayoutHandle }
+			)
+	);
 	
 	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 b09943e4b9432ac09c6eaaa5bbe06b0b28b59ab3..c09d01214be479c8da8a3117a3ac972931202d85 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -89,17 +89,15 @@ int main(int argc, const char** argv) {
 
 	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
-
-	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
-		sceneShaderProgram,
-		UINT32_MAX,
-		UINT32_MAX,
-		scenePass,
-		{sceneLayout},
-		{ material0.getDescriptorSetLayout() },
-		true
-	};
-	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
+	
+	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					sceneShaderProgram,
+					scenePass,
+					{ sceneLayout },
+					{ material0.getDescriptorSetLayout() }
+			)
+	);
 	
 	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 6959e2bda1138971486dc2d703f30a6506f2781d..d98ea8e77312a3299e1ec82db4b26e6dcb240ea8 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -53,17 +53,14 @@ int main(int argc, const char** argv) {
 		{ vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" }
 	}, nullptr);
 
-	const vkcv::GraphicsPipelineConfig trianglePipelineDefinition {
-		triangleShaderProgram,
-		UINT32_MAX,
-		UINT32_MAX,
-		trianglePass,
-		{},
-		{},
-		true
-	};
-
-	vkcv::GraphicsPipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
+	vkcv::GraphicsPipelineHandle trianglePipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					triangleShaderProgram,
+					trianglePass,
+					{},
+					{}
+			)
+	);
 
 	if (!trianglePipeline)
 	{
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index a159684f2d7972fd6c609a6f66083ef7ed1250e5..5e3d0abcce5fa036f46c159b9895e0799f4af82d 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -152,28 +152,23 @@ int main(int argc, const char** argv) {
 	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
 	
-	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
-			sceneShaderProgram,
-			UINT32_MAX,
-			UINT32_MAX,
-			scenePass,
-			{sceneLayout},
-			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
-			true
-	};
-	
-	const vkcv::GraphicsPipelineConfig linePipelineDefinition{
-			lineShaderProgram,
-			UINT32_MAX,
-			UINT32_MAX,
-			linePass,
-			{sceneLayout},
-			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
-			true
-	};
-	
-	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
-	vkcv::GraphicsPipelineHandle linePipeline = core.createGraphicsPipeline(linePipelineDefinition);
+	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+				sceneShaderProgram,
+				scenePass,
+				{ sceneLayout },
+				{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout }
+			)
+	);
+	
+	vkcv::GraphicsPipelineHandle linePipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					lineShaderProgram,
+					linePass,
+					{ sceneLayout },
+					{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout }
+			)
+	);
 	
 	if ((!scenePipeline) || (!linePipeline)) {
 		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index d428a327125d24fe691b71023d43af588e57b795..8a5977ceeea8e08e74a96ab2570fad694bf86614 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -136,19 +136,16 @@ bool loadGraphicPass(
 	    outPassHandles->descriptorSet = core.createDescriptorSet(outPassHandles->descriptorSetLayout);
 	    descriptorSetLayouts.push_back(outPassHandles->descriptorSetLayout);
 	}
-
-
-	vkcv::GraphicsPipelineConfig pipelineConfig{
+	
+	vkcv::GraphicsPipelineConfig pipelineConfig(
 		shaderProgram,
-		UINT32_MAX,
-		UINT32_MAX,
 		outPassHandles->renderPass,
 		{ vertexLayout },
-		descriptorSetLayouts,
-		true
-	};
-	pipelineConfig.m_depthTest  = depthTest;
-	outPassHandles->pipeline    = core.createGraphicsPipeline(pipelineConfig);
+		descriptorSetLayouts
+	);
+	
+	pipelineConfig.setDepthTest(depthTest);
+	outPassHandles->pipeline = core.createGraphicsPipeline(pipelineConfig);
 
 	if (!outPassHandles->pipeline) {
 		vkcv_log(vkcv::LogLevel::ERROR, "Error: Could not create graphics pipeline");
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index d9990a28c88cb75063b9f4d310322a2f4102c70c..6c3c19dfdfd4a88e5d4b198be805407e7cd387be 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -467,16 +467,15 @@ int main(int argc, const char** argv) {
 	setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
-	const vkcv::GraphicsPipelineConfig sponzaPipelineConfig {
-        sponzaProgram,
-        UINT32_MAX,
-        UINT32_MAX,
-        passHandle,
-        {sponzaVertexLayout},
-		{ descriptorSetLayout },
-		true
-	};
-	vkcv::GraphicsPipelineHandle sponzaPipelineHandle = core.createGraphicsPipeline(sponzaPipelineConfig);
+	vkcv::GraphicsPipelineHandle sponzaPipelineHandle = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					sponzaProgram,
+					passHandle,
+					{ sponzaVertexLayout },
+					{ descriptorSetLayout }
+			)
+	);
+	
 	if (!sponzaPipelineHandle) {
 		std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl;
 		return EXIT_FAILURE;
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 5b727a19e689092687e38bad07e13dee6a04872f..287a925f8801ad87977de8264a54cec4a1f78cea 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -209,16 +209,6 @@ int main(int argc, const char** argv) {
 
     vkcv::DescriptorSetLayoutHandle vertexShaderDescriptorSetLayout = core.createDescriptorSetLayout(bunnyShaderProgram.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle vertexShaderDescriptorSet = core.createDescriptorSet(vertexShaderDescriptorSetLayout);
-	
-	const vkcv::GraphicsPipelineConfig bunnyPipelineDefinition {
-			bunnyShaderProgram,
-			UINT32_MAX,
-			UINT32_MAX,
-			renderPass,
-			{ bunnyLayout },
-			{ vertexShaderDescriptorSetLayout },
-			true
-	};
 
 	struct ObjectMatrices {
 		glm::mat4 model;
@@ -231,7 +221,14 @@ int main(int argc, const char** argv) {
 	vertexShaderDescriptorWrites.writeStorageBuffer(0, matrixBuffer.getHandle());
 	core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
 
-	vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
+	vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					bunnyShaderProgram,
+					renderPass,
+					{ bunnyLayout },
+					{ vertexShaderDescriptorSetLayout }
+			)
+	);
 
 	if (!bunnyPipeline)
 	{
@@ -260,17 +257,14 @@ int main(int argc, const char** argv) {
 	vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet(meshShaderDescriptorSetLayout);
 	const vkcv::VertexLayout meshShaderLayout(bindings);
 
-	const vkcv::GraphicsPipelineConfig meshShaderPipelineDefinition{
-		meshShaderProgram,
-		UINT32_MAX,
-		UINT32_MAX,
-		renderPass,
-		{meshShaderLayout},
-		{meshShaderDescriptorSetLayout},
-		true
-	};
-
-	vkcv::GraphicsPipelineHandle meshShaderPipeline = core.createGraphicsPipeline(meshShaderPipelineDefinition);
+	vkcv::GraphicsPipelineHandle meshShaderPipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					meshShaderProgram,
+					renderPass,
+					{ meshShaderLayout },
+					{ meshShaderDescriptorSetLayout }
+			)
+	);
 
 	if (!meshShaderPipeline)
 	{
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index 50963769b7d87e71e4e4fcdffb61281b5feff220..a281c393a5f1e8794a409fffa957483766683265 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -117,16 +117,14 @@ int main(int argc, const char **argv) {
 
     const vkcv::VertexLayout particleLayout { bindings };
 
-    vkcv::GraphicsPipelineConfig particlePipelineDefinition{
+    vkcv::GraphicsPipelineConfig particlePipelineDefinition (
             particleShaderProgram,
-            UINT32_MAX,
-            UINT32_MAX,
             particlePass,
             {particleLayout},
-            {descriptorSetLayout},
-            true
-	};
-    particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive;
+            {descriptorSetLayout}
+	);
+	
+    particlePipelineDefinition.setBlendMode(vkcv::BlendMode::Additive);
 
     const std::vector<glm::vec3> vertices = {glm::vec3(-0.012, 0.012, 0),
                                              glm::vec3(0.012, 0.012, 0),
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 3e6d9e6c3db736d55e05e7993c9f94e946bab360..cc6dd0d479b2e8213ea7661a5f893199650fb8dd 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -176,24 +176,21 @@ int main(int argc, const char** argv) {
 	}
 
 	//create the render pipeline + compute pipeline
-	const vkcv::GraphicsPipelineConfig safrPipelineDefinition{
-			safrShaderProgram,
-			UINT32_MAX,
-			UINT32_MAX,
-			safrPass,
-			{},
-			{ descriptorSetLayout },
-			true
-	};
-
-	vkcv::GraphicsPipelineHandle safrPipeline = core.createGraphicsPipeline(safrPipelineDefinition);
-
-	const vkcv::ComputePipelineConfig computePipelineConfig{
-			computeShaderProgram,
-			{computeDescriptorSetLayout}
-	};
-
-	vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline(computePipelineConfig);
+	vkcv::GraphicsPipelineHandle safrPipeline = core.createGraphicsPipeline(
+			vkcv::GraphicsPipelineConfig(
+					safrShaderProgram,
+					safrPass,
+					{},
+					{ descriptorSetLayout }
+			)
+	);
+
+	vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline(
+			vkcv::ComputePipelineConfig(
+					computeShaderProgram,
+					{ computeDescriptorSetLayout }
+			)
+	);
 
 	if (!safrPipeline || !computePipeline)
 	{
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index 8b4be7475ea29f38f02871ddf306a5593ae7197f..02d659eb3ba4afdaa1791e25b7da6d90665f8b1d 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -116,16 +116,14 @@ int main(int argc, const char **argv) {
     const vkcv::VertexLayout particleLayout { bindings };
 
     // initializing graphics pipeline
-    vkcv::GraphicsPipelineConfig particlePipelineDefinition{
+    vkcv::GraphicsPipelineConfig particlePipelineDefinition (
             particleShaderProgram,
-            UINT32_MAX,
-            UINT32_MAX,
             particlePass,
             {particleLayout},
-            {descriptorSetLayout},
-            true
-	};
-    particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive;
+            {descriptorSetLayout}
+	);
+	
+    particlePipelineDefinition.setBlendMode(vkcv::BlendMode::Additive);
 
     const std::vector<glm::vec3> vertices = {glm::vec3(-0.012, 0.012, 0),
                                              glm::vec3(0.012, 0.012, 0),
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index eb463944877803aef13b92aeb9be3ef88cb2bb22..1d4fb1b8ad6013492f7f9c0b343ca3f4e736780f 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -166,19 +166,18 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	m_shadowMapPass = corePtr->createPass(shadowPassConfig);
 
 	// pipeline
-	vkcv::GraphicsPipelineConfig shadowPipeConfig{
+	vkcv::GraphicsPipelineConfig shadowPipeConfig (
 		shadowShader,
-		shadowMapResolution,
-		shadowMapResolution,
 		m_shadowMapPass,
 		vertexLayout,
-		{},
-		false
-	};
-	shadowPipeConfig.m_multisampling        = msaa;
-	shadowPipeConfig.m_EnableDepthClamping  = true;
-	shadowPipeConfig.m_culling              = vkcv::CullMode::Front;
-	m_shadowMapPipe                         = corePtr->createGraphicsPipeline(shadowPipeConfig);
+		{}
+	);
+	
+	shadowPipeConfig.setResolution(shadowMapResolution, shadowMapResolution);
+	shadowPipeConfig.setMultisampling(msaa);
+	shadowPipeConfig.setDepthClampingEnabled(true);
+	shadowPipeConfig.setCulling(vkcv::CullMode::Front);
+	m_shadowMapPipe = corePtr->createGraphicsPipeline(shadowPipeConfig);
 
 	m_shadowSampler = corePtr->createSampler(
 		vkcv::SamplerFilterType::LINEAR,
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 049bdb1d28855fc3fe9a83d5fd176818bdf06678..4053a34a55c57b3ab3331a3efff7153455502542 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -107,16 +107,16 @@ Voxelization::Voxelization(
 	vkcv::DescriptorSetLayoutHandle dummyPerMeshDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelizationShader.getReflectedDescriptors().at(1));
 	vkcv::DescriptorSetHandle dummyPerMeshDescriptorSet = m_corePtr->createDescriptorSet(dummyPerMeshDescriptorSetLayout);
 
-	const vkcv::GraphicsPipelineConfig voxelizationPipeConfig{
+	vkcv::GraphicsPipelineConfig voxelizationPipeConfig (
 		voxelizationShader,
-		voxelResolution,
-		voxelResolution,
 		m_voxelizationPass,
 		dependencies.vertexLayout,
-		{ m_voxelizationDescriptorSetLayout, dummyPerMeshDescriptorSetLayout },
-		false,
-		true
-	};
+		{ m_voxelizationDescriptorSetLayout, dummyPerMeshDescriptorSetLayout }
+	);
+	
+	voxelizationPipeConfig.setResolution(voxelResolution, voxelResolution);
+	voxelizationPipeConfig.setUsingConservativeRasterization(true);
+	
 	m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig);
 
 	vkcv::DescriptorWrites voxelizationDescriptorWrites;
@@ -156,18 +156,15 @@ Voxelization::Voxelization(
 	
 	m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition);
 
-	vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig{
+	vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig (
 		voxelVisualisationShader,
-		0,
-		0,
 		m_visualisationPass,
 		{},
-		{ m_visualisationDescriptorSetLayout },
-		true,
-		false,
-		vkcv::PrimitiveTopology::PointList
-	};	// points are extended to cubes in the geometry shader
-	voxelVisualisationPipeConfig.m_multisampling = msaa;
+		{ m_visualisationDescriptorSetLayout }
+	);	// points are extended to cubes in the geometry shader
+	
+	voxelVisualisationPipeConfig.setPrimitiveTopology(vkcv::PrimitiveTopology::PointList);
+	voxelVisualisationPipeConfig.setMultisampling(msaa);
 	m_visualisationPipe = m_corePtr->createGraphicsPipeline(voxelVisualisationPipeConfig);
 
 	std::vector<uint16_t> voxelIndexData;
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 55e3b38af19550c5cdbd8ed836ce98f49f85534e..995045d26c8eb29be11ed8b6d52b055e6fdfc4e9 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -335,36 +335,32 @@ int main(int argc, const char** argv) {
 
 	auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 	
-	vkcv::GraphicsPipelineConfig prepassPipelineConfig{
+	vkcv::GraphicsPipelineConfig prepassPipelineConfig (
 		depthPrepassShader,
-		swapchainExtent.width,
-		swapchainExtent.height,
 		prepassPass,
 		vertexLayout,
-		{ prepassDescriptorSetLayout, perMeshDescriptorSetLayouts[0] },
-		true
-	};
-	prepassPipelineConfig.m_culling         = vkcv::CullMode::Back;
-	prepassPipelineConfig.m_multisampling   = msaa;
-	prepassPipelineConfig.m_depthTest       = vkcv::DepthTest::LessEqual;
-	prepassPipelineConfig.m_alphaToCoverage = true;
+		{ prepassDescriptorSetLayout, perMeshDescriptorSetLayouts[0] }
+	);
+	
+	prepassPipelineConfig.setCulling(vkcv::CullMode::Back);
+	prepassPipelineConfig.setMultisampling(msaa);
+	prepassPipelineConfig.setDepthTest(vkcv::DepthTest::LessEqual);
+	prepassPipelineConfig.setWritingAlphaToCoverage(true);
 
 	vkcv::GraphicsPipelineHandle prepassPipeline = core.createGraphicsPipeline(prepassPipelineConfig);
 
 	// forward pipeline
-	vkcv::GraphicsPipelineConfig forwardPipelineConfig {
+	vkcv::GraphicsPipelineConfig forwardPipelineConfig (
 		forwardProgram,
-		swapchainExtent.width,
-		swapchainExtent.height,
 		forwardPass,
 		vertexLayout,
-		{ forwardShadingDescriptorSetLayout, perMeshDescriptorSetLayouts[0] },
-		true
-	};
-    forwardPipelineConfig.m_culling         = vkcv::CullMode::Back;
-	forwardPipelineConfig.m_multisampling   = msaa;
-	forwardPipelineConfig.m_depthTest       = vkcv::DepthTest::Equal;
-	forwardPipelineConfig.m_depthWrite      = false;
+		{ forwardShadingDescriptorSetLayout, perMeshDescriptorSetLayouts[0] }
+	);
+	
+	forwardPipelineConfig.setCulling(vkcv::CullMode::Back);
+	forwardPipelineConfig.setMultisampling(msaa);
+	forwardPipelineConfig.setDepthTest(vkcv::DepthTest::Equal);
+	forwardPipelineConfig.setWritingDepth(false);
 	
 	vkcv::GraphicsPipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
 	
@@ -405,16 +401,15 @@ int main(int argc, const char** argv) {
 		skyShader.addShader(shaderStage, path);
 	});
 
-	vkcv::GraphicsPipelineConfig skyPipeConfig;
-	skyPipeConfig.m_ShaderProgram       = skyShader;
-	skyPipeConfig.m_Width               = swapchainExtent.width;
-	skyPipeConfig.m_Height              = swapchainExtent.height;
-	skyPipeConfig.m_PassHandle          = skyPass;
-	skyPipeConfig.m_VertexLayout        = vkcv::VertexLayout();
-	skyPipeConfig.m_DescriptorLayouts   = {};
-	skyPipeConfig.m_UseDynamicViewport  = true;
-	skyPipeConfig.m_multisampling       = msaa;
-	skyPipeConfig.m_depthWrite          = false;
+	vkcv::GraphicsPipelineConfig skyPipeConfig (
+			skyShader,
+			skyPass,
+			{},
+			{}
+	);
+	
+	skyPipeConfig.setMultisampling(msaa);
+	skyPipeConfig.setWritingDepth(false);
 
 	vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
 
@@ -1023,7 +1018,8 @@ int main(int argc, const char** argv) {
 					[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
 					newForwardProgram.addShader(shaderStage, path);
 				});
-				forwardPipelineConfig.m_ShaderProgram = newForwardProgram;
+				
+				forwardPipelineConfig.setShaderProgram(newForwardProgram);
 				vkcv::GraphicsPipelineHandle newPipeline = core.createGraphicsPipeline(forwardPipelineConfig);
 
 				if (newPipeline) {
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 079eb9390f007ba1ec8a5b06cef2c957efe2ec91..7a567c403a0929d02c40d3c82ebe86321fac6d4c 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -527,41 +527,36 @@ int main(int argc, const char **argv) {
 		vkcv::createVertexBinding(0, gfxProgramGrid.getVertexAttachments())
 	});
 	
-	vkcv::GraphicsPipelineConfig gfxPipelineConfigGrid;
-	gfxPipelineConfigGrid.m_ShaderProgram = gfxProgramGrid;
-	gfxPipelineConfigGrid.m_Width = windowWidth;
-	gfxPipelineConfigGrid.m_Height = windowHeight;
-	gfxPipelineConfigGrid.m_PassHandle = gfxPassGrid;
-	gfxPipelineConfigGrid.m_VertexLayout = vertexLayoutGrid;
-	gfxPipelineConfigGrid.m_DescriptorLayouts = { gfxSetLayoutGrid };
-	gfxPipelineConfigGrid.m_UseDynamicViewport = true;
+	vkcv::GraphicsPipelineConfig gfxPipelineConfigGrid (
+			gfxProgramGrid,
+			gfxPassGrid,
+			vertexLayoutGrid,
+			{ gfxSetLayoutGrid }
+	);
 	
 	vkcv::VertexLayout vertexLayoutParticles ({
 		vkcv::createVertexBinding(0, gfxProgramParticles.getVertexAttachments())
 	});
 	
-	vkcv::GraphicsPipelineConfig gfxPipelineConfigParticles;
-	gfxPipelineConfigParticles.m_ShaderProgram = gfxProgramParticles;
-	gfxPipelineConfigParticles.m_Width = windowWidth;
-	gfxPipelineConfigParticles.m_Height = windowHeight;
-	gfxPipelineConfigParticles.m_PassHandle = gfxPassParticles;
-	gfxPipelineConfigParticles.m_VertexLayout = vertexLayoutParticles;
-	gfxPipelineConfigParticles.m_DescriptorLayouts = { gfxSetLayoutParticles };
-	gfxPipelineConfigParticles.m_UseDynamicViewport = true;
+	vkcv::GraphicsPipelineConfig gfxPipelineConfigParticles (
+			gfxProgramParticles,
+			gfxPassParticles,
+			vertexLayoutParticles,
+			{ gfxSetLayoutParticles }
+	);
 	
 	vkcv::VertexLayout vertexLayoutLines ({
 		vkcv::createVertexBinding(0, gfxProgramLines.getVertexAttachments())
 	});
 	
-	vkcv::GraphicsPipelineConfig gfxPipelineConfigLines;
-	gfxPipelineConfigLines.m_ShaderProgram = gfxProgramLines;
-	gfxPipelineConfigLines.m_Width = windowWidth;
-	gfxPipelineConfigLines.m_Height = windowHeight;
-	gfxPipelineConfigLines.m_PassHandle = gfxPassLines;
-	gfxPipelineConfigLines.m_VertexLayout = vertexLayoutLines;
-	gfxPipelineConfigLines.m_DescriptorLayouts = {};
-	gfxPipelineConfigLines.m_UseDynamicViewport = true;
-	gfxPipelineConfigLines.m_PrimitiveTopology = vkcv::PrimitiveTopology::LineList;
+	vkcv::GraphicsPipelineConfig gfxPipelineConfigLines (
+			gfxProgramLines,
+			gfxPassLines,
+			vertexLayoutLines,
+			{}
+	);
+	
+	gfxPipelineConfigLines.setPrimitiveTopology(vkcv::PrimitiveTopology::LineList);
 	
 	vkcv::GraphicsPipelineHandle gfxPipelineGrid = core.createGraphicsPipeline(gfxPipelineConfigGrid);
 	vkcv::GraphicsPipelineHandle gfxPipelineParticles = core.createGraphicsPipeline(gfxPipelineConfigParticles);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 3716acb0e02a3c02ea0b994c40d4b81fae778a9c..22f334be819cfdb2832870b63a9e2daa4659736a 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -86,13 +86,13 @@ namespace vkcv
 
     ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) {
 		std::vector<vk::DescriptorSetLayout> layouts;
-		layouts.resize(config.m_DescriptorSetLayouts.size());
+		layouts.resize(config.getDescriptorSetLayouts().size());
 	
 		for (size_t i = 0; i < layouts.size(); i++) {
-			layouts[i] = getDescriptorSetLayout(config.m_DescriptorSetLayouts[i]).vulkanHandle;
+			layouts[i] = getDescriptorSetLayout(config.getDescriptorSetLayouts()[i]).vulkanHandle;
 		}
 		
-        return m_ComputePipelineManager->createComputePipeline(config.m_ShaderProgram, layouts);
+        return m_ComputePipelineManager->createComputePipeline(config.getShaderProgram(), layouts);
     }
 
     PassHandle Core::createPass(const PassConfig &config) {
@@ -430,7 +430,7 @@ namespace vkcv
 			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
 
 			const GraphicsPipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
-			if (pipeConfig.m_UseDynamicViewport) {
+			if (pipeConfig.isViewportDynamic()) {
 				recordDynamicViewport(cmdBuffer, width, height);
 			}
 
@@ -503,7 +503,7 @@ namespace vkcv
             cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
 
             const GraphicsPipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
-            if (pipeConfig.m_UseDynamicViewport) {
+            if (pipeConfig.isViewportDynamic()) {
                 recordDynamicViewport(cmdBuffer, width, height);
             }
 
@@ -635,7 +635,7 @@ namespace vkcv
 			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
 
 			const GraphicsPipelineConfig& pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
-			if (pipeConfig.m_UseDynamicViewport) {
+			if (pipeConfig.isViewportDynamic()) {
 				recordDynamicViewport(cmdBuffer, width, height);
 			}
 
diff --git a/src/vkcv/GraphicsPipelineConfig.cpp b/src/vkcv/GraphicsPipelineConfig.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5dea0238dc3f469b56166dc81b10aebe0d5b4cc7
--- /dev/null
+++ b/src/vkcv/GraphicsPipelineConfig.cpp
@@ -0,0 +1,129 @@
+
+#include "vkcv/GraphicsPipelineConfig.hpp"
+
+namespace vkcv {
+	
+	GraphicsPipelineConfig::GraphicsPipelineConfig()
+	: PipelineConfig(),
+	m_PassHandle(),
+	m_VertexLayout(),
+	m_Width(std::numeric_limits<uint32_t>::max()),
+	m_Height(std::numeric_limits<uint32_t>::max()) {}
+	
+	GraphicsPipelineConfig::GraphicsPipelineConfig(const ShaderProgram &program,
+												   const PassHandle &pass,
+												   const VertexLayout &vertexLayout,
+												   const std::vector<DescriptorSetLayoutHandle> &layouts)
+												   : PipelineConfig(program, layouts),
+												   m_PassHandle(pass),
+												   m_VertexLayout(vertexLayout),
+												   m_Width(std::numeric_limits<uint32_t>::max()),
+												   m_Height(std::numeric_limits<uint32_t>::max()) {}
+	
+	const PassHandle &GraphicsPipelineConfig::getPass() const {
+		return m_PassHandle;
+	}
+	
+	const VertexLayout &GraphicsPipelineConfig::getVertexLayout() const {
+		return m_VertexLayout;
+	}
+	
+	uint32_t GraphicsPipelineConfig::getWidth() const {
+		return m_Width;
+	}
+	
+	uint32_t GraphicsPipelineConfig::getHeight() const {
+		return m_Height;
+	}
+	
+	void GraphicsPipelineConfig::setResolution(uint32_t width, uint32_t height) {
+		m_Width = width;
+		m_Height = height;
+	}
+	
+	bool GraphicsPipelineConfig::isViewportDynamic() const {
+		return ((m_Width == std::numeric_limits<uint32_t>::max()) &&
+				(m_Height == std::numeric_limits<uint32_t>::max()));
+	}
+	
+	bool GraphicsPipelineConfig::isUsingConservativeRasterization() const {
+		return m_UseConservativeRasterization;
+	}
+	
+	void GraphicsPipelineConfig::setUsingConservativeRasterization(bool conservativeRasterization) {
+		m_UseConservativeRasterization = conservativeRasterization;
+	}
+	
+	PrimitiveTopology GraphicsPipelineConfig::getPrimitiveTopology() const {
+		return m_PrimitiveTopology;
+	}
+	
+	void GraphicsPipelineConfig::setPrimitiveTopology(PrimitiveTopology primitiveTopology) {
+		m_PrimitiveTopology = primitiveTopology;
+	}
+	
+	BlendMode GraphicsPipelineConfig::getBlendMode() const {
+		return m_blendMode;
+	}
+	
+	void GraphicsPipelineConfig::setBlendMode(BlendMode blendMode) {
+		m_blendMode = blendMode;
+	}
+	
+	bool GraphicsPipelineConfig::isDepthClampingEnabled() const {
+		return m_EnableDepthClamping;
+	}
+	
+	void GraphicsPipelineConfig::setDepthClampingEnabled(bool depthClamping) {
+		m_EnableDepthClamping = depthClamping;
+	}
+	
+	Multisampling GraphicsPipelineConfig::getMultisampling() const {
+		return m_Multisampling;
+	}
+	
+	void GraphicsPipelineConfig::setMultisampling(Multisampling multisampling) {
+		m_Multisampling = multisampling;
+	}
+	
+	CullMode GraphicsPipelineConfig::getCulling() const {
+		return m_Culling;
+	}
+	
+	void GraphicsPipelineConfig::setCulling(CullMode cullMode) {
+		m_Culling = cullMode;
+	}
+	
+	DepthTest GraphicsPipelineConfig::getDepthTest() const {
+		return m_DepthTest;
+	}
+	
+	void GraphicsPipelineConfig::setDepthTest(DepthTest depthTest) {
+		m_DepthTest = depthTest;
+	}
+	
+	bool GraphicsPipelineConfig::isWritingDepth() const {
+		return m_DepthWrite;
+	}
+	
+	void GraphicsPipelineConfig::setWritingDepth(bool writingDepth) {
+		m_DepthWrite = writingDepth;
+	}
+	
+	bool GraphicsPipelineConfig::isWritingAlphaToCoverage() const {
+		return m_AlphaToCoverage;
+	}
+	
+	void GraphicsPipelineConfig::setWritingAlphaToCoverage(bool alphaToCoverage) {
+		m_AlphaToCoverage = alphaToCoverage;
+	}
+	
+	uint32_t GraphicsPipelineConfig::getTesselationControlPoints() const {
+		return m_TessellationControlPoints;
+	}
+	
+	void GraphicsPipelineConfig::setTesselationControlPoints(uint32_t tessellationControlPoints) {
+		m_TessellationControlPoints = tessellationControlPoints;
+	}
+	
+}
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index 2ebc84ad476bf911e42fc71bbc575db6b16db081..9f30d92e728739fe13b2186bd16736b161979abe 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -141,7 +141,7 @@ namespace vkcv
 			const GraphicsPipelineConfig &config) {
 		
 		if (existsVertexShader) {
-			const VertexLayout& layout = config.m_VertexLayout;
+			const VertexLayout& layout = config.getVertexLayout();
 			
 			// iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer
 			for (const auto& vertexBinding : layout.vertexBindings)
@@ -190,7 +190,7 @@ namespace vkcv
 	vk::PipelineInputAssemblyStateCreateInfo createPipelineInputAssemblyStateCreateInfo(const GraphicsPipelineConfig &config) {
 		vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
 				{},
-				primitiveTopologyToVulkanPrimitiveTopology(config.m_PrimitiveTopology),
+				primitiveTopologyToVulkanPrimitiveTopology(config.getPrimitiveTopology()),
 				false
 		);
 		
@@ -200,7 +200,7 @@ namespace vkcv
 	vk::PipelineTessellationStateCreateInfo createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) {
 		vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo(
 				{},
-				config.m_tessellationControlPoints
+				config.getTesselationControlPoints()
 		);
 		
 		return pipelineTessellationStateCreateInfo;
@@ -217,14 +217,14 @@ namespace vkcv
 		
 		viewport = vk::Viewport(
 				0.f, 0.f,
-				static_cast<float>(config.m_Width),
-				static_cast<float>(config.m_Height),
+				static_cast<float>(config.getWidth()),
+				static_cast<float>(config.getHeight()),
 				0.f, 1.f
 		);
 		
 		scissor = vk::Rect2D(
 				{ 0,0 },
-				{ config.m_Width, config.m_Height }
+				{ config.getWidth(), config.getHeight() }
 		);
 		
 		vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
@@ -253,7 +253,7 @@ namespace vkcv
 		const GraphicsPipelineConfig &config,
 		const vk::PhysicalDeviceConservativeRasterizationPropertiesEXT& conservativeRasterProperties) {
 		vk::CullModeFlags cullMode;
-		switch (config.m_culling) {
+		switch (config.getCulling()) {
 			case CullMode::None:
 				cullMode = vk::CullModeFlagBits::eNone;
 				break;
@@ -273,7 +273,7 @@ namespace vkcv
 		
 		vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo (
 				{},
-				config.m_EnableDepthClamping,
+				config.isDepthClampingEnabled(),
 				false,
 				vk::PolygonMode::eFill,
 				cullMode,
@@ -287,7 +287,7 @@ namespace vkcv
 
 		static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization;
 		
-		if (config.m_UseConservativeRasterization) {
+		if (config.isUsingConservativeRasterization()) {
             const float overestimationSize = 1.0f - conservativeRasterProperties.primitiveOverestimationSize;
             const float maxOverestimationSize = conservativeRasterProperties.maxExtraPrimitiveOverestimationSize;
 
@@ -311,11 +311,11 @@ namespace vkcv
 	vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config) {
 		vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
 				{},
-				msaaToVkSampleCountFlag(config.m_multisampling),
+				msaaToVkSampleCountFlag(config.getMultisampling()),
 				false,
 				0.f,
 				nullptr,
-				config.m_alphaToCoverage,
+				config.isWritingAlphaToCoverage(),
 				false
 		);
 		
@@ -332,7 +332,7 @@ namespace vkcv
 		// 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,
+				config.getBlendMode() != BlendMode::None,
 				vk::BlendFactor::eOne,
 				vk::BlendFactor::eOne,
 				vk::BlendOp::eAdd,
@@ -368,7 +368,7 @@ namespace vkcv
 																const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) {
 		static vk::PushConstantRange pushConstantRange;
 		
-		const size_t pushConstantsSize = config.m_ShaderProgram.getPushConstantsSize();
+		const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize();
 		pushConstantRange = vk::PushConstantRange(
 				vk::ShaderStageFlagBits::eAll, 0, pushConstantsSize
 		);
@@ -394,9 +394,9 @@ namespace vkcv
 	vk::PipelineDepthStencilStateCreateInfo createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) {
 		const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo(
 				vk::PipelineDepthStencilStateCreateFlags(),
-				config.m_depthTest != DepthTest::None,
-				config.m_depthWrite,
-				depthTestToVkCompareOp(config.m_depthTest),
+				config.getDepthTest() != DepthTest::None,
+				config.isWritingDepth(),
+				depthTestToVkCompareOp(config.getDepthTest()),
 				false,
 				false,
 				{},
@@ -417,7 +417,7 @@ namespace vkcv
 		static std::vector<vk::DynamicState> dynamicStates;
 		dynamicStates.clear();
 		
-		if(config.m_UseDynamicViewport) {
+		if(config.isViewportDynamic()) {
 			dynamicStates.push_back(vk::DynamicState::eViewport);
 			dynamicStates.push_back(vk::DynamicState::eScissor);
 		}
@@ -434,15 +434,17 @@ namespace vkcv
     GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config,
 																   const PassManager& passManager,
 																   const DescriptorManager& descriptorManager) {
-        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 existsTessellationControlShader = config.m_ShaderProgram.existsShader(ShaderStage::TESS_CONTROL);
-		const bool existsTessellationEvaluationShader = config.m_ShaderProgram.existsShader(ShaderStage::TESS_EVAL);
+        const vk::RenderPass &pass = passManager.getVkPass(config.getPass());
+
+		const auto& program = config.getShaderProgram();
+		
+        const bool existsTaskShader     = program.existsShader(ShaderStage::TASK);
+        const bool existsMeshShader     = program.existsShader(ShaderStage::MESH);
+        const bool existsVertexShader   = program.existsShader(ShaderStage::VERTEX);
+        const bool existsFragmentShader = program.existsShader(ShaderStage::FRAGMENT);
+        const bool existsGeometryShader = program.existsShader(ShaderStage::GEOMETRY);
+		const bool existsTessellationControlShader = program.existsShader(ShaderStage::TESS_CONTROL);
+		const bool existsTessellationEvaluationShader = program.existsShader(ShaderStage::TESS_EVAL);
 		
         const bool validGeometryStages  = (
 				(existsVertexShader && (existsTessellationControlShader == existsTessellationEvaluationShader)) ||
@@ -471,7 +473,7 @@ namespace vkcv
         if (existsVertexShader) {
             vk::PipelineShaderStageCreateInfo createInfo;
             const bool success = createPipelineShaderStageCreateInfo(
-                    config.m_ShaderProgram,
+					program,
                     ShaderStage::VERTEX,
                     m_Device,
                     &createInfo);
@@ -488,7 +490,7 @@ namespace vkcv
         if (existsTaskShader) {
             vk::PipelineShaderStageCreateInfo createInfo;
             const bool success = createPipelineShaderStageCreateInfo(
-                    config.m_ShaderProgram,
+					program,
                     ShaderStage::TASK,
                     m_Device,
                     &createInfo);
@@ -505,7 +507,7 @@ namespace vkcv
         if (existsMeshShader) {
             vk::PipelineShaderStageCreateInfo createInfo;
             const bool success = createPipelineShaderStageCreateInfo(
-                    config.m_ShaderProgram,
+					program,
                     ShaderStage::MESH,
                     m_Device,
                     &createInfo);
@@ -522,7 +524,7 @@ namespace vkcv
         {
             vk::PipelineShaderStageCreateInfo createInfo;
             const bool success = createPipelineShaderStageCreateInfo(
-                    config.m_ShaderProgram,
+					program,
                     ShaderStage::FRAGMENT,
                     m_Device,
                     &createInfo);
@@ -539,7 +541,7 @@ namespace vkcv
         if (existsGeometryShader) {
             vk::PipelineShaderStageCreateInfo createInfo;
             const bool success = createPipelineShaderStageCreateInfo(
-                    config.m_ShaderProgram,
+					program,
                     ShaderStage::GEOMETRY,
                     m_Device,
                     &createInfo);
@@ -556,7 +558,7 @@ namespace vkcv
 		if (existsTessellationControlShader) {
 			vk::PipelineShaderStageCreateInfo createInfo;
 			const bool success = createPipelineShaderStageCreateInfo(
-					config.m_ShaderProgram,
+					program,
 					ShaderStage::TESS_CONTROL,
 					m_Device,
 					&createInfo);
@@ -573,7 +575,7 @@ namespace vkcv
 		if (existsTessellationEvaluationShader) {
 			vk::PipelineShaderStageCreateInfo createInfo;
 			const bool success = createPipelineShaderStageCreateInfo(
-					config.m_ShaderProgram,
+					program,
 					ShaderStage::TESS_EVAL,
 					m_Device,
 					&createInfo);
@@ -632,8 +634,8 @@ namespace vkcv
                 createPipelineDynamicStateCreateInfo(config);
 
 		std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
-		descriptorSetLayouts.reserve(config.m_DescriptorLayouts.size());
-		for (const auto& handle : config.m_DescriptorLayouts) {
+		descriptorSetLayouts.reserve(config.getDescriptorSetLayouts().size());
+		for (const auto& handle : config.getDescriptorSetLayouts()) {
 			descriptorSetLayouts.push_back(descriptorManager.getDescriptorSetLayout(handle).vulkanHandle);
 		}
 		
@@ -652,7 +654,7 @@ namespace vkcv
                 createPipelineDepthStencilStateCreateInfo(config);
 
         const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr;
-        const PassConfig& passConfig = passManager.getPassConfig(config.m_PassHandle);
+        const PassConfig& passConfig = passManager.getPassConfig(config.getPass());
 
         for (const auto& attachment : passConfig.attachments) {
             if (isDepthFormat(attachment.format)) {
diff --git a/src/vkcv/PipelineConfig.cpp b/src/vkcv/PipelineConfig.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7585f9fe6d95eaf0409eb187d9da43162770719f
--- /dev/null
+++ b/src/vkcv/PipelineConfig.cpp
@@ -0,0 +1,36 @@
+
+#include "vkcv/PipelineConfig.hpp"
+
+namespace vkcv {
+	
+	PipelineConfig::PipelineConfig() : m_ShaderProgram(), m_DescriptorSetLayouts() {}
+	
+	PipelineConfig::PipelineConfig(const ShaderProgram &program,
+								   const std::vector<DescriptorSetLayoutHandle> &layouts)
+								   : m_ShaderProgram(program), m_DescriptorSetLayouts(layouts) {}
+	
+	void PipelineConfig::setShaderProgram(const ShaderProgram& program) {
+		m_ShaderProgram = program;
+	}
+	
+	const ShaderProgram &PipelineConfig::getShaderProgram() const {
+		return m_ShaderProgram;
+	}
+	
+	void PipelineConfig::addDescriptorSetLayout(const DescriptorSetLayoutHandle &layout) {
+		m_DescriptorSetLayouts.push_back(layout);
+	}
+	
+	void PipelineConfig::addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts) {
+		m_DescriptorSetLayouts.reserve(m_DescriptorSetLayouts.size() + layouts.size());
+		
+		for (const auto& layout : layouts) {
+			m_DescriptorSetLayouts.push_back(layout);
+		}
+	}
+	
+	const std::vector<DescriptorSetLayoutHandle> &PipelineConfig::getDescriptorSetLayouts() const {
+		return m_DescriptorSetLayouts;
+	}
+	
+}