From e3736739e0177b79c4c75424409ca055b2bd6275 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Tue, 30 Aug 2022 01:47:39 +0200
Subject: [PATCH] Abstracing pass configuration, adding clear values and
 reducing redundancy

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 config/Sources.cmake                        |   1 +
 include/vkcv/GraphicsPipelineConfig.hpp     |   6 -
 include/vkcv/PassConfig.hpp                 |  59 ++++++----
 projects/bindless_textures/src/main.cpp     |  10 +-
 projects/fire_works/src/main.cpp            |   6 +-
 projects/first_mesh/src/main.cpp            |  10 +-
 projects/first_scene/src/main.cpp           |  12 +-
 projects/first_triangle/src/main.cpp        |   7 +-
 projects/head_demo/src/main.cpp             |  16 +--
 projects/indirect_dispatch/src/AppSetup.cpp |  56 +++++----
 projects/indirect_draw/src/main.cpp         |  15 +--
 projects/mesh_shader/src/main.cpp           |  13 ++-
 projects/particle_simulation/src/main.cpp   |   7 +-
 projects/saf_r/src/main.cpp                 |   7 +-
 projects/sph/src/main.cpp                   |   8 +-
 projects/voxelization/src/ShadowMapping.cpp |   7 +-
 projects/voxelization/src/Voxelization.cpp  |  25 ++--
 projects/voxelization/src/main.cpp          |  44 +++----
 projects/wobble_bobble/src/main.cpp         |  24 ++--
 src/vkcv/Core.cpp                           |  15 +--
 src/vkcv/GraphicsPipelineConfig.cpp         |   8 --
 src/vkcv/GraphicsPipelineManager.cpp        |  13 ++-
 src/vkcv/PassConfig.cpp                     |  59 ++++++++++
 src/vkcv/PassManager.cpp                    | 122 ++++++++++++--------
 24 files changed, 322 insertions(+), 228 deletions(-)
 create mode 100644 src/vkcv/PassConfig.cpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index 85a87f5d..45dc8bc8 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -17,6 +17,7 @@ set(vkcv_sources
 		${vkcv_source}/vkcv/File.cpp
 
 		${vkcv_include}/vkcv/PassConfig.hpp
+		${vkcv_source}/vkcv/PassConfig.cpp
 
 		${vkcv_source}/vkcv/PassManager.hpp
 		${vkcv_source}/vkcv/PassManager.cpp
diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp
index e4257735..91e9fa75 100644
--- a/include/vkcv/GraphicsPipelineConfig.hpp
+++ b/include/vkcv/GraphicsPipelineConfig.hpp
@@ -71,7 +71,6 @@ namespace vkcv {
         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;
@@ -131,11 +130,6 @@ namespace vkcv {
 		
 		void setDepthClampingEnabled(bool depthClamping);
 	
-		[[nodiscard]]
-		Multisampling getMultisampling() const;
-		
-		void setMultisampling(Multisampling multisampling);
-	
 		[[nodiscard]]
 		CullMode getCulling() const;
 		
diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp
index 26c4f815..7f06ab14 100644
--- a/include/vkcv/PassConfig.hpp
+++ b/include/vkcv/PassConfig.hpp
@@ -12,25 +12,6 @@
 
 namespace vkcv
 {
-	
-	/**
-	 * @brief Enum class to specify kinds of attachment layouts.
-	 */
-    enum class AttachmentLayout {
-        UNDEFINED,
-        GENERAL,
-
-        COLOR_ATTACHMENT,
-        SHADER_READ_ONLY,
-
-        DEPTH_STENCIL_ATTACHMENT,
-        DEPTH_STENCIL_READ_ONLY,
-
-        TRANSFER_SRC,
-        TRANSFER_DST,
-
-        PRESENTATION
-    };
 
 	/**
 	 * @brief Enum class to specify types of attachment operations.
@@ -45,10 +26,42 @@ namespace vkcv
 	/**
 	 * @brief Structure to store details about an attachment of a pass.
 	 */
-    struct AttachmentDescription {
-        AttachmentOperation store_operation;
-        AttachmentOperation load_operation;
-        vk::Format format;
+    class AttachmentDescription {
+	private:
+		vk::Format m_format;
+	
+		AttachmentOperation m_load_op;
+        AttachmentOperation m_store_op;
+		
+		vk::ClearValue m_clear_value;
+	public:
+		AttachmentDescription(vk::Format format,
+							  AttachmentOperation load,
+							  AttachmentOperation store);
+		
+		AttachmentDescription(vk::Format format,
+							  AttachmentOperation load,
+							  AttachmentOperation store,
+							  const vk::ClearValue &clear);
+	
+		AttachmentDescription(const AttachmentDescription &other) = default;
+		AttachmentDescription(AttachmentDescription &&other) = default;
+		
+		~AttachmentDescription() = default;
+	
+		AttachmentDescription& operator=(const AttachmentDescription &other) = default;
+		AttachmentDescription& operator=(AttachmentDescription &&other) = default;
+		
+		vk::Format getFormat() const;
+	
+		AttachmentOperation getLoadOperation() const;
+	
+		AttachmentOperation getStoreOperation() const;
+		
+		void setClearValue(const vk::ClearValue &clear);
+	
+		const vk::ClearValue& getClearValue() const;
+		
     };
 
 	/**
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index bec0ca45..f196db2e 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -101,15 +101,15 @@ int main(int argc, const char** argv) {
 
 	// an example attachment for passes that output to the window
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain())
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment(
-			vkcv::AttachmentOperation::STORE,
+			vk::Format::eD32Sfloat,
 			vkcv::AttachmentOperation::CLEAR,
-			vk::Format::eD32Sfloat
+			vkcv::AttachmentOperation::STORE
 	);
 
 	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment }, vkcv::Multisampling::None);
diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp
index 9f086bdf..500f5f5e 100644
--- a/projects/fire_works/src/main.cpp
+++ b/projects/fire_works/src/main.cpp
@@ -590,10 +590,10 @@ int main(int argc, const char **argv) {
 	vkcv::PassHandle renderPass = core.createPass(vkcv::PassConfig(
 		{
 			vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				colorFormat,
 				vkcv::AttachmentOperation::CLEAR,
-				colorFormat
-				)
+				vkcv::AttachmentOperation::STORE
+			)
 		},
 		vkcv::Multisampling::None
 	));
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index c68238d4..356fd9f1 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -52,15 +52,15 @@ int main(int argc, const char** argv) {
 
 	// an example attachment for passes that output to the window
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain())
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment(
-			vkcv::AttachmentOperation::STORE,
+			vk::Format::eD32Sfloat,
 			vkcv::AttachmentOperation::CLEAR,
-			vk::Format::eD32Sfloat
+			vkcv::AttachmentOperation::STORE
 	);
 
 	vkcv::PassConfig firstMeshPassDefinition(
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index dfa58d88..bd3b2ac7 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -49,15 +49,15 @@ int main(int argc, const char** argv) {
 	));
 
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain())
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
 
 	const vkcv::AttachmentDescription depth_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		vk::Format::eD32Sfloat
+			vk::Format::eD32Sfloat,
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
 
 	vkcv::PassConfig scenePassDefinition(
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 4723d17e..edf8fa8f 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -30,9 +30,10 @@ int main(int argc, const char** argv) {
 	
 	// an example attachment for passes that output to the window
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain()));
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::PassConfig trianglePassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
 	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index fb3170d4..9c92128f 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -44,27 +44,27 @@ int main(int argc, const char** argv) {
 	vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
 	
 	const vkcv::AttachmentDescription color_attachment0(
-			vkcv::AttachmentOperation::STORE,
+			colorFormat,
 			vkcv::AttachmentOperation::CLEAR,
-			colorFormat
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment0(
-			vkcv::AttachmentOperation::STORE,
+			vk::Format::eD32Sfloat,
 			vkcv::AttachmentOperation::CLEAR,
-			vk::Format::eD32Sfloat
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vkcv::AttachmentDescription color_attachment1(
-			vkcv::AttachmentOperation::STORE,
+			colorFormat,
 			vkcv::AttachmentOperation::LOAD,
-			colorFormat
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment1(
-			vkcv::AttachmentOperation::STORE,
+			vk::Format::eD32Sfloat,
 			vkcv::AttachmentOperation::LOAD,
-			vk::Format::eD32Sfloat
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	vkcv::PassConfig linePassDefinition(
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 8a5977ce..4f008586 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -160,14 +160,16 @@ bool loadMeshPass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 	assert(outHandles);
 
 	vkcv::AttachmentDescription colorAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::DONT_CARE,
-		AppConfig::colorBufferFormat);
+			AppConfig::colorBufferFormat,
+			vkcv::AttachmentOperation::DONT_CARE,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::AttachmentDescription depthAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		AppConfig::depthBufferFormat);
+			AppConfig::depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	return loadGraphicPass(
 		core,
@@ -186,14 +188,16 @@ bool loadSkyPass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 	assert(outHandles);
 
 	vkcv::AttachmentDescription colorAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		AppConfig::colorBufferFormat);
+			AppConfig::colorBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::AttachmentDescription depthAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		AppConfig::depthBufferFormat);
+			AppConfig::depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	return loadGraphicPass(
 		core,
@@ -211,14 +215,16 @@ bool loadPrePass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 	assert(outHandles);
 
 	vkcv::AttachmentDescription motionAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		AppConfig::motionBufferFormat);
+			AppConfig::motionBufferFormat,
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::AttachmentDescription depthAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		AppConfig::depthBufferFormat);
+			AppConfig::depthBufferFormat,
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	return loadGraphicPass(
 		core,
@@ -236,14 +242,16 @@ bool loadSkyPrePass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 	assert(outHandles);
 
 	vkcv::AttachmentDescription motionAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		AppConfig::motionBufferFormat);
+			AppConfig::motionBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::AttachmentDescription depthAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		AppConfig::depthBufferFormat);
+			AppConfig::depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	return loadGraphicPass(
 		core,
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index ce4bada1..f3fa7f8d 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -328,15 +328,16 @@ int main(int argc, const char** argv) {
         return EXIT_FAILURE;
     }
 
-    const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain())
+    const vkcv::AttachmentDescription present_color_attachment (
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
-	const vkcv::AttachmentDescription depth_attachment(
-			vkcv::AttachmentOperation::STORE,
+	
+	const vkcv::AttachmentDescription depth_attachment (
+			vk::Format::eD32Sfloat,
 			vkcv::AttachmentOperation::CLEAR,
-			vk::Format::eD32Sfloat
+			vkcv::AttachmentOperation::STORE
 	);
 
 	vkcv::PassConfig passDefinition({ present_color_attachment, depth_attachment }, vkcv::Multisampling::None);
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 34a9de9e..77df9f4e 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -164,14 +164,15 @@ int main(int argc, const char** argv) {
 
 	// attachments
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain()));
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
     const vkcv::AttachmentDescription depth_attachment(
-            vkcv::AttachmentOperation::STORE,
-            vkcv::AttachmentOperation::CLEAR,
-            vk::Format::eD32Sfloat
+			vk::Format::eD32Sfloat,
+			vkcv::AttachmentOperation::CLEAR,
+            vkcv::AttachmentOperation::STORE
     );
 
 	vkcv::PassConfig bunnyPassDefinition(
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index c87afc98..a1e40221 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -35,9 +35,10 @@ int main(int argc, const char **argv) {
     vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
     // an example attachment for passes that output to the window
     const vkcv::AttachmentDescription present_color_attachment(
-            vkcv::AttachmentOperation::STORE,
-            vkcv::AttachmentOperation::CLEAR,
-            colorFormat);
+			colorFormat,
+			vkcv::AttachmentOperation::CLEAR,
+            vkcv::AttachmentOperation::STORE
+	);
 
 
     vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index dda23973..19ecf20d 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -163,9 +163,10 @@ int main(int argc, const char** argv) {
 
 	// an example attachment for passes that output to the window
 	const vkcv::AttachmentDescription present_color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainFormat(window.getSwapchain()));
+			core.getSwapchainFormat(window.getSwapchain()),
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::PassConfig safrPassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
 	vkcv::PassHandle safrPass = core.createPass(safrPassDefinition);
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index a5bf4bf0..f6ed0505 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -33,10 +33,10 @@ int main(int argc, const char **argv) {
     vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
     // an example attachment for passes that output to the window
     const vkcv::AttachmentDescription present_color_attachment(
-            vkcv::AttachmentOperation::STORE,
-            vkcv::AttachmentOperation::CLEAR,
-            colorFormat);
-
+			colorFormat,
+			vkcv::AttachmentOperation::CLEAR,
+            vkcv::AttachmentOperation::STORE
+	);
 
     vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
     vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 6aa31577..990007cb 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -160,7 +160,11 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 
 	// pass
 	const std::vector<vkcv::AttachmentDescription> shadowAttachments = {
-		vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapDepthFormat)
+		vkcv::AttachmentDescription(
+				shadowMapDepthFormat,
+				vkcv::AttachmentOperation::CLEAR,
+				vkcv::AttachmentOperation::STORE
+		)
 	};
 	vkcv::PassConfig shadowPassConfig(shadowAttachments, msaa);
 	m_shadowMapPass = corePtr->createPass(shadowPassConfig);
@@ -174,7 +178,6 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	);
 	
 	shadowPipeConfig.setResolution(shadowMapResolution, shadowMapResolution);
-	shadowPipeConfig.setMultisampling(msaa);
 	shadowPipeConfig.setDepthClampingEnabled(true);
 	shadowPipeConfig.setCulling(vkcv::CullMode::Front);
 	m_shadowMapPipe = corePtr->createGraphicsPipeline(shadowPipeConfig);
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index dd2cda78..63316208 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -93,11 +93,11 @@ Voxelization::Voxelization(
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
 
 	const vkcv::PassConfig voxelizationPassConfig {{
-		  {
+		  vkcv::AttachmentDescription(
+				  voxelizationDummyFormat,
 				  vkcv::AttachmentOperation::DONT_CARE,
-				  vkcv::AttachmentOperation::DONT_CARE,
-				  voxelizationDummyFormat
-		  }
+				  vkcv::AttachmentOperation::DONT_CARE
+		  )
 	}, vkcv::Multisampling::None };
 	m_voxelizationPass = m_corePtr->createPass(voxelizationPassConfig);
 
@@ -137,16 +137,16 @@ Voxelization::Voxelization(
 	m_visualisationDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelVisualisationShader.getReflectedDescriptors().at(0));
 	m_visualisationDescriptorSet = m_corePtr->createDescriptorSet(m_visualisationDescriptorSetLayout);
 
-	const vkcv::AttachmentDescription voxelVisualisationColorAttachments(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		dependencies.colorBufferFormat
+	const vkcv::AttachmentDescription voxelVisualisationColorAttachments (
+			dependencies.colorBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
 	);
 
-	const vkcv::AttachmentDescription voxelVisualisationDepthAttachments(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		dependencies.depthBufferFormat
+	const vkcv::AttachmentDescription voxelVisualisationDepthAttachments (
+			dependencies.depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
 	);
 
 	vkcv::PassConfig voxelVisualisationPassDefinition{
@@ -164,7 +164,6 @@ Voxelization::Voxelization(
 	);	// 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 449993d1..e2e1f0ee 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -181,17 +181,17 @@ int main(int argc, const char** argv) {
 	}
 
 	const vk::Format colorBufferFormat = vk::Format::eB10G11R11UfloatPack32;
-	const vkcv::AttachmentDescription color_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		colorBufferFormat
+	const vkcv::AttachmentDescription color_attachment (
+			colorBufferFormat,
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	const vk::Format depthBufferFormat = vk::Format::eD32Sfloat;
-	const vkcv::AttachmentDescription depth_attachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		depthBufferFormat
+	const vkcv::AttachmentDescription depth_attachment (
+			depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
 	);
 	
 	// forward shading config
@@ -241,9 +241,10 @@ int main(int argc, const char** argv) {
 	const vkcv::VertexLayout prepassVertexLayout { prepassVertexBindings };
 
 	const vkcv::AttachmentDescription prepassAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::CLEAR,
-		depthBufferFormat);
+			depthBufferFormat,
+			vkcv::AttachmentOperation::CLEAR,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::PassConfig prepassPassDefinition({ prepassAttachment }, msaa);
 	vkcv::PassHandle prepassPass = core.createPass(prepassPassDefinition);
@@ -343,7 +344,6 @@ int main(int argc, const char** argv) {
 	);
 	
 	prepassPipelineConfig.setCulling(vkcv::CullMode::Back);
-	prepassPipelineConfig.setMultisampling(msaa);
 	prepassPipelineConfig.setDepthTest(vkcv::DepthTest::LessEqual);
 	prepassPipelineConfig.setWritingAlphaToCoverage(true);
 
@@ -358,7 +358,6 @@ int main(int argc, const char** argv) {
 	);
 	
 	forwardPipelineConfig.setCulling(vkcv::CullMode::Back);
-	forwardPipelineConfig.setMultisampling(msaa);
 	forwardPipelineConfig.setDepthTest(vkcv::DepthTest::Equal);
 	forwardPipelineConfig.setWritingDepth(false);
 	
@@ -378,15 +377,17 @@ int main(int argc, const char** argv) {
 	skySettings.color       = glm::vec3(0.15, 0.65, 1);
 	skySettings.strength    = 5;
 
-	const vkcv::AttachmentDescription skyColorAttachment(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		colorBufferFormat);
+	const vkcv::AttachmentDescription skyColorAttachment (
+			colorBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
-	const vkcv::AttachmentDescription skyDepthAttachments(
-		vkcv::AttachmentOperation::STORE,
-		vkcv::AttachmentOperation::LOAD,
-		depthBufferFormat);
+	const vkcv::AttachmentDescription skyDepthAttachments (
+			depthBufferFormat,
+			vkcv::AttachmentOperation::LOAD,
+			vkcv::AttachmentOperation::STORE
+	);
 
 	vkcv::PassConfig skyPassConfig({ skyColorAttachment, skyDepthAttachments }, msaa);
 	vkcv::PassHandle skyPass = core.createPass(skyPassConfig);
@@ -408,7 +409,6 @@ int main(int argc, const char** argv) {
 			{}
 	);
 	
-	skyPipeConfig.setMultisampling(msaa);
 	skyPipeConfig.setWritingDepth(false);
 
 	vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 5e31155d..23ab97c5 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -456,40 +456,40 @@ int main(int argc, const char **argv) {
 	
 	vkcv::PassConfig passConfigGrid {{
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				core.getSwapchainFormat(window.getSwapchain()),
 				vkcv::AttachmentOperation::CLEAR,
-				core.getSwapchainFormat(window.getSwapchain())
+				vkcv::AttachmentOperation::STORE
 		),
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				vk::Format::eD32Sfloat,
 				vkcv::AttachmentOperation::CLEAR,
-				vk::Format::eD32Sfloat
+				vkcv::AttachmentOperation::STORE
 		)
 	}, vkcv::Multisampling::None };
 	
 	vkcv::PassConfig passConfigParticles {{
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				core.getSwapchainFormat(window.getSwapchain()),
 				vkcv::AttachmentOperation::CLEAR,
-				core.getSwapchainFormat(window.getSwapchain())
+				vkcv::AttachmentOperation::STORE
 		),
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				vk::Format::eD32Sfloat,
 				vkcv::AttachmentOperation::CLEAR,
-				vk::Format::eD32Sfloat
+				vkcv::AttachmentOperation::STORE
 		)
 	}, vkcv::Multisampling::None };
 	
 	vkcv::PassConfig passConfigLines {{
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				core.getSwapchainFormat(window.getSwapchain()),
 				vkcv::AttachmentOperation::LOAD,
-				core.getSwapchainFormat(window.getSwapchain())
+				vkcv::AttachmentOperation::STORE
 		),
 		vkcv::AttachmentDescription(
-				vkcv::AttachmentOperation::STORE,
+				vk::Format::eD32Sfloat,
 				vkcv::AttachmentOperation::LOAD,
-				vk::Format::eD32Sfloat
+				vkcv::AttachmentOperation::STORE
 		)
 	}, vkcv::Multisampling::None };
 	
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 176e07ae..9cbba197 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -355,19 +355,8 @@ namespace vkcv
 	std::vector<vk::ClearValue> createAttachmentClearValues(const std::vector<AttachmentDescription>& attachments) {
 		std::vector<vk::ClearValue> clearValues;
 		for (const auto& attachment : attachments) {
-			if (attachment.load_operation == AttachmentOperation::CLEAR) {
-				float clear = 0.0f;
-
-				if (isDepthFormat(attachment.format)) {
-					clear = 1.0f;
-				}
-
-				clearValues.emplace_back(std::array<float, 4>{
-					clear,
-					clear,
-					clear,
-					0.f
-				});
+			if (attachment.getLoadOperation() == AttachmentOperation::CLEAR) {
+				clearValues.push_back(attachment.getClearValue());
 			}
 		}
 		return clearValues;
diff --git a/src/vkcv/GraphicsPipelineConfig.cpp b/src/vkcv/GraphicsPipelineConfig.cpp
index 5dea0238..37e86240 100644
--- a/src/vkcv/GraphicsPipelineConfig.cpp
+++ b/src/vkcv/GraphicsPipelineConfig.cpp
@@ -78,14 +78,6 @@ namespace vkcv {
 		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;
 	}
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index 95a33c08..57eedcac 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -326,10 +326,11 @@ namespace vkcv {
 	 * @param config set MSAA Sample Count Flag
 	 * @return Pipeline Multisample State Create Info Struct
 	 */
-	vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config) {
+	vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config,
+																					const PassConfig &passConfig) {
 		vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
 				{},
-				msaaToSampleCountFlagBits(config.getMultisampling()),
+				msaaToSampleCountFlagBits(passConfig.msaa),
 				false,
 				0.f,
 				nullptr,
@@ -598,6 +599,8 @@ namespace vkcv {
 				return {};
 			}
 		}
+	
+		const PassConfig& passConfig = passManager.getPassConfig(config.getPass());
 
         // vertex input state
         // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers
@@ -633,7 +636,7 @@ namespace vkcv {
 
         // multisample state
         vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
-                createPipelineMultisampleStateCreateInfo(config);
+                createPipelineMultisampleStateCreateInfo(config, passConfig);
 
         // color blend state
         vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo =
@@ -666,10 +669,10 @@ namespace vkcv {
                 createPipelineDepthStencilStateCreateInfo(config);
 
         const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr;
-        const PassConfig& passConfig = passManager.getPassConfig(config.getPass());
 
         for (const auto& attachment : passConfig.attachments) {
-            if (isDepthFormat(attachment.format)) {
+            if ((isDepthFormat(attachment.getFormat())) ||
+				(isStencilFormat(attachment.getFormat()))) {
                 p_depthStencilCreateInfo = &depthStencilCreateInfo;
                 break;
             }
diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp
new file mode 100644
index 00000000..bfb93c87
--- /dev/null
+++ b/src/vkcv/PassConfig.cpp
@@ -0,0 +1,59 @@
+
+#include "vkcv/PassConfig.hpp"
+#include "vkcv/Image.hpp"
+
+namespace vkcv
+{
+	
+	AttachmentDescription::AttachmentDescription(vk::Format format,
+												 AttachmentOperation load,
+												 AttachmentOperation store)
+			: m_format(format),
+			  m_load_op(load),
+			  m_store_op(store),
+			  m_clear_value()
+	{
+		if (isDepthFormat(format)) {
+			setClearValue(vk::ClearValue(
+					vk::ClearDepthStencilValue(1.0f, 0)
+			));
+		} else {
+			setClearValue(vk::ClearValue(
+					vk::ClearColorValue(std::array<float, 4>{
+							0.0f, 0.0f, 0.0f, 0.0f
+					})
+			));
+		}
+	}
+	
+	AttachmentDescription::AttachmentDescription(vk::Format format,
+												 AttachmentOperation load,
+												 AttachmentOperation store,
+												 const vk::ClearValue &clear)
+	: m_format(format),
+	  m_load_op(load),
+	  m_store_op(store),
+	  m_clear_value(clear)
+	{}
+	
+	vk::Format AttachmentDescription::getFormat() const {
+		return m_format;
+	}
+	
+	AttachmentOperation AttachmentDescription::getLoadOperation() const {
+		return m_load_op;
+	}
+	
+	AttachmentOperation AttachmentDescription::getStoreOperation() const {
+		return m_store_op;
+	}
+	
+	void AttachmentDescription::setClearValue(const vk::ClearValue &clear) {
+		m_clear_value = clear;
+	}
+	
+	const vk::ClearValue &AttachmentDescription::getClearValue() const {
+		return m_clear_value;
+	}
+	
+}
diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp
index 740ab333..71fa8006 100644
--- a/src/vkcv/PassManager.cpp
+++ b/src/vkcv/PassManager.cpp
@@ -59,63 +59,91 @@ namespace vkcv
         // individual references to color attachments (of a subpass)
         std::vector<vk::AttachmentReference> colorAttachmentReferences{};
         // individual reference to depth attachment (of a subpass)
-        vk::AttachmentReference depthAttachmentReference{};
-        vk::AttachmentReference *pDepthAttachment = nullptr;	//stays nullptr if no depth attachment used
+        vk::AttachmentReference depthStencilAttachmentRef;
+		
+		// stays nullptr if no depth attachment used
+        vk::AttachmentReference *pDepthStencil = nullptr;
+		
+		const auto &featureManager = getCore().getContext().getFeatureManager();
+	
+		const bool separateDepthStencil = (
+			featureManager.checkFeatures<vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>(
+				vk::StructureType::ePhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR,
+				[](const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR& features) {
+					return features.separateDepthStencilLayouts;
+				}
+			)
+		);
 
-        for (uint32_t i = 0; i < config.attachments.size(); i++)
-        {
-            // TODO: Renderpass struct should hold proper format information
-            vk::Format      format = config.attachments[i].format;
+        for (uint32_t i = 0; i < config.attachments.size(); i++) {
+            vk::Format format = config.attachments[i].getFormat();
             vk::ImageLayout layout;
-
-            if (isDepthFormat(config.attachments[i].format))
-            {
-                layout                              = vk::ImageLayout::eDepthStencilAttachmentOptimal;
-                depthAttachmentReference.attachment = i;
-                depthAttachmentReference.layout     = layout;
-                pDepthAttachment                    = &depthAttachmentReference;
-            }
-            else
-            {
-                layout = vk::ImageLayout::eColorAttachmentOptimal;
-                vk::AttachmentReference attachmentRef(i, layout);
+			
+			bool depthFormat = isDepthFormat(config.attachments[i].getFormat());
+			bool stencilFormat = isStencilFormat(config.attachments[i].getFormat());
+			
+            if ((separateDepthStencil) && (depthFormat) && (!stencilFormat)) {
+				layout = vk::ImageLayout::eDepthAttachmentOptimal;
+			} else
+			if ((separateDepthStencil) && (!depthFormat) && (stencilFormat)) {
+				layout = vk::ImageLayout::eStencilAttachmentOptimal;
+			} else
+			if ((depthFormat) || (stencilFormat)) {
+				layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
+			} else {
+				layout = vk::ImageLayout::eColorAttachmentOptimal;
+			}
+			
+			if ((depthFormat) || (stencilFormat)) {
+				depthStencilAttachmentRef = vk::AttachmentReference(i, layout);
+				pDepthStencil = &depthStencilAttachmentRef;
+            } else {
+                vk::AttachmentReference attachmentRef (i, layout);
                 colorAttachmentReferences.push_back(attachmentRef);
             }
 
-            vk::AttachmentDescription attachmentDesc(
-                {},
-                format,
-				msaaToSampleCountFlagBits(config.msaa),
-                getVKLoadOpFromAttachOp(config.attachments[i].load_operation),
-                getVkStoreOpFromAttachOp(config.attachments[i].store_operation),
-                vk::AttachmentLoadOp::eDontCare,
-                vk::AttachmentStoreOp::eDontCare,
-                layout,
-                layout);
+            vk::AttachmentDescription attachmentDesc (
+					{},
+					format,
+					msaaToSampleCountFlagBits(config.msaa),
+					getVKLoadOpFromAttachOp(config.attachments[i].getLoadOperation()),
+					getVkStoreOpFromAttachOp(config.attachments[i].getStoreOperation()),
+					vk::AttachmentLoadOp::eDontCare,
+					vk::AttachmentStoreOp::eDontCare,
+					layout,
+					layout
+			);
+	
+			if (stencilFormat) {
+				attachmentDesc.setStencilLoadOp(attachmentDesc.loadOp);
+				attachmentDesc.setStencilStoreOp(attachmentDesc.storeOp);
+			}
 
             attachmentDescriptions.push_back(attachmentDesc);
         }
         
-        const vk::SubpassDescription subpassDescription(
-            {},
-            vk::PipelineBindPoint::eGraphics,
-            0,
-            {},
-            static_cast<uint32_t>(colorAttachmentReferences.size()),
-            colorAttachmentReferences.data(),
-            {},
-            pDepthAttachment,
-            0,
-            {});
+        const vk::SubpassDescription subpassDescription (
+				{},
+				vk::PipelineBindPoint::eGraphics,
+				0,
+				{},
+				static_cast<uint32_t>(colorAttachmentReferences.size()),
+				colorAttachmentReferences.data(),
+				{},
+				pDepthStencil,
+				0,
+				{}
+		);
 
-        const vk::RenderPassCreateInfo passInfo(
-            {},
-            static_cast<uint32_t>(attachmentDescriptions.size()),
-            attachmentDescriptions.data(),
-            1,
-            &subpassDescription,
-            0,
-            {});
+        const vk::RenderPassCreateInfo passInfo (
+				{},
+				static_cast<uint32_t>(attachmentDescriptions.size()),
+				attachmentDescriptions.data(),
+				1,
+				&subpassDescription,
+				0,
+				{}
+		);
 
         vk::RenderPass renderPass = getCore().getContext().getDevice().createRenderPass(passInfo);
 
-- 
GitLab