diff --git a/config/Sources.cmake b/config/Sources.cmake
index 45dc8bc8248e19868234f9fa7963c5098838c22c..764ea2e74b8338467ecbf1d31a6a48a41997dd80 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -15,6 +15,9 @@ set(vkcv_sources
 		
 		${vkcv_include}/vkcv/File.hpp
 		${vkcv_source}/vkcv/File.cpp
+		
+		${vkcv_include}/vkcv/Pass.hpp
+		${vkcv_source}/vkcv/Pass.cpp
 
 		${vkcv_include}/vkcv/PassConfig.hpp
 		${vkcv_source}/vkcv/PassConfig.cpp
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index bf944a61305ffe43615862848e8594a15320b09c..e6c61cbb76a42439a33b780e9f2d9d3c57cb03c4 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -189,6 +189,16 @@ namespace vkcv
          */
         [[nodiscard]]
         PassHandle createPass(const PassConfig &config);
+		
+		/**
+		 * Returns the used configuration for a created render pass which is
+		 * represented by the given handle.
+		 *
+		 * @param[in] pass Pass handle
+		 * @return Pass configuration
+		 */
+		[[nodiscard]]
+		const PassConfig& getPassConfiguration(const PassHandle &pass);
 	
 		/**
 		 * @brief Creates a buffer with given parameters and returns its handle.
diff --git a/include/vkcv/Pass.hpp b/include/vkcv/Pass.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f931eef50d0c78d015ef08472b5513942773edc3
--- /dev/null
+++ b/include/vkcv/Pass.hpp
@@ -0,0 +1,31 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Pass.hpp
+ * @brief Support functions for basic pass creation.
+ */
+
+#include "Core.hpp"
+#include "Handles.hpp"
+#include "PassConfig.hpp"
+
+namespace vkcv
+{
+
+	PassHandle passFormats(Core &core,
+						   const std::vector<vk::Format> formats,
+						   bool clear = true,
+						   Multisampling multisampling = Multisampling::None);
+	
+	PassHandle passFormat(Core &core,
+						  vk::Format format,
+						  bool clear = true,
+						  Multisampling multisampling = Multisampling::None);
+	
+	PassHandle passSwapchain(Core &core,
+							 const SwapchainHandle &swapchain,
+							 const std::vector<vk::Format> formats,
+							 bool clear = true,
+							 Multisampling multisampling = Multisampling::None);
+	
+}
diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp
index 7f06ab141bf5893178341f0a80e3d4aa35f9b8a3..849a6e837acd6321afed6c99dc3b608ba26766b7 100644
--- a/include/vkcv/PassConfig.hpp
+++ b/include/vkcv/PassConfig.hpp
@@ -24,7 +24,7 @@ namespace vkcv
     };
 
 	/**
-	 * @brief Structure to store details about an attachment of a pass.
+	 * @brief Class to store details about an attachment of a pass.
 	 */
     class AttachmentDescription {
 	private:
@@ -51,25 +51,55 @@ namespace vkcv
 	
 		AttachmentDescription& operator=(const AttachmentDescription &other) = default;
 		AttachmentDescription& operator=(AttachmentDescription &&other) = default;
-		
+	
+		[[nodiscard]]
 		vk::Format getFormat() const;
 	
+		[[nodiscard]]
 		AttachmentOperation getLoadOperation() const;
 	
+		[[nodiscard]]
 		AttachmentOperation getStoreOperation() const;
 		
 		void setClearValue(const vk::ClearValue &clear);
 	
+		[[nodiscard]]
 		const vk::ClearValue& getClearValue() const;
 		
     };
+	
+	using AttachmentDescriptions = std::vector<AttachmentDescription>;
 
 	/**
-	 * @brief Structure to configure a pass for usage.
+	 * @brief Class to configure a pass for usage.
 	 */
-    struct PassConfig {
-		std::vector<AttachmentDescription> attachments;
-        Multisampling msaa;
+    class PassConfig {
+	private:
+		AttachmentDescriptions m_attachments;
+        Multisampling m_multisampling;
+		
+	public:
+		PassConfig();
+		
+		explicit PassConfig(const AttachmentDescriptions &attachments,
+							Multisampling multisampling = Multisampling::None);
+		
+		PassConfig(const PassConfig &other) = default;
+		PassConfig(PassConfig &&other) = default;
+		
+		~PassConfig() = default;
+	
+		PassConfig& operator=(const PassConfig &other) = default;
+		PassConfig& operator=(PassConfig &&other) = default;
+		
+		[[nodiscard]]
+		const AttachmentDescriptions& getAttachments() const;
+		
+		void setMultisampling(Multisampling multisampling);
+	
+		[[nodiscard]]
+		Multisampling getMultisampling() const;
+		
     };
 	
 }
\ No newline at end of file
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index f196db2e2812c6d46f2853f1e686b4238befce24..8f594e598a468c0db9b8f1f3fd703384577e4d6c 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -98,23 +99,13 @@ int main(int argc, const char** argv) {
 	);
 	
 	indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
-
-	// an example attachment for passes that output to the window
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
 	
-	const vkcv::AttachmentDescription depth_attachment(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
+	vkcv::PassHandle firstMeshPass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
 	);
 
-	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment }, vkcv::Multisampling::None);
-	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
-
 	if (!firstMeshPass) {
 		std::cerr << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp
index 500f5f5e45596ca136c717f05a9a052f124aadaa..a657d8bf69b964cd4a6c2a7551a1c65f8c7f134b 100644
--- a/projects/fire_works/src/main.cpp
+++ b/projects/fire_works/src/main.cpp
@@ -3,6 +3,7 @@
 
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/DrawcallRecording.hpp>
 
 #include <vkcv/camera/CameraManager.hpp>
@@ -587,16 +588,7 @@ int main(int argc, const char **argv) {
 	
 	const vkcv::VertexLayout smokeLayout { vbSmoke };
 	
-	vkcv::PassHandle renderPass = core.createPass(vkcv::PassConfig(
-		{
-			vkcv::AttachmentDescription(
-				colorFormat,
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-			)
-		},
-		vkcv::Multisampling::None
-	));
+	vkcv::PassHandle renderPass = vkcv::passFormat(core, colorFormat);
 	
 	vkcv::GraphicsPipelineConfig smokePipelineDefinition (
 		smokeShaderProgram,
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 356fd9f11eaafb093f9432dd9536896e01793461..27e0630eb567eb63ffad1e2eb12c89866f35397a 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <vkcv/asset/asset_loader.hpp>
@@ -50,26 +51,12 @@ int main(int argc, const char** argv) {
 	
 	indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
 
-	// an example attachment for passes that output to the window
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-	
-	const vkcv::AttachmentDescription depth_attachment(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	vkcv::PassConfig firstMeshPassDefinition(
-			{ present_color_attachment, depth_attachment },
-			vkcv::Multisampling::None
+	vkcv::PassHandle firstMeshPass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
 	);
 
-	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
-
 	if (!firstMeshPass) {
 		std::cerr << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index bd3b2ac74fdac27abc553987d307ae3100178b07..17b41378ea1650a90b3640258692296bb9d16001 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -1,5 +1,6 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/gui/GUI.hpp>
@@ -47,25 +48,12 @@ int main(int argc, const char** argv) {
 	vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path(
 			argc > 1 ? argv[1] : "assets/Sponza/Sponza.gltf"
 	));
-
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	const vkcv::AttachmentDescription depth_attachment(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	vkcv::PassConfig scenePassDefinition(
-			{ present_color_attachment, depth_attachment },
-			vkcv::Multisampling::None
-	);
 	
-	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
+	vkcv::PassHandle scenePass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
+	);
 
 	if (!scenePass) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index edf8fa8fa0f041854db452e7b335d34f7dbc5cf0..5ad87a5707a654806f96418181383f8696d0ac87 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -28,16 +29,12 @@ int main(int argc, const char** argv) {
 
 	core.setDebugLabel(triangleIndexBuffer.getHandle(), "Triangle Index Buffer");
 	
-	// an example attachment for passes that output to the window
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
+	vkcv::PassHandle trianglePass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined }
 	);
 
-	vkcv::PassConfig trianglePassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
-	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
-
 	if (!trianglePass)
 	{
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 9c92128f46d1f7c2472e2a082bac03219cdd5615..905c333fa71cadc16244e02a327599a1126db39d 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/gui/GUI.hpp>
@@ -43,43 +44,8 @@ int main(int argc, const char** argv) {
 	
 	vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
 	
-	const vkcv::AttachmentDescription color_attachment0(
-			colorFormat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-	
-	const vkcv::AttachmentDescription depth_attachment0(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-	
-	const vkcv::AttachmentDescription color_attachment1(
-			colorFormat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
-	);
-	
-	const vkcv::AttachmentDescription depth_attachment1(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
-	);
-	
-	vkcv::PassConfig linePassDefinition(
-			{ color_attachment0, depth_attachment0 },
-			vkcv::Multisampling::None
-	);
-	
-	vkcv::PassHandle linePass = core.createPass(linePassDefinition);
-	
-	vkcv::PassConfig scenePassDefinition(
-			{ color_attachment1, depth_attachment1 },
-			vkcv::Multisampling::None
-	);
-	
-	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
+	vkcv::PassHandle linePass = vkcv::passFormats(core, { colorFormat, vk::Format::eD32Sfloat });
+	vkcv::PassHandle scenePass = vkcv::passFormats(core, { colorFormat, vk::Format::eD32Sfloat }, false);
 	
 	if ((!scenePass) || (!linePass)) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index f3fa7f8d2712eb5f465c6899983298fa63cfd564..733469fdab16e1a026b61f4b8975720ed57bb01c 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <vkcv/gui/GUI.hpp>
@@ -328,20 +329,12 @@ int main(int argc, const char** argv) {
         return EXIT_FAILURE;
     }
 
-    const vkcv::AttachmentDescription present_color_attachment (
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
+    vkcv::PassHandle passHandle = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
 	);
 	
-	const vkcv::AttachmentDescription depth_attachment (
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	vkcv::PassConfig passDefinition({ present_color_attachment, depth_attachment }, vkcv::Multisampling::None);
-	vkcv::PassHandle passHandle = core.createPass(passDefinition);
 	if (!passHandle) {
 		std::cerr << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 77df9f4e04d2a32487faa1b7f61be80a31be516e..f80c47ffb28c9adfd81ec58abc2b2b10a03fda42 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -161,26 +162,12 @@ int main(int argc, const char** argv) {
 		vkcv::BufferMemoryType::DEVICE_LOCAL
 		);
 	meshletBuffer.fill(meshShaderModelData.meshlets);
-
-	// attachments
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-    const vkcv::AttachmentDescription depth_attachment(
-			vk::Format::eD32Sfloat,
-			vkcv::AttachmentOperation::CLEAR,
-            vkcv::AttachmentOperation::STORE
-    );
-
-	vkcv::PassConfig bunnyPassDefinition(
-			{ present_color_attachment, depth_attachment },
-			vkcv::Multisampling::None
-	);
 	
-	vkcv::PassHandle renderPass = core.createPass(bunnyPassDefinition);
+	vkcv::PassHandle renderPass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
+	);
 
 	if (!renderPass)
 	{
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index a1e40221efe9a4bdd076ed9bef0a30d129c43d87..5ade2185a6e392992096d902c9d91c83309b6db0 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -33,16 +34,7 @@ int main(int argc, const char **argv) {
     particleIndexBuffer.fill(&indices[0], sizeof(indices));
 
     vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
-    // an example attachment for passes that output to the window
-    const vkcv::AttachmentDescription present_color_attachment(
-			colorFormat,
-			vkcv::AttachmentOperation::CLEAR,
-            vkcv::AttachmentOperation::STORE
-	);
-
-
-    vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
-    vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
+    vkcv::PassHandle particlePass = vkcv::passFormat(core, colorFormat);
 
     if (!particlePass)
     {
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index 3b9d8ab4d30ad377242e260bcda6aec0e8abd397..6c34f51a675f890d2fc00a5db2c4193065347a66 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -1,5 +1,6 @@
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 19ecf20d44416cba37e6f37d2d4298fb45602432..d514eb2f9fb138feaefcd9c2c43886cecead71c0 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
 #include <vkcv/Buffer.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
@@ -11,7 +12,6 @@
 #include <cstring>
 #include "safrScene.hpp"
 
-
 void createQuadraticLightCluster(std::vector<safrScene::Light>& lights, int countPerDimension, float dimension, float height, float intensity) {
     float distance = dimension/countPerDimension;
 
@@ -42,16 +42,6 @@ int main(int argc, const char** argv) {
 	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true);
 	vkcv::Window& window = core.getWindow(windowHandle);
 
-	//configuring the compute Shader
-	vkcv::PassConfig computePassDefinition({});
-	vkcv::PassHandle computePass = core.createPass(computePassDefinition);
-
-	if (!computePass)
-	{
-		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
-		return EXIT_FAILURE;
-	}
-
 	std::string shaderPathCompute = "shaders/raytracing.comp";
 
 	//creating the shader programs
@@ -160,19 +150,14 @@ int main(int argc, const char** argv) {
 	auto safrIndexBuffer = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3);
 	uint16_t indices[3] = { 0, 1, 2 };
 	safrIndexBuffer.fill(&indices[0], sizeof(indices));
-
-	// an example attachment for passes that output to the window
-	const vkcv::AttachmentDescription present_color_attachment(
-			core.getSwapchainFormat(window.getSwapchain()),
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
+	
+	vkcv::PassHandle safrPass = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined }
 	);
 
-	vkcv::PassConfig safrPassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
-	vkcv::PassHandle safrPass = core.createPass(safrPassDefinition);
-
-	if (!safrPass)
-	{
+	if (!safrPass) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
 	}
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index f6ed05058f3bae8609aefeffbbc5b16177a433f3..ab02c4a0f8c31f1a432b96830eafd0d74cb04c02 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
 #include <vkcv/Buffer.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <random>
@@ -31,15 +32,7 @@ int main(int argc, const char **argv) {
     particleIndexBuffer.fill(&indices[0], sizeof(indices));
 
     vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
-    // an example attachment for passes that output to the window
-    const vkcv::AttachmentDescription present_color_attachment(
-			colorFormat,
-			vkcv::AttachmentOperation::CLEAR,
-            vkcv::AttachmentOperation::STORE
-	);
-
-    vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
-    vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
+    vkcv::PassHandle particlePass = vkcv::passFormat(core, colorFormat);
 
     //rotation
     float rotationx = 0;
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 990007cb6b28b40c716aaf907ed0accc87312c00..c0f7ed2ad614d0b717a322430b07b776e57971f2 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -1,4 +1,6 @@
 #include "ShadowMapping.hpp"
+
+#include <vkcv/Pass.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
 const vk::Format            shadowMapFormat         = vk::Format::eR16G16B16A16Unorm;
@@ -159,15 +161,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	vkcv::ShaderProgram shadowShader = loadShadowShader();
 
 	// pass
-	const std::vector<vkcv::AttachmentDescription> shadowAttachments = {
-		vkcv::AttachmentDescription(
-				shadowMapDepthFormat,
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-		)
-	};
-	vkcv::PassConfig shadowPassConfig(shadowAttachments, msaa);
-	m_shadowMapPass = corePtr->createPass(shadowPassConfig);
+	m_shadowMapPass = vkcv::passFormat(*corePtr, shadowMapDepthFormat, true, msaa);
 
 	// pipeline
 	vkcv::GraphicsPipelineConfig shadowPipeConfig (
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 63316208057c246f42c712f7d09aea72f0631e8e..f8d7fa4f75ca4d36c9e4bd52058bf9702e0e4663 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -1,4 +1,6 @@
 #include "Voxelization.hpp"
+
+#include <vkcv/Pass.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <glm/gtc/matrix_transform.hpp>
 #include <algorithm>
@@ -136,25 +138,13 @@ Voxelization::Voxelization(
 
 	m_visualisationDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelVisualisationShader.getReflectedDescriptors().at(0));
 	m_visualisationDescriptorSet = m_corePtr->createDescriptorSet(m_visualisationDescriptorSetLayout);
-
-	const vkcv::AttachmentDescription voxelVisualisationColorAttachments (
-			dependencies.colorBufferFormat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	const vkcv::AttachmentDescription voxelVisualisationDepthAttachments (
-			dependencies.depthBufferFormat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	vkcv::PassConfig voxelVisualisationPassDefinition{
-		{ voxelVisualisationColorAttachments, voxelVisualisationDepthAttachments },
-		msaa
-	};
 	
-	m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition);
+	m_visualisationPass = vkcv::passFormats(
+			*m_corePtr,
+			{ dependencies.colorBufferFormat, dependencies.depthBufferFormat },
+			false,
+			msaa
+	);
 
 	vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig (
 		voxelVisualisationShader,
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index e2e1f0ee6115cc7f6e7d792ebf185acf9035ad8c..8f568407b17175e23e2d472591ac12b9d697557f 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -1,5 +1,6 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -239,15 +240,8 @@ int main(int argc, const char** argv) {
 		prepassVertexBindings.push_back(vkcv::createVertexBinding(i, { prepassVertexAttachments[i] }));
 	}
 	const vkcv::VertexLayout prepassVertexLayout { prepassVertexBindings };
-
-	const vkcv::AttachmentDescription prepassAttachment(
-			depthBufferFormat,
-			vkcv::AttachmentOperation::CLEAR,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	vkcv::PassConfig prepassPassDefinition({ prepassAttachment }, msaa);
-	vkcv::PassHandle prepassPass = core.createPass(prepassPassDefinition);
+	
+	vkcv::PassHandle prepassPass = vkcv::passFormat(core, depthBufferFormat, true, msaa);
 
 	// create descriptor sets
 	vkcv::SamplerHandle colorSampler = core.createSampler(
@@ -376,22 +370,14 @@ int main(int argc, const char** argv) {
 	SkySettings skySettings;
 	skySettings.color       = glm::vec3(0.15, 0.65, 1);
 	skySettings.strength    = 5;
-
-	const vkcv::AttachmentDescription skyColorAttachment (
-			colorBufferFormat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
-	);
-
-	const vkcv::AttachmentDescription skyDepthAttachments (
-			depthBufferFormat,
-			vkcv::AttachmentOperation::LOAD,
-			vkcv::AttachmentOperation::STORE
+	
+	vkcv::PassHandle skyPass = vkcv::passFormats(
+			core,
+			{ colorBufferFormat, depthBufferFormat },
+			false,
+			msaa
 	);
 
-	vkcv::PassConfig skyPassConfig({ skyColorAttachment, skyDepthAttachments }, msaa);
-	vkcv::PassHandle skyPass = core.createPass(skyPassConfig);
-
 	vkcv::ShaderProgram skyShader;
 	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/sky.vert"),
 		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 23ab97c5e9038303144632e9d79cf0b94abf0a7d..da02ed38dc2c7c769bd9079d23b08593a0404c1a 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -1,6 +1,7 @@
 
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/gui/GUI.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -454,45 +455,6 @@ int main(int argc, const char **argv) {
 			{ vkcv::ShaderStage::FRAGMENT, "shaders/lines.frag" }
 	}, nullptr);
 	
-	vkcv::PassConfig passConfigGrid {{
-		vkcv::AttachmentDescription(
-				core.getSwapchainFormat(window.getSwapchain()),
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-		),
-		vkcv::AttachmentDescription(
-				vk::Format::eD32Sfloat,
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-		)
-	}, vkcv::Multisampling::None };
-	
-	vkcv::PassConfig passConfigParticles {{
-		vkcv::AttachmentDescription(
-				core.getSwapchainFormat(window.getSwapchain()),
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-		),
-		vkcv::AttachmentDescription(
-				vk::Format::eD32Sfloat,
-				vkcv::AttachmentOperation::CLEAR,
-				vkcv::AttachmentOperation::STORE
-		)
-	}, vkcv::Multisampling::None };
-	
-	vkcv::PassConfig passConfigLines {{
-		vkcv::AttachmentDescription(
-				core.getSwapchainFormat(window.getSwapchain()),
-				vkcv::AttachmentOperation::LOAD,
-				vkcv::AttachmentOperation::STORE
-		),
-		vkcv::AttachmentDescription(
-				vk::Format::eD32Sfloat,
-				vkcv::AttachmentOperation::LOAD,
-				vkcv::AttachmentOperation::STORE
-		)
-	}, vkcv::Multisampling::None };
-	
 	vkcv::DescriptorSetLayoutHandle gfxSetLayoutGrid = core.createDescriptorSetLayout(
 			gfxProgramGrid.getReflectedDescriptors().at(0)
 	);
@@ -519,9 +481,24 @@ int main(int argc, const char **argv) {
 		core.writeDescriptorSet(gfxSetParticles, writes);
 	}
 	
-	vkcv::PassHandle gfxPassGrid = core.createPass(passConfigGrid);
-	vkcv::PassHandle gfxPassParticles = core.createPass(passConfigParticles);
-	vkcv::PassHandle gfxPassLines = core.createPass(passConfigLines);
+	vkcv::PassHandle gfxPassGrid = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
+	);
+	
+	vkcv::PassHandle gfxPassParticles = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat }
+	);
+	
+	vkcv::PassHandle gfxPassLines = vkcv::passSwapchain(
+			core,
+			window.getSwapchain(),
+			{ vk::Format::eUndefined, vk::Format::eD32Sfloat },
+			false
+	);
 	
 	vkcv::VertexLayout vertexLayoutGrid ({
 		vkcv::createVertexBinding(0, gfxProgramGrid.getVertexAttachments())
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 9cbba1973741078c3ee7571351df7c8bf9b63172..2382aff155eae02177992bd6c34a1325b95ebb9b 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -163,6 +163,10 @@ namespace vkcv
         return m_PassManager->createPass(config);
     }
 	
+	const PassConfig &Core::getPassConfiguration(const vkcv::PassHandle &pass) {
+		return m_PassManager->getPassConfig(pass);
+	}
+	
 	BufferHandle Core::createBuffer(BufferType type,
 									const TypeGuard &typeGuard,
 									size_t count,
@@ -479,7 +483,9 @@ namespace vkcv
 		}
 
 		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
-			const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(passConfig.attachments);
+			const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(
+					passConfig.getAttachments()
+			);
 
 			const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data());
 			cmdBuffer.beginRenderPass(beginInfo, {}, {});
@@ -557,7 +563,9 @@ namespace vkcv
 
         auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) {
 
-            const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(passConfig.attachments);
+            const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(
+					passConfig.getAttachments()
+			);
 
             const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(),
                                                     clearValues.data());
@@ -699,7 +707,9 @@ namespace vkcv
 		}
 
 		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
-			const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(passConfig.attachments);
+			const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(
+					passConfig.getAttachments()
+			);
 
 			const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data());
 			cmdBuffer.beginRenderPass(beginInfo, {}, {});
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index 57eedcaca4d59cc2d27c25ae8a212f7a436d5f2d..2a495fa18950f7b48e2b082853d1b31b5a7cf9c9 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -330,7 +330,7 @@ namespace vkcv {
 																					const PassConfig &passConfig) {
 		vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
 				{},
-				msaaToSampleCountFlagBits(passConfig.msaa),
+				msaaToSampleCountFlagBits(passConfig.getMultisampling()),
 				false,
 				0.f,
 				nullptr,
@@ -670,7 +670,7 @@ namespace vkcv {
 
         const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr;
 
-        for (const auto& attachment : passConfig.attachments) {
+        for (const auto& attachment : passConfig.getAttachments()) {
             if ((isDepthFormat(attachment.getFormat())) ||
 				(isStencilFormat(attachment.getFormat()))) {
                 p_depthStencilCreateInfo = &depthStencilCreateInfo;
diff --git a/src/vkcv/Pass.cpp b/src/vkcv/Pass.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..54482cd9d3189fd1e4ed5a15a07163b079105db4
--- /dev/null
+++ b/src/vkcv/Pass.cpp
@@ -0,0 +1,47 @@
+
+#include "vkcv/Pass.hpp"
+
+namespace vkcv {
+	
+	PassHandle passFormats(Core &core,
+						   const std::vector<vk::Format> formats,
+						   bool clear,
+						   Multisampling multisampling) {
+		AttachmentDescriptions attachments;
+		
+		for (const auto format : formats) {
+			attachments.emplace_back(
+					format,
+					clear? AttachmentOperation::CLEAR : AttachmentOperation::LOAD,
+					AttachmentOperation::STORE
+			);
+		}
+		
+		const PassConfig config (attachments, multisampling);
+		return core.createPass(config);
+	}
+	
+	PassHandle passFormat(Core &core,
+						  vk::Format format,
+						  bool clear,
+						  Multisampling multisampling) {
+		return passFormats(core, { format }, clear, multisampling);
+	}
+	
+	PassHandle passSwapchain(Core &core,
+							 const SwapchainHandle &swapchain,
+							 const std::vector<vk::Format> formats,
+							 bool clear,
+							 Multisampling multisampling) {
+		std::vector<vk::Format> swapchainFormats (formats);
+		
+		for (auto& format : swapchainFormats) {
+			if (vk::Format::eUndefined == format) {
+				format = core.getSwapchainFormat(swapchain);
+			}
+		}
+		
+		return passFormats(core, swapchainFormats, clear, multisampling);
+	}
+	
+}
diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp
index bfb93c8783fd12ee03629b8b4ec523482fc81227..54f3f17f080ec01207a162532dc140e9abd92dd3 100644
--- a/src/vkcv/PassConfig.cpp
+++ b/src/vkcv/PassConfig.cpp
@@ -56,4 +56,27 @@ namespace vkcv
 		return m_clear_value;
 	}
 	
+	PassConfig::PassConfig()
+	: m_attachments(),
+	  m_multisampling(Multisampling::None)
+	{}
+	
+	PassConfig::PassConfig(const AttachmentDescriptions &attachments,
+						   Multisampling multisampling)
+	: m_attachments(attachments),
+	  m_multisampling(multisampling)
+	{}
+	
+	const AttachmentDescriptions &PassConfig::getAttachments() const {
+		return m_attachments;
+	}
+	
+	void PassConfig::setMultisampling(Multisampling multisampling) {
+		m_multisampling = multisampling;
+	}
+	
+	Multisampling PassConfig::getMultisampling() const {
+		return m_multisampling;
+	}
+	
 }
diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp
index 71fa8006285f34661c5be419b7db92ca4c6b2db0..3677fc8319c5a378aac6ea5dcf3d3053887651d1 100644
--- a/src/vkcv/PassManager.cpp
+++ b/src/vkcv/PassManager.cpp
@@ -74,13 +74,15 @@ namespace vkcv
 				}
 			)
 		);
+		
+		const auto& attachments = config.getAttachments();
 
-        for (uint32_t i = 0; i < config.attachments.size(); i++) {
-            vk::Format format = config.attachments[i].getFormat();
+        for (uint32_t i = 0; i < attachments.size(); i++) {
+            vk::Format format = attachments[i].getFormat();
             vk::ImageLayout layout;
 			
-			bool depthFormat = isDepthFormat(config.attachments[i].getFormat());
-			bool stencilFormat = isStencilFormat(config.attachments[i].getFormat());
+			bool depthFormat = isDepthFormat(attachments[i].getFormat());
+			bool stencilFormat = isStencilFormat(attachments[i].getFormat());
 			
             if ((separateDepthStencil) && (depthFormat) && (!stencilFormat)) {
 				layout = vk::ImageLayout::eDepthAttachmentOptimal;
@@ -105,9 +107,9 @@ namespace vkcv
             vk::AttachmentDescription attachmentDesc (
 					{},
 					format,
-					msaaToSampleCountFlagBits(config.msaa),
-					getVKLoadOpFromAttachOp(config.attachments[i].getLoadOperation()),
-					getVkStoreOpFromAttachOp(config.attachments[i].getStoreOperation()),
+					msaaToSampleCountFlagBits(config.getMultisampling()),
+					getVKLoadOpFromAttachOp(attachments[i].getLoadOperation()),
+					getVkStoreOpFromAttachOp(attachments[i].getStoreOperation()),
 					vk::AttachmentLoadOp::eDontCare,
 					vk::AttachmentStoreOp::eDontCare,
 					layout,