diff --git a/.gitmodules b/.gitmodules
index e270bddb0a91069af1eff869560e8b817f7cc844..efa79ed703e1cc83f962cebfd4299621810cf82e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -22,9 +22,6 @@
 [submodule "modules/gui/lib/imgui"]
 	path = modules/gui/lib/imgui
 	url = https://github.com/ocornut/imgui.git
-[submodule "lib/VulkanMemoryAllocator-Hpp"]
-	path = lib/VulkanMemoryAllocator-Hpp
-	url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git
 [submodule "modules/upscaling/lib/FidelityFX-FSR"]
 	path = modules/upscaling/lib/FidelityFX-FSR
 	url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git
@@ -37,3 +34,6 @@
 [submodule "modules/upscaling/lib/NVIDIAImageScaling"]
 	path = modules/upscaling/lib/NVIDIAImageScaling
 	url = https://github.com/NVIDIAGameWorks/NVIDIAImageScaling.git
+[submodule "lib/VulkanMemoryAllocator-Hpp"]
+	path = lib/VulkanMemoryAllocator-Hpp
+	url = https://github.com/YaaZ/VulkanMemoryAllocator-Hpp.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c3f6df3508592fc5003ee490951fdf8368b48ac..d47706415b6274a135a4c85aa1010fde2e959105 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,8 @@ message(STATUS "Linker: [ " ${CMAKE_LINKER} " ]")
 
 if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0"))
 	message(FATAL_ERROR "Upgrade your compiler! GCC 9.0+ is required!")
+elseif(MINGW)
+	message(WARNING "MinGW is impressively unstable! So beware it may not compile or crash during runtime!")
 endif()
 
 # setting up different paths
diff --git a/Doxyfile b/Doxyfile
index 249fed47d3c09ceca1e570b3be4f1a20cb1b13c3..05d73d3cd7cf3ed9322481cfbee1597a488305b6 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -2349,7 +2349,7 @@ HIDE_UNDOC_RELATIONS   = YES
 # set to NO
 # The default value is: NO.
 
-HAVE_DOT               = YES
+HAVE_DOT               = NO
 
 # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
 # to run in parallel. When set to 0 doxygen will base this on the number of
@@ -2491,7 +2491,7 @@ INCLUDED_BY_GRAPH      = YES
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-CALL_GRAPH             = YES
+CALL_GRAPH             = NO
 
 # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
 # dependency graph for every global function or class method.
@@ -2503,7 +2503,7 @@ CALL_GRAPH             = YES
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-CALLER_GRAPH           = YES
+CALLER_GRAPH           = NO
 
 # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
 # hierarchy of all classes instead of a textual one.
diff --git a/README.md b/README.md
index 62efc4df4a929963f8581c1c2cc66796f4c6a80d..fa0d833ea8ba66c6851296a4e12b5d06d7ab0406 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ The following modules will be provided in this repository and they will automati
  - [Asset-Loader](modules/asset_loader/README.md)
  - [Camera](modules/asset_loader/README.md)
  - [GUI](modules/gui/README.md)
+ - [Effects](modules/effects/README.md)
  - [Material](modules/material/README.md)
  - [Meshlet](modules/meshlet/README.md)
  - [Scene](modules/scene/README.md)
diff --git a/config/Libraries.cmake b/config/Libraries.cmake
index ca2af95ef5533ffaf36cbd439f58cf9bd8e28854..fb4677e6e13698dcae87657290463253f40d1c1e 100644
--- a/config/Libraries.cmake
+++ b/config/Libraries.cmake
@@ -3,7 +3,8 @@ set(vkcv_config_lib ${vkcv_config}/lib)
 set(vkcv_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_lib})
 
 if(NOT WIN32)
-	if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+	if (((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.1.0")) OR
+		((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")))
 		set(vkcv_libraries stdc++fs)
 	endif()
 	
diff --git a/config/Sources.cmake b/config/Sources.cmake
index 606dc4c97d62ed284d5967707e07237ebd2f7580..ad7b1bbf84ea515af449b81c505de24d8cf0ecf9 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -17,7 +17,6 @@ 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
@@ -42,6 +41,9 @@ set(vkcv_sources
 		${vkcv_source}/vkcv/ImageManager.cpp
 		
 		${vkcv_include}/vkcv/Logger.hpp
+		
+		${vkcv_include}/vkcv/Surface.hpp
+		${vkcv_source}/vkcv/Surface.cpp
 
 		${vkcv_include}/vkcv/Swapchain.hpp
 		${vkcv_source}/vkcv/Swapchain.cpp
@@ -83,6 +85,9 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/DescriptorConfig.hpp
 		${vkcv_source}/vkcv/DescriptorConfig.cpp
 		
+		${vkcv_include}/vkcv/DescriptorWrites.hpp
+		${vkcv_source}/vkcv/DescriptorWrites.cpp
+		
 		${vkcv_source}/vkcv/SamplerManager.hpp
 		${vkcv_source}/vkcv/SamplerManager.cpp
 
@@ -97,7 +102,7 @@ set(vkcv_sources
         ${vkcv_include}/vkcv/DrawcallRecording.hpp
         ${vkcv_source}/vkcv/DrawcallRecording.cpp
         
-        ${vkcv_include}/vkcv/CommandStreamManager.hpp
+        ${vkcv_source}/vkcv/CommandStreamManager.hpp
         ${vkcv_source}/vkcv/CommandStreamManager.cpp
         
         ${vkcv_include}/vkcv/CommandRecordingFunctionTypes.hpp
diff --git a/config/lib/SPIRV_Cross.cmake b/config/lib/SPIRV_Cross.cmake
index ce4b2e437467436daa7e1bc04975be4fa9609fef..c6304606a14a30f8de7dba1fe2e479ed63743e1e 100644
--- a/config/lib/SPIRV_Cross.cmake
+++ b/config/lib/SPIRV_Cross.cmake
@@ -1,3 +1,4 @@
+
 find_package(spirv_cross_c_shared QUIET)
 
 if (spirv-cross_FOUND)
@@ -31,4 +32,4 @@ else()
 
         message(${vkcv_config_msg} " SPIRV Cross    - " ${SPIRV_CROSS_VERSION})
     endif ()
-endif ()
\ No newline at end of file
+endif ()
diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index 992093061e254ce7c71d382a60f07ce08ca71cfd..52056d9f0441f807aa802ef3d29b31e2129b605c 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -1,16 +1,22 @@
 #pragma once
 /**
- * @authors Lars Hoerttrich, Tobias Frisch
+ * @authors Tobias Frisch, Lars Hoerttrich, Alexander Gauggel
  * @file vkcv/Buffer.hpp
- * @brief template buffer class, template for type security, implemented here because template classes can't be written in .cpp
+ * @brief Template buffer class for type security with buffers.
  */
-#include "Handles.hpp"
-#include "BufferManager.hpp"
 
 #include <vector>
 
+#include "Handles.hpp"
+#include "BufferManager.hpp"
+
 namespace vkcv {
 
+	/**
+	 * @brief Template class for buffer handling and filling data.
+	 *
+	 * @tparam T Buffer content type
+	 */
 	template<typename T>
 	class Buffer {
 		friend class Core;
@@ -18,44 +24,96 @@ namespace vkcv {
 		// explicit destruction of default constructor
 		Buffer() = delete;
 		
+		/**
+		 * @brief Returns the buffers handle.
+		 *
+		 * @return The #BufferHandle to be used with the #Core
+		 */
 		[[nodiscard]]
 		const BufferHandle& getHandle() const {
 			return m_handle;
 		}
 		
+		/**
+		 * @brief Returns the type of the buffer.
+		 *
+		 * @return The #BufferType of the #Buffer
+		 */
 		[[nodiscard]]
 		BufferType getType() const {
 			return m_type;
 		};
 		
+		/**
+		 * @brief Returns the count of elements in the buffer.
+		 *
+		 * @return The number of objects of type T the #Buffer holds
+		 */
 		[[nodiscard]]
 		size_t getCount() const {
 			return m_count;
 		}
 		
+		/**
+		 * @brief Returns the size of the buffer in bytes.
+		 *
+		 * @return The size of the #Buffer in bytes
+		 */
 		[[nodiscard]]
 		size_t getSize() const {
 			return m_count * sizeof(T);
 		}
 
+		/**
+		 * @brief Returns the vulkan buffer handle of the buffer.
+		 *
+		 * @return The vulkan handle of the #Buffer to be used for manual vulkan commands
+		 */
         [[nodiscard]]
 		vk::Buffer getVulkanHandle() const {
             return m_manager->getBuffer(m_handle);
         }
-		
-		void fill(const T* data, size_t count = 0, size_t offset = 0) {
+
+		/**
+		 * @brief Fills the #Buffer with data of type T.
+		 * 
+		 * @param[in] data Pointer to the array of object type T
+		 * @param[in] count The number of objects to copy from the data array
+		 * @param[in] offset The offset into the #Buffer where the data is copied into
+		 */
+		void fill(const T* data,
+				  size_t count = 0,
+				  size_t offset = 0) {
 			 m_manager->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
 		}
 		
-		void fill(const std::vector<T>& vector, size_t offset = 0) {
+		/**
+		 * @brief Fills the #Buffer with data from a vector of type T.
+		 * 
+		 * @param vector Vector of type T to be copied into the #Buffer
+		 * @param offset The offset into the #Buffer where the data is copied into
+		 */
+		void fill(const std::vector<T>& vector,
+				  size_t offset = 0) {
 			fill( static_cast<const T*>(vector.data()), static_cast<size_t>(vector.size()), offset);
 		}
 		
+		/**
+		 * @brief Maps memory to the #Buffer and returns it.
+		 *
+		 * @param[in] offset Offset of mapping in objects of type T
+		 * @param[in] count Count of objects of type T that are mapped
+		 * @return Pointer to mapped memory as type T
+		 */
 		[[nodiscard]]
-		T* map(size_t offset = 0, size_t count = 0) {
+		T* map(size_t offset = 0,
+			   size_t count = 0) {
 			return reinterpret_cast<T*>(m_manager->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T)));
 		}
 
+		/**
+		 * @brief Unmaps the #Buffer, invalidates the pointer obtained by map().
+		 */
 		void unmap() {
 			m_manager->unmapBuffer(m_handle);
 		}
@@ -67,7 +125,20 @@ namespace vkcv {
 		const size_t m_count;
 		const BufferMemoryType m_memoryType;
 		
-		Buffer(BufferManager* manager, BufferHandle handle, BufferType type, size_t count, BufferMemoryType memoryType) :
+		/**
+		 * @brief Constructor of the buffer object.
+		 *
+		 * @param[in,out] manager Buffer manager
+		 * @param[in] handle Buffer handle
+		 * @param[in] type Type of buffer
+		 * @param[in] count Count of elements
+		 * @param[in] memoryType Type of memory
+		 */
+		Buffer(BufferManager* manager,
+			   BufferHandle handle,
+			   BufferType type,
+			   size_t count,
+			   BufferMemoryType memoryType) :
 				m_manager(manager),
 				m_handle(handle),
 				m_type(type),
@@ -75,9 +146,36 @@ namespace vkcv {
 				m_memoryType(memoryType)
 		{}
 		
+		/**
+		 * @brief Creates a buffer object of type T with
+		 * a selected type, count of elements, memory type
+		 * and support of indirect usage.
+		 *
+		 * @param[in,out] manager Buffer manager
+		 * @param[in] type Buffer type
+		 * @param[in] count Count of elements
+		 * @param[in] memoryType Type of memory
+		 * @param[in] supportIndirect Support indirect usage
+		 * @return New buffer object
+		 */
 		[[nodiscard]]
-		static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType memoryType, bool supportIndirect) {
-			return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType, supportIndirect), type, count, memoryType);
+		static Buffer<T> create(BufferManager* manager,
+								BufferType type,
+								size_t count,
+								BufferMemoryType memoryType,
+								bool supportIndirect) {
+			return Buffer<T>(
+				manager,
+				manager->createBuffer(
+					type,
+					count * sizeof(T),
+					memoryType,
+					supportIndirect
+				),
+				type,
+				count,
+				memoryType
+			);
 		}
 		
 	};
diff --git a/include/vkcv/BufferManager.hpp b/include/vkcv/BufferManager.hpp
index e4e1e4019f982908ad592466f342b84d3ef52d9a..3ac685b06068c4581202f5371f8dafab5445ecf1 100644
--- a/include/vkcv/BufferManager.hpp
+++ b/include/vkcv/BufferManager.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Tobias Frisch, Alexander Gauggel, Artur Wasmut, Lars Hoerttrich, Sebastian Gaida
+ * @file vkcv/BufferManager.hpp
+ * @brief Manager to handle buffer operations.
+ */
 
 #include <vector>
 #include <vulkan/vulkan.hpp>
@@ -8,6 +13,10 @@
 
 namespace vkcv
 {
+	
+	/**
+	 * @brief Enum class to specify types of buffers.
+	 */
 	enum class BufferType {
 		INDEX,
 		VERTEX,
@@ -17,6 +26,9 @@ namespace vkcv
 		INDIRECT
 	};
 	
+	/**
+	 * @brief Enum class to specify types of buffer memory.
+	 */
 	enum class BufferMemoryType {
 		DEVICE_LOCAL,
 		HOST_VISIBLE
@@ -24,6 +36,10 @@ namespace vkcv
 	
 	class Core;
 	
+	/**
+	 * @brief Class to manage the creation, destruction, allocation
+	 * and filling of buffers.
+	 */
 	class BufferManager
 	{
 		friend class Core;
@@ -63,79 +79,94 @@ namespace vkcv
 		BufferManager& operator=(const BufferManager& other) = delete;
 		
 		/**
-		 * Creates and allocates a new buffer and returns its
+		 * @brief Creates and allocates a new buffer and returns its
 		 * unique buffer handle.
 		 *
-		 * @param type Type of buffer
-		 * @param size Size of buffer in bytes
-		 * @param memoryType Type of buffers memory
+		 * @param[in] type Type of buffer
+		 * @param[in] size Size of buffer in bytes
+		 * @param[in] memoryType Type of buffers memory
+		 * @param[in] supportIndirect Support of indirect usage
 		 * @return New buffer handle
 		 */
-		BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType, bool supportIndirect);
+		BufferHandle createBuffer(BufferType type,
+								  size_t size,
+								  BufferMemoryType memoryType,
+								  bool supportIndirect);
 		
 		/**
-		 * Returns the Vulkan buffer handle of a buffer
+		 * @brief Returns the Vulkan buffer handle of a buffer
 		 * represented by a given buffer handle.
 		 *
-		 * @param handle Buffer handle
+		 * @param[in] handle Buffer handle
 		 * @return Vulkan buffer handle
 		 */
 		[[nodiscard]]
 		vk::Buffer getBuffer(const BufferHandle& handle) const;
 		
 		/**
-		 * Returns the size of a buffer represented
+		 * @brief Returns the size of a buffer represented
 		 * by a given buffer handle.
 		 *
-		 * @param handle Buffer handle
+		 * @param[in] handle Buffer handle
 		 * @return Size of the buffer
 		 */
 		[[nodiscard]]
 		size_t getBufferSize(const BufferHandle& handle) const;
 		
 		/**
-		 * Returns the Vulkan device memory handle of a buffer
+		 * @brief Returns the Vulkan device memory handle of a buffer
 		 * represented by a given buffer handle id.
 		 *
-		 * @param handle Buffer handle
+		 * @param[in] handle Buffer handle
 		 * @return Vulkan device memory handle
 		 */
 		[[nodiscard]]
 		vk::DeviceMemory getDeviceMemory(const BufferHandle& handle) const;
 		
 		/**
-		 * Fills a buffer represented by a given buffer
+		 * @brief Fills a buffer represented by a given buffer
 		 * handle with custom data.
 		 *
-		 * @param handle Buffer handle
-		 * @param data Pointer to data
-		 * @param size Size of data in bytes
-		 * @param offset Offset to fill in data in bytes
+		 * @param[in] handle Buffer handle
+		 * @param[in] data Pointer to data
+		 * @param[in] size Size of data in bytes
+		 * @param[in] offset Offset to fill in data in bytes
 		 */
-		void fillBuffer(const BufferHandle& handle, const void* data, size_t size, size_t offset);
+		void fillBuffer(const BufferHandle& handle,
+						const void* data,
+						size_t size,
+						size_t offset);
 		
 		/**
-		 * Maps memory to a buffer represented by a given
+		 * @brief Maps memory to a buffer represented by a given
 		 * buffer handle and returns it.
 		 *
-		 * @param handle Buffer handle
-		 * @param offset Offset of mapping in bytes
-		 * @param size Size of mapping in bytes
+		 * @param[in] handle Buffer handle
+		 * @param[in] offset Offset of mapping in bytes
+		 * @param[in] size Size of mapping in bytes
 		 * @return Pointer to mapped memory
 		 */
-		void* mapBuffer(const BufferHandle& handle, size_t offset, size_t size);
+		void* mapBuffer(const BufferHandle& handle,
+						size_t offset,
+						size_t size);
 		
 		/**
-		 * Unmaps memory from a buffer represented by a given
+		 * @brief Unmaps memory from a buffer represented by a given
 		 * buffer handle.
 		 *
-		 * @param handle Buffer handle
+		 * @param[in] handle Buffer handle
 		 */
 		void unmapBuffer(const BufferHandle& handle);
 		
-		void recordBufferMemoryBarrier(
-			const BufferHandle& handle,
-			vk::CommandBuffer cmdBuffer);
+		/**
+		 * @brief Records a memory barrier for a buffer,
+		 * synchronizing subsequent accesses to buffer data
+		 *
+		 * @param[in] handle BufferHandle of the buffer
+		 * @param[in] cmdBuffer Vulkan command buffer to record the barrier into
+		*/
+		void recordBufferMemoryBarrier(const BufferHandle& handle,
+									   vk::CommandBuffer cmdBuffer);
 	};
 	
 }
diff --git a/include/vkcv/CommandRecordingFunctionTypes.hpp b/include/vkcv/CommandRecordingFunctionTypes.hpp
index c236fb2c717afd2a3bafc4b3a22708cdac942ffe..d8cda4216e6fbd5686240f52fa0838650ef409df 100644
--- a/include/vkcv/CommandRecordingFunctionTypes.hpp
+++ b/include/vkcv/CommandRecordingFunctionTypes.hpp
@@ -1,8 +1,24 @@
 #pragma once
-#include "vkcv/Event.hpp"
+/**
+ * @authors Alexander Gauggel, Tobias Frisch
+ * @file vkcv/CommandRecordingFunctionTypes.hpp
+ * @brief Abstract function types to handle command recording.
+ */
+
 #include <vulkan/vulkan.hpp>
 
+#include "Event.hpp"
+
 namespace vkcv {
+	
+	/**
+	 * @brief Function to be called for recording a command buffer.
+	 */
 	typedef typename event_function<const vk::CommandBuffer&>::type RecordCommandFunction;
+	
+	/**
+	 * @brief Function to be called after finishing a given process.
+	 */
 	typedef typename event_function<>::type FinishCommandFunction;
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/CommandResources.hpp b/include/vkcv/CommandResources.hpp
index ffdd6d0315549c7522623f535856bbaffc8e5c6e..8ec868c0a5a353cba2efb2313d4168450f30844b 100644
--- a/include/vkcv/CommandResources.hpp
+++ b/include/vkcv/CommandResources.hpp
@@ -1,25 +1,113 @@
 #pragma once
+/**
+ * @authors Alexander Gauggel, Tobias Frisch
+ * @file vkcv/CommandResources.hpp
+ * @brief Support functions to deal with command resources.
+ */
+
 #include <vulkan/vulkan.hpp>
 #include <unordered_set>
+
 #include "QueueManager.hpp"
 
 namespace vkcv {
+	
+	/**
+	 * @brief Structure to store command pools for given queue families
+	 * of a device.
+	 */
 	struct CommandResources {
 		std::vector<vk::CommandPool> cmdPoolPerQueueFamily;
 	};
 
-	std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager& queueManager);
-	CommandResources		createCommandResources(const vk::Device& device, const std::unordered_set<int> &familyIndexSet);
-	void					destroyCommandResources(const vk::Device& device, const CommandResources& resources);
-	vk::CommandBuffer		allocateCommandBuffer(const vk::Device& device, const vk::CommandPool cmdPool);
-	vk::CommandPool			chooseCmdPool(const Queue &queue, const CommandResources &cmdResources);
-	Queue					getQueueForSubmit(const QueueType type, const QueueManager &queueManager);
-	void					beginCommandBuffer(const vk::CommandBuffer cmdBuffer, const vk::CommandBufferUsageFlags flags);
+	/**
+	 * @brief Generates a set of the family indices for all different kinds of
+	 * queues a given queue manager provides.
+	 *
+	 * @param[in] queueManager Queue manager
+	 * @return Set of queue family indices
+	 */
+	std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager &queueManager);
+	
+	/**
+	 * @brief Creates and returns a new command resources instance containing
+	 * a vector of newly allocated command pools for each different queue family
+	 * index in a given set.
+	 *
+	 * @param[in,out] device Vulkan device
+	 * @param[in] familyIndexSet Set of queue family indices
+	 * @return New command resources
+	 */
+	CommandResources createCommandResources(const vk::Device &device,
+											const std::unordered_set<int> &familyIndexSet);
+	
+	/**
+	 * @brief Destroys a command resources instance and deallocates its command
+	 * pools. The command resources will be invalid to use afterwards.
+	 *
+	 * @param[in,out] device Vulkan device
+	 * @param[in,out] resources Command resources
+	 */
+	void destroyCommandResources(const vk::Device &device,
+								 const CommandResources &resources);
+	
+	/**
+	 * @brief Allocates and returns a new primary command buffer of a given
+	 * command pool.
+	 *
+	 * @param[in,out] device Vulkan device
+	 * @param[in,out] cmdPool Vulkan command pool
+	 * @return New vulkan command buffer
+	 */
+	vk::CommandBuffer allocateCommandBuffer(const vk::Device &device,
+											const vk::CommandPool &cmdPool);
+	
+	/**
+	 * @brief Returns the matching command pool of given command resources for
+	 * a specific queue.
+	 *
+	 * @param[in] queue Queue
+	 * @param[in] cmdResources Command resources
+	 * @return Command pool for a given queue
+	 */
+	vk::CommandPool chooseCmdPool(const Queue &queue,
+								  const CommandResources &cmdResources);
+	
+	/**
+	 * @brief Returns a queue of a given type from a queue manager.
+	 *
+	 * @param[in] type Type of queue
+	 * @param[in] queueManager Queue manager
+	 * @return Queue of a given type
+	 */
+	Queue getQueueForSubmit(QueueType type,
+							const QueueManager &queueManager);
+	
+	/**
+	 * @brief Begins the usage of a command buffer with given command buffer
+	 * usage flags.
+	 *
+	 * @param[in] cmdBuffer Vulkan command buffer
+	 * @param[in] flags Command buffer usage flags
+	 */
+	void beginCommandBuffer(const vk::CommandBuffer &cmdBuffer,
+							vk::CommandBufferUsageFlags flags);
 
-	void submitCommandBufferToQueue(
-		const vk::Queue						queue,
-		const vk::CommandBuffer				cmdBuffer,
-		const vk::Fence						fence,
-		const std::vector<vk::Semaphore>&	waitSemaphores,
-		const std::vector<vk::Semaphore>&	signalSemaphores);
+	/**
+	 * @brief Submits a command buffer into a queue with given fence and
+	 * semaphores to wait for or to signal after processing the command
+	 * buffer.
+	 *
+	 * @param[in,out] queue Vulkan queue
+	 * @param[in] cmdBuffer Vulkan command buffer
+	 * @param[in] fence Vulkan fence to wait for
+	 * @param[in] waitSemaphores Vector of semaphores to wait for
+	 * @param[in] signalSemaphores Vector of semaphores to signal
+	 */
+	void submitCommandBufferToQueue(vk::Queue queue,
+									const vk::CommandBuffer &cmdBuffer,
+									const vk::Fence &fence,
+									const std::vector<vk::Semaphore>& waitSemaphores,
+									const std::vector<vk::Semaphore>& signalSemaphores);
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/CommandStreamManager.hpp b/include/vkcv/CommandStreamManager.hpp
deleted file mode 100644
index 4af2127ccf6271f1076e3dde05304b8f9c556139..0000000000000000000000000000000000000000
--- a/include/vkcv/CommandStreamManager.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-#include <vulkan/vulkan.hpp>
-#include <vector>
-#include "vkcv/Event.hpp"
-#include "vkcv/Handles.hpp"
-#include "vkcv/CommandRecordingFunctionTypes.hpp"
-
-namespace vkcv {
-	
-	class Core;
-
-	class CommandStreamManager
-	{
-		friend class Core;
-	private:
-		struct CommandStream {
-			inline CommandStream(vk::CommandBuffer cmdBuffer, vk::Queue queue, vk::CommandPool cmdPool) 
-				: cmdBuffer(cmdBuffer), cmdPool(cmdPool), queue(queue) {};
-			vk::CommandBuffer                   cmdBuffer;
-			vk::CommandPool                     cmdPool;
-			vk::Queue                           queue;
-			std::vector<FinishCommandFunction>  callbacks;
-		};
-
-		Core* m_core;
-		std::vector<CommandStream> m_commandStreams;
-
-		CommandStreamManager() noexcept;
-
-		void init(Core* core);
-
-	public:
-		~CommandStreamManager() noexcept;
-
-		CommandStreamManager(CommandStreamManager&& other) = delete;
-		CommandStreamManager(const CommandStreamManager& other) = delete;
-
-		CommandStreamManager& operator=(CommandStreamManager&& other) = delete;
-		CommandStreamManager& operator=(const CommandStreamManager& other) = delete;
-
-		CommandStreamHandle createCommandStream(
-			const vk::Queue queue,
-			vk::CommandPool cmdPool);
-
-		void recordCommandsToStream(const CommandStreamHandle handle, const RecordCommandFunction record);
-		void addFinishCallbackToStream(const CommandStreamHandle handle, const FinishCommandFunction finish);
-		void submitCommandStreamSynchronous(
-			const CommandStreamHandle   handle,
-			std::vector<vk::Semaphore>  &waitSemaphores,
-			std::vector<vk::Semaphore>  &signalSemaphores);
-
-		vk::CommandBuffer getStreamCommandBuffer(const CommandStreamHandle handle);
-	};
-
-}
\ No newline at end of file
diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp
index 7695f05349e75dadd166340187ca2770f3dc62cc..ab458aa53704ccc1d5dbe2f1024d826b0b337f78 100644
--- a/include/vkcv/ComputePipelineConfig.hpp
+++ b/include/vkcv/ComputePipelineConfig.hpp
@@ -1,8 +1,8 @@
 #pragma once
 /**
  * @authors Mark Mints, Tobias Frisch
- * @file src/vkcv/ComputePipelineConfig.hpp
- * @brief Compute Pipeline Config Struct to hand over required information to Pipeline Creation.
+ * @file vkcv/ComputePipelineConfig.hpp
+ * @brief Compute pipeline config struct to hand over required information to pipeline creation.
  */
 
 #include <vector>
@@ -10,10 +10,14 @@
 #include "Handles.hpp"
 #include "ShaderProgram.hpp"
 
-namespace vkcv
-{
+namespace vkcv {
+	
+	/**
+	 * @brief Structure to configure a compute pipeline before its creation.
+	 */
     struct ComputePipelineConfig {
         ShaderProgram&                          m_ShaderProgram;
         std::vector<DescriptorSetLayoutHandle>	m_DescriptorSetLayouts;
     };
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp
index 1160857cb2cdbbb0815390ff1f8405dda0f83796..d91855a54c83f17b8251aad7c6fe2cb2591f9add 100644
--- a/include/vkcv/Context.hpp
+++ b/include/vkcv/Context.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Tobias Frisch, Artur Wasmut, Sebastian Gaida, Alexander Gauggel
+ * @file vkcv/Context.hpp
+ * @brief Class to handle the instance, device, allocator and features of the current context.
+ */
 
 #include <vulkan/vulkan.hpp>
 #include <vk_mem_alloc.hpp>
@@ -9,6 +14,15 @@
 
 namespace vkcv
 {
+	
+	/**
+	 * @brief Class to manage core resources for vulkan callbacks.
+	 *
+	 * The class to manage the vulkan resources as an instance,
+	 * a device, a physical device and a memory allocator. Additionally
+	 * instances of this class will hold the feature manager and the
+	 * queue manager.
+	 */
     class Context
     {
         friend class Core;
@@ -24,24 +38,66 @@ namespace vkcv
         Context & operator=(const Context &other) = delete; // copy assignment
         Context & operator=(Context &&other) noexcept; // move assignment
 
+		/**
+		 * @brief Returns the vulkan instance of the context.
+		 *
+		 * @return Vulkan instance
+		 */
         [[nodiscard]]
         const vk::Instance &getInstance() const;
         
+		/**
+		 * @brief Returns the vulkan physical device of the context.
+		 *
+		 * @return Vulkan physical device
+		 */
         [[nodiscard]]
         const vk::PhysicalDevice &getPhysicalDevice() const;
         
+		/**
+		 * @brief Returns the vulkan device of the context.
+		 *
+		 * @return Vulkan device
+		 */
         [[nodiscard]]
         const vk::Device &getDevice() const;
         
+		/**
+		 * @brief Returns the feature manager of the context.
+		 *
+		 * @return Feature manager
+		 */
         [[nodiscard]]
         const FeatureManager& getFeatureManager() const;
         
+		/**
+		 * @brief Returns the queue manager of the context.
+		 *
+		 * @return Queue manager
+		 */
         [[nodiscard]]
         const QueueManager& getQueueManager() const;
 	
+		/**
+		 * @brief Returns the VMA allocator of the context.
+		 *
+		 * @return VMA allocator
+		 */
         [[nodiscard]]
 		const vma::Allocator& getAllocator() const;
-        
+  
+		/**
+		 * @brief Creates a context for a given application with
+		 * a specific name, version, queue requirements, features and
+		 * required instance extensions.
+		 *
+		 * @param applicationName Application name
+		 * @param applicationVersion  Application version
+		 * @param queueFlags Queue flags
+		 * @param features Features
+		 * @param instanceExtensions Instance extensions
+		 * @return New context
+		 */
         static Context create(const char *applicationName,
 							  uint32_t applicationVersion,
 							  const std::vector<vk::QueueFlagBits>& queueFlags,
@@ -50,14 +106,19 @@ namespace vkcv
 
     private:
         /**
-         * Constructor of #Context requires an @p instance, a @p physicalDevice and a @p device.
+         * @brief Constructor of #Context requires an @p instance,
+         * a @p physicalDevice and a @p device.
          *
          * @param instance Vulkan-Instance
          * @param physicalDevice Vulkan-PhysicalDevice
          * @param device Vulkan-Device
          */
-        Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device,
-				FeatureManager&& featureManager, QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
+        Context(vk::Instance instance,
+				vk::PhysicalDevice physicalDevice,
+				vk::Device device,
+				FeatureManager &&featureManager,
+				QueueManager &&queueManager,
+				vma::Allocator &&allocator) noexcept;
         
         vk::Instance        m_Instance;
         vk::PhysicalDevice  m_PhysicalDevice;
@@ -67,4 +128,5 @@ namespace vkcv
 		vma::Allocator 		m_Allocator;
 		
     };
+	
 }
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index cac5bdf5d6e4d1cb182d8b9036695378165a5e65..6505599489f405d135d33ce1c4aeeba295e2176a 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -1,7 +1,9 @@
 #pragma once
 /**
- * @file src/vkcv/Core.hpp
- * @brief Handling of global states regarding dependencies
+ * @authors Alexander Gauggel, Tobias Frisch, Sebastian Gaida, Artur Wasmut, Lars Hoerttrich,
+ *          Mara Vogt, Mark Mints, Simeon Hermann, Alex Laptop, Katharina Krämer, Vanessa Karolek
+ * @file vkcv/Core.hpp
+ * @brief Handling of global states regarding dependencies.
  */
 
 #include <memory>
@@ -25,8 +27,6 @@
 #include "Event.hpp"
 #include "DrawcallRecording.hpp"
 #include "CommandRecordingFunctionTypes.hpp"
-#include "../../src/vkcv/WindowManager.hpp"
-#include "../../src/vkcv/SwapchainManager.hpp"
 
 #define VKCV_FRAMEWORK_NAME "VkCV"
 #define VKCV_FRAMEWORK_VERSION (VK_MAKE_VERSION(0, 1, 0))
@@ -46,12 +46,21 @@ namespace vkcv
 	class WindowManager;
 	class SwapchainManager;
 
+	/**
+	 * @brief Structure to store details about a queue submission.
+	 */
 	struct SubmitInfo {
 		QueueType queueType;
 		std::vector<vk::Semaphore> waitSemaphores;
 		std::vector<vk::Semaphore> signalSemaphores;
 	};
 
+	/**
+	 * @brief Class to handle the core functionality of the framework.
+	 *
+	 * The class handles the core functionality of the framework with most
+	 * calls addressing resource management via more simplified abstraction.
+	 */
     class Core final
     {
     private:
@@ -85,8 +94,8 @@ namespace vkcv
 		uint32_t            m_currentSwapchainImageIndex;
 
 		/**
-		 * sets up swapchain images
-		 * @param swapchainHandles of swapchain
+		 * Sets up swapchain images
+		 * @param handle Handle of swapchain
 		 */
 		void setSwapchainImages(SwapchainHandle handle);
 
@@ -113,7 +122,7 @@ namespace vkcv
         /**
          * Copy assignment operator of #Core is deleted!
          *
-         * @param other Other instance of #Context
+         * @param other Other instance of Context
          * @return Reference to itself
          */
         Core & operator=(const Core &other) = delete;
@@ -121,29 +130,34 @@ namespace vkcv
         /**
          * Move assignment operator of #Core uses default behavior!
          *
-         * @param other Other instance of #Context
+         * @param other Other instance of Context
          * @return Reference to itself
          */
         Core & operator=(Core &&other) = delete;
 
+		/**
+		 * Returns the context of a Core instance.
+		 *
+		 * @return Current Context
+		 */
         [[nodiscard]]
         const Context &getContext() const;
 
         /**
-             * Creates a #Core with given @p applicationName and @p applicationVersion for your application.
-             *
-             * It is also possible to require a specific amount of queues, ask for specific queue-flags or
-             * extensions. This function will take care of the required arguments as best as possible.
-             *
-             * To pass a valid version for your application, you should use #VK_MAKE_VERSION().
-             *
-             * @param[in] applicationName Name of the application
-             * @param[in] applicationVersion Version of the application
-             * @param[in] queueFlags (optional) Requested flags of queues
-             * @param[in] instanceExtensions (optional) Requested instance extensions
-             * @param[in] deviceExtensions (optional) Requested device extensions
-             * @return New instance of #Context
-             */
+		 * Creates a #Core with given @p applicationName and @p applicationVersion for your application.
+		 *
+		 * It is also possible to require a specific amount of queues, ask for specific queue-flags or
+		 * extensions. This function will take care of the required arguments as best as possible.
+		 *
+		 * To pass a valid version for your application, you should use #VK_MAKE_VERSION().
+		 *
+		 * @param[in] applicationName Name of the application
+		 * @param[in] applicationVersion Version of the application
+		 * @param[in] queueFlags (optional) Requested flags of queues
+		 * @param[in] instanceExtensions (optional) Requested instance extensions
+		 * @param[in] deviceExtensions (optional) Requested device extensions
+		 * @return New instance of #Context
+		 */
         static Core create(const char *applicationName,
                            uint32_t applicationVersion,
                            const std::vector<vk::QueueFlagBits>& queueFlags    = {},
@@ -172,12 +186,11 @@ namespace vkcv
         ComputePipelineHandle createComputePipeline(const ComputePipelineConfig &config);
 
         /**
-         * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
+         * Creates a basic vulkan render pass using @p config from the render pass config class and returns it.
          * Fixed Functions for pipeline are set with standard values.
          *
          * @param config a render pass config object from the render pass config class
-         * @param handle a handle to return the created vulkan handle
-         * @return True if render pass creation was successful, False if not
+         * @return A handle to represent the created pass
          */
         [[nodiscard]]
         PassHandle createPass(const PassConfig &config);
@@ -230,7 +243,7 @@ namespace vkcv
 			Multisampling   multisampling = Multisampling::None);
 
         /**
-         * creates a new window and returns it's handle
+         * Creates a new window and returns it's handle
          * @param applicationName window name
          * @param windowWidth
          * @param windowHeight
@@ -245,7 +258,7 @@ namespace vkcv
 				bool resizeable);
 
 		/**
-		 * getter for window reference
+		 * Getter for window reference
 		 * @param handle of the window
 		 * @return the window
 		 */
@@ -253,14 +266,14 @@ namespace vkcv
 		Window& getWindow(const WindowHandle& handle );
 
 		/**
-		 * gets the swapchain of the current focused window
+		 * Gets the swapchain of the current focused window
 		 * @return swapchain
 		 */
 		[[nodiscard]]
 		Swapchain& getSwapchainOfCurrentWindow();
 
 		/**
-		 * returns the swapchain reference
+		 * Returns the swapchain reference
 		 * @param handle of the swapchain
 		 * @return swapchain
 		 */
@@ -268,7 +281,7 @@ namespace vkcv
 		Swapchain& getSwapchain(const SwapchainHandle &handle);
 
 		/**
-		 * gets the swapchain handle from the window
+		 * Gets the swapchain handle from the window
 		 * @param handle of the window
 		 * @return the swapchain from getSwapchain( SwapchainHandle )
 		 */
@@ -276,7 +289,7 @@ namespace vkcv
 		Swapchain& getSwapchain(const WindowHandle &handle);
 
 		/**
-		 * returns the image width
+		 * Returns the image width
 		 * @param image handle
 		 * @return imageWidth
 		 */
@@ -284,7 +297,7 @@ namespace vkcv
         uint32_t getImageWidth(const ImageHandle &image);
 
         /**
-         * returns the image height
+         * Returns the image height
          * @param image handle
          * @return imageHeight
          */
@@ -292,7 +305,7 @@ namespace vkcv
         uint32_t getImageHeight(const ImageHandle &image);
 
         /**
-         * returns the image format of the image
+         * Returns the image format of the image
          * @param image handle
          * @return imageFormat
          */
@@ -308,31 +321,66 @@ namespace vkcv
 		[[nodiscard]]
 		uint32_t getImageMipLevels(const ImageHandle &image);
 
-		/** TODO:
-		 * @param bindings
-		 * @return
+		/**
+		 * @brief Creates a descriptor set layout handle by a set of descriptor bindings.
+		 *
+		 * @param bindings Descriptor bindings
+		 * @return Descriptor set layout handle
 		 */
 		[[nodiscard]]
-		DescriptorSetLayoutHandle createDescriptorSetLayout(const std::unordered_map<uint32_t, DescriptorBinding> &bindingsMap);
+		DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &bindings);
+		
+		/**
+		 * @brief Returns the descriptor set layout of a descriptor set layout handle.
+		 *
+		 * @param handle Descriptor set layout handle
+		 * @return Descriptor set layout
+		 */
 		DescriptorSetLayout getDescriptorSetLayout(const DescriptorSetLayoutHandle handle) const;
 
-		// TODO: existsDescriptorSetLayout function that checks and returns fitting layout upon existence.
-
-        /** TODO:
-         *   @param setDescriptions
-         *   @return
-         */
+		/**
+		 * @brief Creates a new descriptor set
+		 * 
+		 * @param layoutHandle Handle to the layout that the descriptor set will use
+		 * @return Handle that represents the descriptor set
+		 */
         [[nodiscard]]
         DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layoutHandle);
+
+		/**
+		 * @brief Writes resources bindings to a descriptor set
+		 * 
+		 * @param handle Handle of the descriptor set
+		 * @param writes Struct containing the resource bindings to be written
+		 * must be compatible with the descriptor set's layout
+		*/
 		void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
+
+		/**
+		 * @brief Returns information about a descriptor set
+		 * 
+		 * @param handle Handle of the descriptor set
+		 * @return Struct containing the descriptor set's vulkan handle, layout handle and descriptor pool index
+		*/
 		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
 
 		/**
-		 * @brief start recording command buffers and increment frame index
+		 * @brief Start recording command buffers and increment frame index
 		*/
 		bool beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle);
 
+		/**
+		 * @brief Records drawcalls to a command stream
+		 * 
+		 * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into
+		 * @param renderpassHandle Handle of the renderpass that is used for the drawcalls
+		 * @param pipelineHandle Handle of the pipeline that is used for the drawcalls
+		 * @param pushConstants Push constants that are used for the drawcalls, ignored if constant size is set to 0
+		 * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor set bindings and instance count
+		 * @param renderTargets Image handles that are used as render targets
+		 * @param windowHandle Window handle that is used to retrieve the corresponding swapchain
+		*/
 		void recordDrawcallsToCmdStream(
 			const CommandStreamHandle&      cmdStreamHandle,
 			const PassHandle&               renderpassHandle,
@@ -341,7 +389,22 @@ namespace vkcv
 			const std::vector<DrawcallInfo> &drawcalls,
 			const std::vector<ImageHandle>  &renderTargets,
 			const WindowHandle              &windowHandle);
-
+	
+		/**
+		 * @brief Records indirect drawcalls to a command stream
+		 *
+		 * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into
+		 * @param renderpassHandle Handle of the renderpass that is used for the drawcalls
+		 * @param pipelineHandle Handle of the pipeline that is used for the drawcalls
+		 * @param pushConstantData Push constants that are used for the drawcalls, ignored if constant size is set to 0
+		 * @param compiledDescriptorSet TODO
+		 * @param compiledMesh TODO
+		 * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor set bindings and instance count
+		 * @param renderTargets Image handles that are used as render targets
+		 * @param indirectBuffer TODO
+		 * @param drawCount TODO
+		 * @param windowHandle Window handle that is used to retrieve the corresponding swapchain
+		*/
 		void recordIndexedIndirectDrawcallsToCmdStream(
 				const CommandStreamHandle                           cmdStreamHandle,
 				const PassHandle                                    renderpassHandle,
@@ -353,7 +416,18 @@ namespace vkcv
 				const vkcv::Buffer<vk::DrawIndexedIndirectCommand>  &indirectBuffer,
 				const uint32_t                                      drawCount,
 				const WindowHandle                                  &windowHandle);
-
+		
+		/**
+		 * @brief Records mesh shader drawcalls to a command stream
+		 *
+		 * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into
+		 * @param renderpassHandle Handle of the renderpass that is used for the drawcalls
+		 * @param pipelineHandle Handle of the pipeline that is used for the drawcalls
+		 * @param pushConstantData Push constants that are used for the drawcalls, ignored if constant size is set to 0
+		 * @param drawcalls Information about each drawcall, consisting of descriptor set bindings and task shader dispatch count
+		 * @param renderTargets Image handles that are used as render targets
+		 * @param windowHandle Window handle that is used to retrieve the corresponding swapchain
+		*/
 		void recordMeshShaderDrawcalls(
 			const CommandStreamHandle&              cmdStreamHandle,
 			const PassHandle&                       renderpassHandle,
@@ -362,11 +436,11 @@ namespace vkcv
             const std::vector<MeshShaderDrawcall>&  drawcalls,
 			const std::vector<ImageHandle>&         renderTargets,
 			const WindowHandle&                     windowHandle);
-        
-
+		
         /**
          * Records the rtx ray generation to the @p cmdStreamHandle.
          * Currently only supports @p closestHit, @p rayGen and @c miss shaderstages @c.
+         *
          * @param cmdStreamHandle The command stream handle which receives relevant commands for drawing.
          * @param rtxPipeline The raytracing pipeline from the RTXModule.
          * @param rtxPipelineLayout The raytracing pipeline layout from the RTXModule.
@@ -390,6 +464,15 @@ namespace vkcv
             const PushConstants& pushConstants,
             const WindowHandle windowHandle);
 
+		/**
+		 * @brief Record a compute shader dispatch into a command stream
+		 * 
+		 * @param cmdStream Handle of the command stream that the dispatch is recorded into
+		 * @param computePipeline Handle of the pipeline that is used for the dispatch
+		 * @param dispatchCount How many work groups are dispatched
+		 * @param descriptorSetUsages Descriptor set bindings of the dispatch
+		 * @param pushConstants Push constant data for the dispatch
+		 */
 		void recordComputeDispatchToCmdStream(
 			CommandStreamHandle cmdStream,
             ComputePipelineHandle computePipeline,
@@ -397,12 +480,34 @@ namespace vkcv
 			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
 			const PushConstants& pushConstants);
 		
+		/**
+		 * @brief Record the start of a debug label into a command stream. 
+		 * Debug labels are displayed in GPU debuggers, such as RenderDoc
+		 * 
+		 * @param cmdStream Handle of the command stream that the label start is recorded into
+		 * @param label Label name, which is displayed in a debugger
+		 * @param color Display color for the label in a debugger
+		*/
 		void recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
 								   const std::string& label,
 								   const std::array<float, 4>& color);
 		
+		/**
+		 * @brief Record the end of a debug label into a command stream
+		 * @param cmdStream Handle of the command stream that the label end is recorded into
+		*/
 		void recordEndDebugLabel(const CommandStreamHandle &cmdStream);
 
+		/**
+		 * @brief Record an indirect compute shader dispatch into a command stream
+		 *
+		 * @param cmdStream Handle of the command stream that the indirect dispatch is recorded into
+		 * @param computePipeline Handle of the pipeline that is used for the indirect dispatch
+		 * @param buffer GPU Buffer from which the dispatch counts are read
+		 * @param bufferArgOffset Offset into the GPU Buffer from where the dispatch counts are read
+		 * @param descriptorSetUsages Descriptor set bindings of the indirect dispatch
+		 * @param pushConstants Push constant data for the indirect dispatch
+		 */
 		void recordComputeIndirectDispatchToCmdStream(
 			const CommandStreamHandle               cmdStream,
 			const ComputePipelineHandle             computePipeline,
@@ -412,8 +517,8 @@ namespace vkcv
 			const PushConstants&                    pushConstants);
 
 		/**
-		 * @brief end recording and present image
-		*/
+		 * @brief End recording and present image
+		 */
 		void endFrame( const WindowHandle& windowHandle );
 
 		/**
@@ -430,46 +535,194 @@ namespace vkcv
 			const RecordCommandFunction &record, 
 			const FinishCommandFunction &finish);
 
+		/**
+		 * @brief Create a new command stream
+		 * 
+		 * @param queueType The type of queue to which the command stream will be submitted to
+		 * @return Handle which represents the command stream
+		 */
 		CommandStreamHandle createCommandStream(QueueType queueType);
 
+		/**
+		 * @brief Record commands to a command stream by providing a function
+		 * 
+		 * @param cmdStreamHandle Handle of the command stream to record to
+		 * @param record Recording function
+		 * @param finish Finish function, called after execution of commands is finished
+		 */
 		void recordCommandsToStream(
 			const CommandStreamHandle   cmdStreamHandle,
 			const RecordCommandFunction &record,
 			const FinishCommandFunction &finish);
 
+		/**
+		 * @brief Submit command stream to GPU for actual execution
+		 * 
+		 * @param handle command stream to submit
+		 */
 		void submitCommandStream(const CommandStreamHandle& handle);
+
+		/**
+		 * @brief Prepare swapchain image for presentation to screen.
+		 * Handles internal state such as image format, also acts as a memory barrier
+		 * 
+		 * @param handle Handle of the command stream to record the preparation commands to
+		 */
 		void prepareSwapchainImageForPresent(const CommandStreamHandle& handle);
+
+		/**
+		 * @brief Prepare image for use as a sampled image.
+		 * Handles internal state such as image format, also acts as a memory barrier
+		 * 
+		 * @param cmdStream Handle of the command stream to record the preparation commands to
+		 * @param image Handle of the image to prepare
+		 */
 		void prepareImageForSampling(const CommandStreamHandle& cmdStream, const ImageHandle& image);
-		void prepareImageForStorage(const CommandStreamHandle& cmdStream, const ImageHandle& image);
 
-		// normally layout transitions for attachments are handled by the core
-		// however for manual vulkan use, e.g. ImGui integration, this function is exposed
-		// this is also why the command buffer is passed directly, instead of the command stream handle
+		/**
+		 * @brief Prepare image for use as a storage image.
+		 * Handles internal state such as image format, also acts as a memory barrier
+		 *
+		 * @param cmdStream Handle of the command stream to record the preparation commands to
+		 * @param image Handle of the image to prepare
+		 */
+		void prepareImageForStorage(const CommandStreamHandle& cmdStream, const ImageHandle& image);
+		
+		/**
+		 * @brief Manual trigger to record commands to prepare an image for use as an attachment
+		 *
+		 * normally layout transitions for attachments are handled by the core
+		 * however for manual vulkan use, e.g. ImGui integration, this function is exposed
+		 * this is also why the command buffer is passed directly, instead of the command stream handle
+		 * 
+		 * @param cmdBuffer The vulkan command buffer to record to
+		 * @param image Handle of the image to prepare
+		 */
 		void prepareImageForAttachmentManually(const vk::CommandBuffer& cmdBuffer, const ImageHandle& image);
 
-		// if manual vulkan work, e.g. ImGui integration, changes an image layout this function must be used
-		// to update the internal image state
+		/**
+		 * @brief Indicate an external change of an image's layout
+		 * 
+		 * if manual vulkan work, e.g. ImGui integration, changes an image layout this function must be used
+		 * to update the internal image state
+		 * 
+		 * @param image Handle of the image whose layout was changed
+		 * @param layout The current layout of the image
+		*/
 		void updateImageLayoutManual(const vkcv::ImageHandle& image, const vk::ImageLayout layout);
 
+		/**
+		 * @brief Records a memory barrier to synchronize subsequent accesses to the image's data
+		 * 
+		 * @param cmdStream Handle of the command stream to record the barrier to
+		 * @param image Handle of the image the barrier belongs to
+		 */
 		void recordImageMemoryBarrier(const CommandStreamHandle& cmdStream, const ImageHandle& image);
+
+		/**
+		 * @brief Records a buffer barrier to synchronize subsequent accesses to the buffer's data
+		 * 
+		 * @param cmdStream Handle of the command stream to record the barrier to
+		 * @param buffer Handle of the buffer the barrier belongs to
+		 */
 		void recordBufferMemoryBarrier(const CommandStreamHandle& cmdStream, const BufferHandle& buffer);
+
+		/**
+		 * @brief Resolve a source MSAA image into a destination image for further use
+		 * 
+		 * @param cmdStream Handle of the command stream to record the resolve to
+		 * @param src The MSAA image that is resolved
+		 * @param dst The target non-MSAA image that is resolved into
+		 */
 		void resolveMSAAImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst);
 
+		/**
+		 * @return Vulkan image view of the current swapchain image
+		 */
 		[[nodiscard]]
 		vk::ImageView getSwapchainImageView() const;
 	
+		/**
+		 * @brief Records a generic memory barrier to a command stream
+		 * 
+		 * @param cmdStream Handle of the command stream the barrier is recorded to
+		 */
 		void recordMemoryBarrier(const CommandStreamHandle& cmdStream);
 		
+		/**
+		 * @brief Record a blit (bit block image transfer) of a source image into a destination image, 
+		 * mip 0 is used for both
+		 * 
+		 * @param cmdStream Handle of the command stream the blit operation is recorded into
+		 * @param src The source image that is read from
+		 * @param dst The destination image that is written into
+		 * @param filterType The type of interpolation that is used
+		 */
 		void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
 							 SamplerFilterType filterType);
 	
+		/**
+		 * @brief Sets a debug label to a buffer handle.
+		 *
+		 * @param handle Buffer handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const BufferHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a pass handle.
+		 *
+		 * @param handle Pass handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const PassHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a graphics pipeline handle.
+		 *
+		 * @param handle Graphics pipeline handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a compute pipeline handle.
+		 *
+		 * @param handle Compute pipeline handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const ComputePipelineHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a descriptor set handle.
+		 *
+		 * @param handle Descriptor set handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a sampler handle.
+		 *
+		 * @param handle Sampler handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const SamplerHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to an image handle.
+		 *
+		 * @param handle Image handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const ImageHandle &handle, const std::string &label);
+		
+		/**
+		 * @brief Sets a debug label to a command stream handle.
+		 *
+		 * @param handle Command stream handle
+		 * @param label Debug label
+		 */
 		void setDebugLabel(const CommandStreamHandle &handle, const std::string &label);
 		
     };
diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp
index becdb9f843aa254fed6f05dec0c18686fac497d6..bc2435f6246f616c907e206e4a3de62aafaebebc 100644
--- a/include/vkcv/DescriptorConfig.hpp
+++ b/include/vkcv/DescriptorConfig.hpp
@@ -1,18 +1,23 @@
 #pragma once
+/**
+ * @authors Artur Wasmut, Tobias Frisch, Simeon Hermann, Alexander Gauggel, Vanessa Karolek
+ * @file vkcv/DescriptorConfig.hpp
+ * @brief Structures to handle descriptor types and bindings.
+ */
 
 #include <unordered_map>
 
-#include "vkcv/Handles.hpp"
-#include "vkcv/ShaderStage.hpp"
-#include "vkcv/Logger.hpp"
+#include "Handles.hpp"
+#include "ShaderStage.hpp"
+#include "Logger.hpp"
 
 namespace vkcv
 {
-    /*
-    * All the types of descriptors (resources) that can be retrieved by the shaders
-    */
-    enum class DescriptorType
-    {
+
+	/**
+	 * @brief Enum class to specify the type of a descriptor set binding.
+	 */
+    enum class DescriptorType {
         UNIFORM_BUFFER,
         STORAGE_BUFFER,
         SAMPLER,
@@ -21,13 +26,15 @@ namespace vkcv
         UNIFORM_BUFFER_DYNAMIC,
         STORAGE_BUFFER_DYNAMIC,
         ACCELERATION_STRUCTURE_KHR
-    };    
+    };
 
     /**
-    * Converts the descriptor types from VulkanCV (vkcv) to native Vulkan (vk).
-    * @param[in] vkcv DescriptorType
-    * @return vk DescriptorType
-    */
+     * @brief Converts the descriptor type from the frameworks enumeration
+     * to the Vulkan type specifier.
+     *
+     * @param[in] type Descriptor type
+     * @return Vulkan descriptor type
+     */
     constexpr vk::DescriptorType getVkDescriptorType(DescriptorType type) noexcept {
         switch (type)
         {
@@ -51,37 +58,38 @@ namespace vkcv
                 return vk::DescriptorType::eMutableVALVE;
         }
     }
-
-    /*
-    * One binding for a descriptor set
-    * @param[in] a unique binding ID
-    * @param[in] a descriptor type
-    * @param[in] the number of descriptors of this type (arrays of the same type possible)
-    * @param[in] the shader stage where the descriptor is supposed to be retrieved
-    */
-    struct DescriptorBinding
-    {
-        uint32_t        bindingID;
-        DescriptorType  descriptorType;
-        uint32_t        descriptorCount;
-        ShaderStages    shaderStages;
-        bool            variableCount;
+	
+	/**
+	 * @brief Structure to store details from a descriptor binding.
+	 */
+    struct DescriptorBinding {
+        uint32_t bindingID;
+        DescriptorType descriptorType;
+        uint32_t descriptorCount;
+        ShaderStages shaderStages;
+        bool variableCount;
 
         bool operator ==(const DescriptorBinding &other) const;
     };
     
     typedef std::unordered_map<uint32_t, DescriptorBinding> DescriptorBindings;
-
-    struct DescriptorSetLayout
-    {
+	
+	/**
+	 * @brief Structure to store details about a descriptor set layout.
+	 */
+    struct DescriptorSetLayout {
         vk::DescriptorSetLayout vulkanHandle;
         DescriptorBindings descriptorBindings;
+        size_t layoutUsageCount;
     };
-
-    struct DescriptorSet
-    {
-        vk::DescriptorSet           vulkanHandle;
-        DescriptorSetLayoutHandle   setLayoutHandle;
-        size_t                      poolIndex;
+	
+	/**
+	 * @brief Structure to store details about a descriptor set.
+	 */
+    struct DescriptorSet {
+        vk::DescriptorSet vulkanHandle;
+        DescriptorSetLayoutHandle setLayoutHandle;
+        size_t poolIndex;
     };
+	
 }
diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp
index f4f9729a193c9da4cfc4ccc869337314e8a71ccb..b8468bfdfd4cd20e59742f410ff8716be4e910fa 100644
--- a/include/vkcv/DescriptorWrites.hpp
+++ b/include/vkcv/DescriptorWrites.hpp
@@ -1,57 +1,209 @@
 #pragma once
-#include "Handles.hpp"
+/**
+ * @authors Artur Wasmut, Tobias Frisch, Alexander Gauggel, Vanessa Karolek
+ * @file vkcv/DescriptorWrites.hpp
+ * @brief Structures to handle descriptor writes.
+ */
+
 #include <vector>
 
+#include "Handles.hpp"
+
 namespace vkcv {
+	
+	/**
+	 * @brief Structure to store details writing a sampled image to a descriptor set.
+	 */
 	struct SampledImageDescriptorWrite {
-		inline SampledImageDescriptorWrite(uint32_t binding, ImageHandle image, uint32_t mipLevel = 0, bool useGeneralLayout = false, uint32_t arrayIndex = 0)
-		: binding(binding), image(image), mipLevel(mipLevel), useGeneralLayout(useGeneralLayout), arrayIndex(arrayIndex) {};
-		uint32_t	binding;
-		ImageHandle	image;
-		uint32_t    mipLevel;
-		bool        useGeneralLayout;
-		uint32_t    arrayIndex;
+		uint32_t binding;
+		ImageHandle image;
+		uint32_t mipLevel;
+		bool useGeneralLayout;
+		uint32_t arrayIndex;
 	};
-
+	
+	/**
+	 * @brief Structure to store details writing a storage image to a descriptor set.
+	 */
 	struct StorageImageDescriptorWrite {
-		inline StorageImageDescriptorWrite(uint32_t binding, ImageHandle image, uint32_t mipLevel = 0) 
-			: binding(binding), image(image), mipLevel(mipLevel) {};
-		uint32_t	binding;
-		ImageHandle	image;
-		uint32_t	mipLevel;
+		uint32_t binding;
+		ImageHandle image;
+		uint32_t mipLevel;
 	};
-
+	
+	/**
+	 * @brief Structure to store details writing a buffer to a descriptor set.
+	 */
 	struct BufferDescriptorWrite {
-		inline BufferDescriptorWrite(uint32_t binding, BufferHandle buffer, bool dynamic = false,
-									 uint32_t offset = 0, uint32_t size = 0) :
-		binding(binding), buffer(buffer), dynamic(dynamic), offset(offset), size(size) {};
-		uint32_t		binding;
-		BufferHandle	buffer;
-		bool 			dynamic;
-		uint32_t 		offset;
-		uint32_t 		size;
+		uint32_t binding;
+		BufferHandle buffer;
+		bool dynamic;
+		uint32_t offset;
+		uint32_t size;
 	};
-
+	
+	/**
+	 * @brief Structure to store details writing a sampler to a descriptor set.
+	 */
 	struct SamplerDescriptorWrite {
-		inline SamplerDescriptorWrite(uint32_t binding, SamplerHandle sampler) : binding(binding), sampler(sampler) {};
-		uint32_t		binding;
-		SamplerHandle	sampler;
+		uint32_t binding;
+		SamplerHandle sampler;
 	};
-
+	
 	/**
-	 * @brief Only used for RTX. Used to bind the Acceleration Structure.
+	 * @brief Structure to store details writing an acceleration structure to
+	 * a descriptor set.
 	 */
 	struct AccelerationDescriptorWrite {
-	    inline AccelerationDescriptorWrite(uint32_t binding) : binding(binding) {};
-	    uint32_t    binding;
+	    uint32_t binding;
 	};
 
-	struct DescriptorWrites {
-		std::vector<SampledImageDescriptorWrite>		sampledImageWrites;
-		std::vector<StorageImageDescriptorWrite>		storageImageWrites;
-		std::vector<BufferDescriptorWrite>	    		uniformBufferWrites;
-		std::vector<BufferDescriptorWrite>	    		storageBufferWrites;
-		std::vector<SamplerDescriptorWrite>			    samplerWrites;
-		std::vector<AccelerationDescriptorWrite>        accelerationWrites;
+	/**
+	 * @brief Class to store details about writing to
+	 * a descriptor set and its bindings.
+	 */
+	class DescriptorWrites {
+	private:
+		std::vector<SampledImageDescriptorWrite> m_sampledImageWrites;
+		std::vector<StorageImageDescriptorWrite> m_storageImageWrites;
+		std::vector<BufferDescriptorWrite> m_uniformBufferWrites;
+		std::vector<BufferDescriptorWrite> m_storageBufferWrites;
+		std::vector<SamplerDescriptorWrite> m_samplerWrites;
+		std::vector<AccelerationDescriptorWrite> m_accelerationWrites;
+		
+	public:
+		/**
+		 * @brief Adds an entry to write an image to a given binding
+		 * of a descriptor set to sample from it using specific details.
+		 *
+		 * @param[in] binding Binding index
+		 * @param[in] image Image handle
+		 * @param[in] mipLevel Mip level index
+		 * @param[in] useGeneralLayout Flag to use a general layout
+		 * @param[in] arrayIndex Image array index
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeSampledImage(uint32_t binding,
+											ImageHandle image,
+											uint32_t mipLevel = 0,
+											bool useGeneralLayout = false,
+											uint32_t arrayIndex = 0);
+		
+		/**
+		 * @brief Adds an entry to write an image to a given binding
+		 * of a descriptor set to store into it using specific details.
+		 *
+		 * @param[in] binding Binding index
+		 * @param[in,out] image Image handle
+		 * @param[in] mipLevel Mip level index
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeStorageImage(uint32_t binding,
+											ImageHandle image,
+											uint32_t mipLevel = 0);
+		
+		/**
+		 * @brief Adds an entry to write a buffer to a given binding
+		 * of a descriptor set as uniform buffer using specific details.
+		 *
+		 * @param[in] binding Binding index
+		 * @param[in] buffer Buffer handle
+		 * @param[in] dynamic Flag to use dynamic access
+		 * @param[in] offset Offset for buffer access range
+		 * @param[in] size Size of the buffer access range
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeUniformBuffer(uint32_t binding,
+											 BufferHandle buffer,
+											 bool dynamic = false,
+											 uint32_t offset = 0,
+											 uint32_t size = 0);
+		
+		/**
+		 * @brief Adds an entry to write a buffer to a given binding
+		 * of a descriptor set as storage buffer using specific details.
+		 *
+		 * @param[in] binding Binding index
+		 * @param[in] buffer Buffer handle
+		 * @param[in,out] dynamic Flag to use dynamic access
+		 * @param[in] offset Offset for buffer access range
+		 * @param[in] size Size of the buffer access range
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeStorageBuffer(uint32_t binding,
+											 BufferHandle buffer,
+											 bool dynamic = false,
+											 uint32_t offset = 0,
+											 uint32_t size = 0);
+		
+		/**
+		 * @brief Adds an entry to write a sampler to a given binding
+		 * of a descriptor set.
+		 *
+		 * @param[in] binding Binding index
+		 * @param[in] sampler Sampler handle
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeSampler(uint32_t binding,
+									   SamplerHandle sampler);
+		
+		/**
+		 * @brief Adds an entry for acceleration to a given binding
+		 * of a descriptor set.
+		 *
+		 * @param[in] binding Binding index
+		 * @return Instance of descriptor writes
+		 */
+		DescriptorWrites& writeAcceleration(uint32_t binding);
+		
+		/**
+		 * @brief Returns the list of stored write entries for sampled images.
+		 *
+		 * @return Sampled image write details
+		 */
+		[[nodiscard]]
+		const std::vector<SampledImageDescriptorWrite>& getSampledImageWrites() const;
+		
+		/**
+		 * @brief Returns the list of stored write entries for storage images.
+		 *
+		 * @return Storage image write details
+		 */
+		[[nodiscard]]
+		const std::vector<StorageImageDescriptorWrite>& getStorageImageWrites() const;
+		
+		/**
+		 * @brief Returns the list of stored write entries for uniform buffers.
+		 *
+		 * @return Uniform buffers write details
+		 */
+		[[nodiscard]]
+		const std::vector<BufferDescriptorWrite>& getUniformBufferWrites() const;
+		
+		/**
+		 * @brief Returns the list of stored write entries for storage buffers.
+		 *
+		 * @return Storage buffers write details
+		 */
+		[[nodiscard]]
+		const std::vector<BufferDescriptorWrite>& getStorageBufferWrites() const;
+		
+		/**
+		 * @brief Returns the list of stored write entries for samplers.
+		 *
+		 * @return Samplers write details
+		 */
+		[[nodiscard]]
+		const std::vector<SamplerDescriptorWrite>& getSamplerWrites() const;
+		
+		/**
+		 * @brief Returns the list of stored write entries for accelerations.
+		 *
+		 * @return Accelerations write details
+		 */
+		[[nodiscard]]
+		const std::vector<AccelerationDescriptorWrite>& getAccelerationWrites() const;
+		
 	};
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp
index 70b23107c4605e6ac01aa80fa4a431c62d7a7219..76b94dc8b4f8595d98e87920329eb616d703f0db 100644
--- a/include/vkcv/DrawcallRecording.hpp
+++ b/include/vkcv/DrawcallRecording.hpp
@@ -1,82 +1,104 @@
 #pragma once
+/**
+ * @authors Sebastian Gaida, Alexander Gauggel, Artur Wasmut, Tobias Frisch
+ * @file vkcv/DrawcallRecording.hpp
+ * @brief Structures and functions to record drawcalls.
+ */
+
 #include <vulkan/vulkan.hpp>
-#include "vkcv/Handles.hpp"
-#include "vkcv/DescriptorConfig.hpp"
-#include "vkcv/PushConstants.hpp"
+
+#include "Handles.hpp"
+#include "DescriptorConfig.hpp"
+#include "PushConstants.hpp"
+
 #include "Buffer.hpp"
 
 namespace vkcv {
 	
+	/**
+	 * @brief Structure to store details about a vertex buffer binding.
+	 */
     struct VertexBufferBinding {
-        inline VertexBufferBinding(vk::DeviceSize offset, vk::Buffer buffer) noexcept
-            : offset(offset), buffer(buffer) {}
-
-        vk::DeviceSize  offset;
-        vk::Buffer      buffer;
+        vk::DeviceSize offset;
+        vk::Buffer buffer;
     };
 
-    enum class IndexBitCount{
+	/**
+	 * @brief Enum class to specify the size of indexes.
+	 */
+    enum class IndexBitCount {
+		Bit8,
         Bit16,
         Bit32
     };
-
+	
+	/**
+	 * @brief Structure to configure a descriptor set usage.
+	 */
     struct DescriptorSetUsage {
         inline DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle descriptorSet,
-								  const std::vector<uint32_t>& dynamicOffsets = {}) noexcept
-            : setLocation(setLocation), descriptorSet(descriptorSet), dynamicOffsets(dynamicOffsets) {}
+								  const std::vector<uint32_t>& dynamicOffsets = {}) noexcept :
+			setLocation(setLocation),
+			descriptorSet(descriptorSet),
+			dynamicOffsets(dynamicOffsets) {}
 
         const uint32_t          	setLocation;
         const DescriptorSetHandle 	descriptorSet;
         const std::vector<uint32_t> dynamicOffsets;
     };
-
+	
+	/**
+	 * @brief Structure to store details of a mesh to draw.
+	 */
     struct Mesh {
-
-        inline Mesh(){}
-
-        inline Mesh(
-            std::vector<VertexBufferBinding>    vertexBufferBindings,
-            vk::Buffer                          indexBuffer,
-            size_t                              indexCount,
-            IndexBitCount                       indexBitCount = IndexBitCount::Bit16) noexcept
-            :
-            vertexBufferBindings(vertexBufferBindings),
-            indexBuffer(indexBuffer),
+        inline Mesh() {}
+
+        inline Mesh(std::vector<VertexBufferBinding> vertexBufferBindings,
+					vk::Buffer indexBuffer,
+					size_t indexCount,
+					IndexBitCount indexBitCount = IndexBitCount::Bit16) noexcept :
+			vertexBufferBindings(vertexBufferBindings),
+			indexBuffer(indexBuffer),
             indexCount(indexCount),
             indexBitCount(indexBitCount) {}
 
-        std::vector<VertexBufferBinding>    vertexBufferBindings;
-        vk::Buffer                          indexBuffer;
-        size_t                              indexCount;
-        IndexBitCount                       indexBitCount;
+        std::vector<VertexBufferBinding> vertexBufferBindings;
+        vk::Buffer indexBuffer;
+        size_t indexCount;
+        IndexBitCount indexBitCount;
 
     };
-
+	
+	/**
+	 * @brief Structure to store details for a drawcall.
+	 */
     struct DrawcallInfo {
-        inline DrawcallInfo(const Mesh& mesh, const std::vector<DescriptorSetUsage>& descriptorSets, const uint32_t instanceCount = 1)
-            : mesh(mesh), descriptorSets(descriptorSets), instanceCount(instanceCount){}
-
-        Mesh                            mesh;
+        inline DrawcallInfo(const Mesh& mesh,
+							const std::vector<DescriptorSetUsage>& descriptorSets,
+							const uint32_t instanceCount = 1) :
+			mesh(mesh),
+			descriptorSets(descriptorSets),
+			instanceCount(instanceCount){}
+
+        Mesh mesh;
         std::vector<DescriptorSetUsage> descriptorSets;
-        uint32_t                        instanceCount;
+        uint32_t instanceCount;
     };
-
-    void InitMeshShaderDrawFunctions(vk::Device device);
-
+	
+	/**
+	 * @brief Structure to store details for a mesh shader drawcall.
+	 */
     struct MeshShaderDrawcall {
-        inline MeshShaderDrawcall(const std::vector<DescriptorSetUsage> descriptorSets, uint32_t taskCount)
-            : descriptorSets(descriptorSets), taskCount(taskCount) {}
-
         std::vector<DescriptorSetUsage> descriptorSets;
-        uint32_t                        taskCount;
+        uint32_t taskCount;
     };
 
-    void recordMeshShaderDrawcall(
-		const Core&								core,
-        vk::CommandBuffer                       cmdBuffer,
-        vk::PipelineLayout                      pipelineLayout,
-        const PushConstants&                 	pushConstantData,
-        const uint32_t                          pushConstantOffset,
-        const MeshShaderDrawcall&               drawcall,
-        const uint32_t                          firstTask);
+    void recordMeshShaderDrawcall(const Core& core,
+								  vk::CommandBuffer cmdBuffer,
+								  vk::PipelineLayout pipelineLayout,
+								  const PushConstants& pushConstantData,
+								  uint32_t pushConstantOffset,
+								  const MeshShaderDrawcall& drawcall,
+								  uint32_t firstTask);
+	
 }
diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp
index 0a5cc1f0d93b6eebea6a54cd8d48632ea4c0be31..c4a05d0e126c2a44a67cfb4e1aad7d07ad6efaa5 100644
--- a/include/vkcv/Event.hpp
+++ b/include/vkcv/Event.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Tobias Frisch, Sebastian Gaida, Josch Morgenstern, Katharina Krämer
+ * @file vkcv/Event.hpp
+ * @brief Template event struct to synchronize callbacks.
+ */
 
 #include <functional>
 
@@ -14,11 +19,21 @@
 
 namespace vkcv {
 	
+	/**
+	 * @brief Template for a function handle to an event
+	 *
+	 * @tparam T Event parameter type list
+	 */
 	template<typename... T>
 	struct event_handle {
 		uint32_t id;
 	};
 
+	/**
+	 * @brief Template for an event function
+	 *
+	 * @tparam T Event parameter type list
+	 */
     template<typename... T>
     struct event_function {
         typedef std::function<void(T...)> type;
@@ -28,8 +43,9 @@ namespace vkcv {
     };
 
     /**
-     * template for event handling
-     * @tparam T parameter list
+     * @brief Template for event handling
+     *
+     * @tparam T Event parameter type list
      */
     template<typename... T>
     struct event {
@@ -48,8 +64,9 @@ namespace vkcv {
     public:
 
         /**
-         * calls all function handles with the given arguments
-         * @param arguments of the given function
+         * @brief Calls all function handles with the given arguments.
+         *
+         * @param[in,out] arguments Arguments of the given event
          */
         void operator()(T... arguments) {
 			lock();
@@ -62,9 +79,10 @@ namespace vkcv {
         }
 
         /**
-         * adds a function handle to the event to be called
-         * @param callback of the function
-         * @return handle of the function
+         * @brief Adds a function handle to the event to be called.
+         *
+         * @param[in] callback Event callback
+         * @return Handle of the function
          */
 		event_handle<T...> add(typename event_function<T...>::type callback) {
 			event_function<T...> function;
@@ -75,8 +93,9 @@ namespace vkcv {
         }
 
         /**
-         * removes a function handle of the event
-         * @param handle of the function
+         * @brief Removes a function handle of the event.
+         *
+         * @param handle Handle of the function
          */
         void remove(event_handle<T...> handle) {
             this->m_functions.erase(
@@ -88,7 +107,8 @@ namespace vkcv {
         }
         
         /**
-         * locks the event so its function handles won't be called
+         * @brief Locks the event so its function handles won't
+         * be called until unlocked.
          */
         void lock() {
 #ifndef __MINGW32__
@@ -101,8 +121,9 @@ namespace vkcv {
         }
 	
 		/**
-		* unlocks the event so its function handles can be called after locking
-		*/
+		 * @brief Unlocks the event so its function handles can
+		 * be called after locking.
+		 */
         void unlock() {
 #ifndef __MINGW32__
 #ifdef __NO_SEMAPHORES__
@@ -136,5 +157,7 @@ namespace vkcv {
         event &operator=(const event &other) = delete;
 
         event &operator=(event &&other) = delete;
+		
     };
+	
 }
diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp
index 5d5a2e9a7ca839c1cbd2cfa53d0f61d042ac3b2a..51e422c949b66fe021ec3a5afd95f50a94e39544 100644
--- a/include/vkcv/FeatureManager.hpp
+++ b/include/vkcv/FeatureManager.hpp
@@ -1,152 +1,403 @@
 #pragma once
-
-#include "Logger.hpp"
+/**
+ * @authors Tobias Frisch, Artur Wasmut, Vanessa Karolek, Sebastian Gaida
+ * @file vkcv/FeatureManager.hpp
+ * @brief Class to manage feature support and extension usage.
+ */
 
 #include <functional>
 #include <unordered_set>
 #include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "Logger.hpp"
+
 namespace vkcv {
 
+	/**
+	 * @brief Class to manage extension and feature requirements, support and usage.
+	 */
 	class FeatureManager {
 	private:
+		/**
+		 * Physical device to check feature support against.
+		 */
 		vk::PhysicalDevice& m_physicalDevice;
 		
+		/**
+		 * List of supported extensions.
+		 */
 		std::vector<const char*> m_supportedExtensions;
+		
+		/**
+		 * List of activated extensions for usage.
+		 */
 		std::vector<const char*> m_activeExtensions;
 		
+		/**
+		 * Feature structure chain to request activated features.
+		 */
 		vk::PhysicalDeviceFeatures2 m_featuresBase;
+		
+		/**
+		 * List of base structures allocated to request extension specific features.
+		 */
 		std::vector<vk::BaseOutStructure*> m_featuresExtensions;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceFeatures& features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDevice16BitStorageFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDevice16BitStorageFeatures& features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDevice8BitStorageFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceBufferDeviceAddressFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceDescriptorIndexingFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceHostQueryResetFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceImagelessFramebufferFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceMultiviewFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceProtectedMemoryFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceSamplerYcbcrConversionFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceScalarBlockLayoutFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicInt64Features.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceShaderFloat16Int8Features.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features& features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceTimelineSemaphoreFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceUniformBufferStandardLayoutFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceVariablePointersFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceVulkanMemoryModelFeatures.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, bool required) const;
 		
+		/**
+         * @brief Checks support of the @p vk::PhysicalDeviceMeshShaderFeaturesNV.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
+         */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV& features, bool required) const;
 		
+		/**
+		 * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT.
+		 *
+		 * @param[in] features The features
+		 * @param[in] required True, if the @p features are required, else false
+		 * @return @p True, if the @p features are supported, else @p false
+		 */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT& features, bool required) const;
 		
+		/**
+		 * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT.
+		 *
+		 * @param[in] features The features
+		 * @param[in] required True, if the @p features are required, else false
+		 * @return @p True, if the @p features are supported, else @p false
+		 */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT& features, bool required) const;
 		
 		/**
-         * @brief Currently used for RTX. Checks support of the @p vk::PhysicalDeviceVulkan12Features.
-         * @param features The features.
-         * @param required True, if the @p features are required, else false.
-         * @return @p True, if the @p features are supported, else @p false.
+         * @brief Checks support of the @p vk::PhysicalDeviceVulkan12Features.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
          */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceVulkan12Features& features, bool required) const;
 
 		/**
-         * @brief Currently used for RTX. Checks support of the @p vk::PhysicalDeviceVulkan11Features.
-         * @param features The features.
-         * @param required True, if the @p features are required, else false.
-         * @return @p True, if the @p features are supported, else @p false.
+         * @brief Checks support of the @p vk::PhysicalDeviceVulkan11Features.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
          */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceVulkan11Features& features, bool required) const;
 
 		/**
-		 * @brief Only used for RTX. Checks support of the @p vk::PhysicalDeviceAccelerationStructureFeaturesKHR.
-		 * @param features The features.
-		 * @param required True, if the @p features are required, else false.
-		 * @return @p True, if the @p features are supported, else @p false.
+		 * @brief Checks support of the @p vk::PhysicalDeviceAccelerationStructureFeaturesKHR.
+		 *
+		 * @param[in] features The features
+		 * @param[in] required True, if the @p features are required, else false
+		 * @return @p True, if the @p features are supported, else @p false
 		 */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceAccelerationStructureFeaturesKHR& features, bool required) const;
 
 		/**
-         * @brief Only used for RTX. Checks support of the @p vk::PhysicalDeviceRayTracingPipelineFeaturesKHR.
-         * @param features The features.
-         * @param required True, if the @p features are required, else false.
-         * @return @p True, if the @p features are supported, else @p false.
+         * @brief Checks support of the @p vk::PhysicalDeviceRayTracingPipelineFeaturesKHR.
+         *
+         * @param[in] features The features
+         * @param[in] required True, if the @p features are required, else false
+         * @return @p True, if the @p features are supported, else @p false
          */
 		[[nodiscard]]
 		bool checkSupport(const vk::PhysicalDeviceRayTracingPipelineFeaturesKHR& features, bool required) const;
 		
+		/**
+		 * @brief Searches for a base structure of a given structure type.
+		 *
+		 * @param[in] type Structure type
+		 * @return Pointer to first matching base structure or nullptr
+		 */
+		[[nodiscard]]
 		vk::BaseOutStructure* findFeatureStructure(vk::StructureType type) const;
 	
 	public:
+		/**
+		 * @brief Constructor of a feature manager with a given physical device.
+		 *
+		 * @param[in,out] physicalDevice Physical device
+		 */
 		explicit FeatureManager(vk::PhysicalDevice& physicalDevice);
 		
 		FeatureManager(const FeatureManager& other) = delete;
+		
+		/**
+		 * @brief Move-constructor of a feature manager.
+		 *
+		 * @param[in,out] other Other feature manager instance
+		 */
 		FeatureManager(FeatureManager&& other) noexcept;
 		
+		/**
+		 * @brief Destructor of a feature manager.
+		 */
 		~FeatureManager();
 		
 		FeatureManager& operator=(const FeatureManager& other) = delete;
+		
+		/**
+		 * @brief Move-operator of a feature manager.
+		 *
+		 * @param[in,out] other Other feature manager instance
+		 * @return Reference to the feature manager itself
+		 */
 		FeatureManager& operator=(FeatureManager&& other) noexcept;
 		
+		/**
+		 * @brief Check if a specific extension is supported by the managers physical device.
+		 *
+		 * @param[in] extension Extension identifier string
+		 * @return @p True, if the @p extension is supported, else @p false
+		 */
 		[[nodiscard]]
 		bool isExtensionSupported(const std::string& extension) const;
 		
+		/**
+		 * @brief Activate a specific extension if supported by the managers physical device.
+		 *
+		 * @param[in] extension Extension identifier string
+		 * @param[in] required True, if the @p extension is required, else false
+		 * @return @p True, if the @p extension could be activated, else @p false
+		 */
 		bool useExtension(const std::string& extension, bool required = true);
 		
+		/**
+		 * @brief Check if a specific extension is activated by the manager.
+		 *
+		 * @param[in] extension Extension identifier string
+		 * @return @p True, if the @p extension is activated, else @p false
+		 */
 		[[nodiscard]]
 		bool isExtensionActive(const std::string& extension) const;
 		
+		/**
+		 * @brief Return list of activated extensions for usage.
+		 *
+		 * @return List of activated extensions
+		 */
 		[[nodiscard]]
 		const std::vector<const char*>& getActiveExtensions() const;
 		
+		/**
+		 * @brief Request specific features for optional or required usage ( only core Vulkan 1.0 ).
+		 *
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 * @param[in] required True, if the @p features are required, else false
+		 * @return @p True, if the requested features could be activated, else @p false
+		 */
 		bool useFeatures(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction, bool required = true);
 		
+		/**
+		 * @brief Request specific features for optional or required usage.
+		 *
+		 * @tparam T Template parameter to use specific base structure types
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 * @param[in] required True, if the @p features are required, else false
+		 * @return @p True, if the requested features could be activated, else @p false
+		 * @see checkSupport()
+		 */
 		template<typename T>
 		bool useFeatures(const std::function<void(T&)>& featureFunction, bool required = true) {
 			T features;
@@ -188,6 +439,11 @@ namespace vkcv {
 			return true;
 		}
 		
+		/**
+		 * @brief Return feature structure chain to request activated features.
+		 *
+		 * @return Head of feature structure chain
+		 */
 		[[nodiscard]]
 		const vk::PhysicalDeviceFeatures2& getFeatures() const;
 		
diff --git a/include/vkcv/Features.hpp b/include/vkcv/Features.hpp
index 6ef3fa28be912627b4495c66427336dfaa51beff..bb0e88c2b52775f00e5d74804d055fe35ee6bd58 100644
--- a/include/vkcv/Features.hpp
+++ b/include/vkcv/Features.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Features.hpp
+ * @brief Class to manage feature requests.
+ */
 
 #include <functional>
 #include <vector>
@@ -8,30 +13,92 @@
 
 namespace vkcv {
 	
+	/**
+	 * Abstract function type to request a feature via the feature manager.
+	 */
 	typedef std::function<bool(FeatureManager&)> Feature;
 	
+	/**
+	 * @brief Class to manage a list of feature requests at once.
+	 */
 	class Features {
 	private:
+		/**
+		 * List of feature requests.
+		 */
 		std::vector<Feature> m_features;
 		
 	public:
+		/**
+		 * @brief Constructor of a features instance.
+		 */
 		Features() = default;
 		
+		/**
+		 * @brief Constructor of a features instance with a given list of extension identifier strings.
+		 *
+		 * @param[in] list List of extension identifier strings
+		 */
 		Features(const std::initializer_list<std::string>& list);
 		
+		/**
+		 * @brief Copy-constructor of a features instance.
+		 *
+		 * @param[in] other Other features instance
+		 */
 		Features(const Features& other) = default;
+		
+		/**
+		 * @brief Move-constructor of a features instance.
+		 *
+		 * @param[in,out] other Other features instance
+		 */
 		Features(Features&& other) = default;
 		
+		/**
+		 * @brief Destructor of a features instance.
+		 */
 		~Features() = default;
 		
+		/**
+		 * @brief Copy-operator of a features instance.
+		 *
+		 * @param[in] other Other features instance
+		 * @return Reference to the features instance itself
+		 */
 		Features& operator=(const Features& other) = default;
+		
+		/**
+		 * @brief Move-operator of a features instance.
+		 *
+		 * @param[in,out] other Other features instance
+		 * @return Reference to the features instance itself
+		 */
 		Features& operator=(Features&& other) = default;
 		
+		/**
+		 * @brief Request a specific extension as required.
+		 *
+		 * @param[in] extension Extension identifier string
+		 */
 		void requireExtension(const std::string& extension);
 		
+		/**
+		 * @brief Request a specific extension and some of its features as required ( only core Vulkan 1.0 ).
+		 *
+		 * @param[in] extension Extension identifier string
+		 * @param[in] featureFunction
+		 */
 		void requireExtensionFeature(const std::string& extension,
 									 const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
 		
+		/**
+		 * @brief Request a specific extension and some of its features as required.
+		 *
+		 * @tparam T Template parameter to use specific base structure types
+		 * @param[in] extension Extension identifier string
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		template<typename T>
 		void requireExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) {
 			m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) {
@@ -43,8 +110,19 @@ namespace vkcv {
 			});
 		}
 		
+		/**
+		 * @brief Request a specific set of features as required ( only core Vulkan 1.0 ).
+		 *
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		void requireFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
 		
+		/**
+		 * @brief Request a specific set of features as required.
+		 *
+		 * @tparam T Template parameter to use specific base structure types
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		template<typename T>
 		void requireFeature(const std::function<void(T&)>& featureFunction) {
 			m_features.emplace_back([featureFunction](FeatureManager& featureManager) {
@@ -52,11 +130,29 @@ namespace vkcv {
 			});
 		}
 		
+		/**
+		 * @brief Request a specific extension as optional.
+		 *
+		 * @param[in] extension Extension identifier string
+		 */
 		void tryExtension(const std::string& extension);
 		
+		/**
+		 * @brief Request a specific extension and some of its features as optional ( only core Vulkan 1.0 ).
+		 *
+		 * @param[in] extension Extension identifier string
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		void tryExtensionFeature(const std::string& extension,
 								 const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
 		
+		/**
+		 * @brief Request a specific extension and some of its features as optional.
+		 *
+		 * @tparam T Template parameter to use specific base structure types
+		 * @param[in] extension Extension identifier string
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		template<typename T>
 		void tryExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) {
 			m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) {
@@ -68,8 +164,19 @@ namespace vkcv {
 			});
 		}
 		
+		/**
+		 * @brief Request a specific set of features as optional ( only core Vulkan 1.0 ).
+		 *
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		void tryFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
 		
+		/**
+		 * @brief Request a specific set of features as optional.
+		 *
+		 * @tparam T Template parameter to use specific base structure types
+		 * @param[in] featureFunction Function or lambda to request specific features
+		 */
 		template<typename T>
 		void tryFeature(const std::function<void(T&)>& featureFunction) {
 			m_features.emplace_back([featureFunction](FeatureManager& featureManager) {
@@ -77,6 +184,11 @@ namespace vkcv {
 			});
 		}
 		
+		/**
+		 * @brief Return list of feature requests.
+		 *
+		 * @return List of feature requests
+		 */
 		[[nodiscard]]
 		const std::vector<Feature>& getList() const;
 		
diff --git a/include/vkcv/File.hpp b/include/vkcv/File.hpp
index 06f1c48593853147140b2c8c68c675d52c9dfaec..4d81f368b03d374fe4f83bf197a76ddd8a6b034a 100644
--- a/include/vkcv/File.hpp
+++ b/include/vkcv/File.hpp
@@ -1,11 +1,26 @@
 #pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/File.hpp
+ * @brief Functions to handle generating temporary file paths.
+ */
 
 #include <filesystem>
 
 namespace vkcv {
 	
+	/**
+	 * @brief Generate a new temporary file path and return it.
+	 *
+	 * @return A unique path for a temporary file
+	 */
 	std::filesystem::path generateTemporaryFilePath();
 	
+	/**
+	 * @brief Generate a new temporary directory path and return it.
+	 *
+	 * @return A unique path for a temporary directory
+	 */
 	std::filesystem::path generateTemporaryDirectoryPath();
 	
 }
diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp
index 286411969a5aa1ce818735faea238f246adb40d6..85cabc135ddfa8e6e6762c16c269741e232cff4d 100644
--- a/include/vkcv/GraphicsPipelineConfig.hpp
+++ b/include/vkcv/GraphicsPipelineConfig.hpp
@@ -1,12 +1,13 @@
 #pragma once
 /**
- * @authors Mara Vogt, Mark Mints
- * @file src/vkcv/PipelineConfig.hpp
+ * @authors Mara Vogt, Mark Mints, Tobias Frisch
+ * @file vkcv/GraphicsPipelineConfig.hpp
  * @brief Graphics Pipeline Config Struct to hand over required information to Pipeline Creation
  */
 
 #include <vector>
 #include <cstdint>
+
 #include "Handles.hpp"
 #include "ShaderProgram.hpp"
 #include "VertexLayout.hpp"
@@ -14,14 +15,51 @@
 
 namespace vkcv {
 
-    enum class PrimitiveTopology{PointList, LineList, TriangleList, PatchList };
-	enum class CullMode{ None, Front, Back };
-    enum class DepthTest { None, Less, LessEqual, Greater, GreatherEqual, Equal };
+	/**
+	 * @brief Enum class to specify types of primitive topology.
+	 */
+    enum class PrimitiveTopology {
+		PointList,
+		LineList,
+		TriangleList,
+		PatchList
+	};
+	
+	/**
+	 * @brief Enum class to specify modes of culling.
+	 */
+	enum class CullMode {
+		None,
+		Front,
+		Back,
+		Both
+	};
+	
+	/**
+	 * @brief Enum class to specify depth-test modes.
+	 */
+    enum class DepthTest {
+		None,
+		Less,
+		LessEqual,
+		Greater,
+		GreatherEqual,
+		Equal
+	};
 
     // add more as needed
     // alternatively we could expose the blend factors directly
-    enum class BlendMode{ None, Additive };
-
+	/**
+	 * @brief Enum class to specify blending modes.
+	 */
+    enum class BlendMode {
+		None,
+		Additive
+	};
+	
+	/**
+	 * @brief Structure to configure a graphics pipeline before its creation.
+	 */
     struct GraphicsPipelineConfig {
         ShaderProgram                         	m_ShaderProgram;
         uint32_t                              	m_Width;
diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp
index 1e6091c97dbe8dfc31013b653f175acede76070b..dea1793871a320016cf7c0da3f3877fc66a6f616 100644
--- a/include/vkcv/Handles.hpp
+++ b/include/vkcv/Handles.hpp
@@ -1,7 +1,7 @@
 #pragma once
 /**
- * @authors Artur Wasmut
- * @file src/vkcv/Handles.cpp
+ * @authors Tobias Frisch, Alexander Gauggel, Artur Wasmut, Sebastian Gaida, Mark Mints
+ * @file vkcv/Handles.hpp
  * @brief Central header file for all possible handles that the framework will hand out.
  */
 
@@ -12,8 +12,14 @@
 namespace vkcv
 {
 	
+	/**
+	 * @brief Function to be called when a handles resources can be destroyed.
+	 */
 	typedef typename event_function<uint64_t>::type HandleDestroyFunction;
-	
+
+    /**
+     * @brief Class for general memory management via handles.
+     */
 	class Handle {
 		friend std::ostream& operator << (std::ostream& out, const Handle& handle);
 		
@@ -24,12 +30,22 @@ namespace vkcv
 		HandleDestroyFunction m_destroy;
 	
 	protected:
+		/**
+		 * @brief Constructor of an invalid handle
+		 */
 		Handle();
 		
+		/**
+		 * @brief Constructor of a valid handle with an
+		 * unique id and an optional destroy callback.
+		 *
+		 * @param[in] id Unique handle id
+		 * @param[in] destroy Destroy callback (optional)
+		 */
 		explicit Handle(uint64_t id, const HandleDestroyFunction& destroy = nullptr);
 		
 		/**
-		 * Returns the actual handle id of a handle.
+		 * @brief Returns the actual handle id of a handle.
 		 *
 		 * @return Handle id
 		 */
@@ -37,7 +53,7 @@ namespace vkcv
 		uint64_t getId() const;
 		
 		/**
-		 * Returns the reference counter of a handle
+		 * @brief Returns the reference counter of a handle
 		 *
 		 * @return Reference counter
 		 */
@@ -53,80 +69,143 @@ namespace vkcv
 		Handle& operator=(const Handle& other);
 		Handle& operator=(Handle&& other) noexcept;
 		
+		/**
+		 * @brief Returns whether a handle is valid to use.
+		 *
+		 * @return True, if the handle is valid, else false.
+		 */
 		explicit operator bool() const;
+		
+		/**
+		 * @brief Returns whether a handle is invalid to use.
+		 *
+		 * @return True, if the handle is invalid, else false.
+		 */
 		bool operator!() const;
 		
 	};
 	
+	/**
+	 * @brief Stream operator to print a handle into an output
+	 * stream.
+	 *
+	 * @param[out] out Output stream
+	 * @param[in] handle
+	 * @return Output stream after printing
+	 */
 	std::ostream& operator << (std::ostream& out, const Handle& handle);
-	
-    // Handle returned for any buffer created with the core/context objects
+
+    /**
+     * @brief Handle class for buffers.
+     */
     class BufferHandle : public Handle {
     	friend class BufferManager;
 	private:
 		using Handle::Handle;
     };
-	
+
+    /**
+     * @brief Handle class for render passes.
+     */
 	class PassHandle : public Handle {
 		friend class PassManager;
 	private:
 		using Handle::Handle;
 	};
-	
+
+    /**
+     * @brief Handle class for graphics pipelines.
+     */
 	class GraphicsPipelineHandle : public Handle {
 		friend class GraphicsPipelineManager;
 	private:
 		using Handle::Handle;
 	};
 
+    /**
+     * @brief Handle class for compute pipelines.
+     */
     class ComputePipelineHandle : public Handle {
         friend class ComputePipelineManager;
     private:
         using Handle::Handle;
     };
-	
+
+    /**
+     * @brief Handle class for descriptor sets.
+     */
 	class DescriptorSetHandle : public Handle {
 		friend class DescriptorManager;
 	private:
 		using Handle::Handle;
 	};
 
+    /**
+     * @brief Handle class for descriptor set layouts.
+     */
 	class DescriptorSetLayoutHandle : public Handle {
 	    friend class DescriptorManager;
 	private:
 	    using Handle::Handle;
 	};
-	
+
+    /**
+     * @brief Handle class for samplers.
+     */
 	class SamplerHandle : public Handle {
 		friend class SamplerManager;
 	private:
 		using Handle::Handle;
 	};
 
+    /**
+     * @brief Handle class for images.
+     */
 	class ImageHandle : public Handle {
 		friend class ImageManager;
 	private:
 		using Handle::Handle;
 	public:
+		/**
+		 * @brief Returns whether the handle represents an swapchain image.
+		 *
+		 * @return True, if the handle represents a swapchain image, else false.
+		 */
 		[[nodiscard]]
 		bool isSwapchainImage() const;
 		
+		/**
+		 * @brief Creates a valid image handle to represent a swapchain image
+		 * using an optional destroy callback.
+		 *
+		 * @param[in] destroy Destroy callback (optional)
+		 * @return New swapchain image handle
+		 */
 		static ImageHandle createSwapchainImageHandle(const HandleDestroyFunction& destroy = nullptr);
 		
 	};
 
+    /**
+     * @brief Handle class for windows.
+     */
 	class WindowHandle : public Handle {
 		friend class WindowManager;
 	private:
 		using Handle::Handle;
 	};
 
+    /**
+     * @brief Handle class for swapchains.
+     */
 	class SwapchainHandle : public Handle {
 		friend class SwapchainManager;
 	private:
 		using Handle::Handle;
 	};
 
+    /**
+     * @brief Handle class for command streams.
+     */
     class CommandStreamHandle : public Handle {
         friend class CommandStreamManager;
     private:
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 3fca76f70315c0e08e404d7acd8c2010a3501c24..5d5359288d4b1b1f38bfabf062c9cc4cd0ca9ad1 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -1,54 +1,137 @@
 #pragma once
 /**
- * @authors Lars Hoerttrich
- * @file vkcv/Buffer.hpp
- * @brief class for image handles
+ * @authors Alexander Gauggel, Tobias Frisch, Lars Hoerttrich, Artur Wasmut
+ * @file vkcv/Image.hpp
+ * @brief Class for image handling.
  */
-#include "vulkan/vulkan.hpp"
+ 
+#include <vulkan/vulkan.hpp>
 
 #include "Handles.hpp"
-#include "vkcv/ImageConfig.hpp"
+#include "ImageConfig.hpp"
 
 namespace vkcv {
 	
 	class ImageManager;
 
+	/**
+	 * @brief Returns whether an image format is usable as depth buffer.
+	 *
+	 * @param format Vulkan image format
+	 * @return True, if the format is valid to use as depth buffer,
+	 * otherwise false.
+	 */
 	bool isDepthFormat(const vk::Format format);
 
+    /**
+     * @brief Class for image handling and filling data.
+     */
 	class Image {
 		friend class Core;
 	public:
+		
+		/**
+		 * @brief Returns the format of the image.
+		 *
+		 * @return Vulkan image format
+		 */
 		[[nodiscard]]
 		vk::Format getFormat() const;
 		
+		/**
+		 * @brief Returns the width of the image.
+		 *
+		 * @return Width of the image
+		 */
 		[[nodiscard]]
 		uint32_t getWidth() const;
 		
+		/**
+		 * @brief Returns the height of the image.
+		 *
+		 * @return Height of the image
+		 */
 		[[nodiscard]]
 		uint32_t getHeight() const;
 		
+		/**
+		 * @brief Returns the depth of the image.
+		 *
+		 * @return Depth of the image
+		 */
 		[[nodiscard]]
 		uint32_t getDepth() const;
 
+		/**
+		 * @brief Returns the image handle of the image.
+		 *
+		 * @return Handle of the image
+		 */
 		[[nodiscard]]
 		const vkcv::ImageHandle& getHandle() const;
 
+		/**
+		 * @brief Returns the amount of mip levels of the image.
+		 *
+		 * @return Number of mip levels
+		 */
 		[[nodiscard]]
 		uint32_t getMipCount() const;
 
+		/**
+		 * @brief Switches the image layout,
+		 * returns after operation is finished.
+		 * 
+		 * @param[in] newLayout Layout that image is switched to
+		 */
 		void switchLayout(vk::ImageLayout newLayout);
 		
+		/**
+		 * @brief Fills the image with data of a given size in bytes.
+		 * 
+		 * @param[in] data Pointer to the source data
+		 * @param[in] size Lower limit of the data size to copy in bytes,
+		 * the actual number of copied bytes is min(size, imageDataSize)
+		 */
 		void fill(const void* data, size_t size = SIZE_MAX);
+
+		/**
+		 * @brief Generates the entire mip chain from mip level zero,
+		 * returns after operation is finished
+		 */
 		void generateMipChainImmediate();
+
+		/**
+		 * @brief Records mip chain generation to command stream,
+		 * mip level zero is used as source
+		 * 
+		 * @param[out] cmdStream Command stream that the commands are recorded into
+		 */
 		void recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream);
+		
 	private:
 	    // TODO: const qualifier removed, very hacky!!!
 	    //  Else you cannot recreate an image. Pls fix.
-		ImageManager*       m_manager;
-		ImageHandle   		m_handle;
+		ImageManager* m_manager;
+		ImageHandle m_handle;
 
 		Image(ImageManager* manager, const ImageHandle& handle);
 		
+		/**
+		 * @brief Creates an image with given parameters like width, height,
+		 * depth, amount of mip levels and others.
+		 *
+		 * @param[in,out] manager Image manager
+		 * @param[in] format Vulkan image format
+		 * @param[in] width Width of the image
+		 * @param[in] height Height of the image
+		 * @param[in] depth Depth of the image
+		 * @param[in] mipCount Amount of mip levels
+		 * @param[in] supportStorage Support of storage
+		 * @param[in] supportColorAttachment Support of color attachment
+		 * @param[in] msaa MSAA mode
+		 * @return New created image
+		 */
 		static Image create(
 			ImageManager*   manager,
 			vk::Format      format,
diff --git a/include/vkcv/ImageConfig.hpp b/include/vkcv/ImageConfig.hpp
index 2e413b97be92ae771ef85342981ea0163a93ab52..d031f790622f1f0595c540c5bbcf0d8795f5fd95 100644
--- a/include/vkcv/ImageConfig.hpp
+++ b/include/vkcv/ImageConfig.hpp
@@ -1,9 +1,32 @@
 #pragma once
+/**
+ * @authors Alexander Gauggel, Tobias Frisch
+ * @file vkcv/ImageConfig.hpp
+ * @brief File to provide functions supporting the use of multisampling.
+ */
+
 #include <vulkan/vulkan.hpp>
 
 namespace vkcv {
+	
 	enum class Multisampling { None, MSAA2X, MSAA4X, MSAA8X };
 
+	/**
+	 * @brief Returns the sample count flag bits of a given
+	 * multi-sample anti-aliasing mode.
+	 *
+	 * @param[in] msaa MSAA mode
+	 * @return Sample count flag bits
+	 */
 	vk::SampleCountFlagBits msaaToVkSampleCountFlag(Multisampling msaa);
-	uint32_t                msaaToSampleCount(Multisampling msaa);
+	
+	/**
+	 * @brief Returns the amount of samples of a given
+	 * multi-sample anti-aliasing mode.
+	 *
+	 * @param msaa MSAA mode
+	 * @return Number of samples
+	 */
+	uint32_t msaaToSampleCount(Multisampling msaa);
+	
 }
diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp
index bb60561e80baadfcac4956223d9313893547068f..9d4fa86f2b42e8190e7dc57c2ad897a76f945126 100644
--- a/include/vkcv/Logger.hpp
+++ b/include/vkcv/Logger.hpp
@@ -1,9 +1,17 @@
 #pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Logger.hpp
+ * @brief Logging macro function to print line of code specific information.
+ */
 
-#include <stdio.h>
+#include <cstdio>
 
 namespace vkcv {
 	
+	/**
+	 * @brief Enum class to specify the level of logging.
+	 */
 	enum class LogLevel {
 		RAW_INFO,
 		INFO,
@@ -11,6 +19,13 @@ namespace vkcv {
 		ERROR
 	};
 	
+	/**
+	 * @brief Return the fitting output stream to print messages
+	 * of a given level of logging.
+	 *
+	 * @param[in] level Level of logging
+	 * @return Output stream (stdout or stderr)
+	 */
 	constexpr auto getLogOutput(LogLevel level) {
 		switch (level) {
 			case LogLevel::RAW_INFO:
@@ -21,6 +36,13 @@ namespace vkcv {
 		}
 	}
 	
+	/**
+	 * @brief Returns the fitting identifier for messages of
+	 * a given level of logging.
+	 *
+	 * @param[in] level Level of logging
+	 * @return Identifier of the given level of logging
+	 */
 	constexpr const char* getLogName(LogLevel level) {
 		switch (level) {
 			case LogLevel::RAW_INFO:
@@ -44,6 +66,12 @@ namespace vkcv {
 #define __PRETTY_FUNCTION__ __FUNCSIG__
 #endif
 
+/**
+ * @brief Macro-function to log formatting messages with
+ * a specific level of logging.
+ *
+ * @param[in] level Level of logging
+ */
 #define vkcv_log(level, ...) {             \
   char output_message [                    \
     VKCV_DEBUG_MESSAGE_LEN                 \
@@ -76,6 +104,12 @@ namespace vkcv {
 }
 
 #else
+/**
+ * @brief Macro-function to log formatting messages with
+ * a specific level of logging.
+ *
+ * @param[in] level Level of logging
+ */
 #define vkcv_log(level, ...) {}
 #endif
 
diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp
index f3b2b802d062a441dfb0c810154205effb7053a2..ad3e3c0dff150f5ba41859477d4bb5a53c4365f8 100644
--- a/include/vkcv/PassConfig.hpp
+++ b/include/vkcv/PassConfig.hpp
@@ -1,13 +1,22 @@
 #pragma once
+/**
+ * @authors Alexander Gauggel, Artur Wasmut, Tobias Frisch
+ * @file vkcv/PassConfig.hpp
+ * @brief Enums and structures to handle render pass configuration.
+ */
 
 #include <vector>
 #include <vulkan/vulkan.hpp>
+
 #include "ImageConfig.hpp"
 
 namespace vkcv
 {
-    enum class AttachmentLayout
-    {
+	
+	/**
+	 * @brief Enum class to specify kinds of attachment layouts.
+	 */
+    enum class AttachmentLayout {
         UNDEFINED,
         GENERAL,
 
@@ -23,31 +32,31 @@ namespace vkcv
         PRESENTATION
     };
 
-    enum class AttachmentOperation
-    {
+	/**
+	 * @brief Enum class to specify types of attachment operations.
+	 */
+    enum class AttachmentOperation {
         LOAD,
         CLEAR,
         STORE,
         DONT_CARE
     };
 
-    struct AttachmentDescription
-    {
-        AttachmentDescription(
-            AttachmentOperation store_op,
-            AttachmentOperation load_op,
-            vk::Format format) noexcept;
-
+	/**
+	 * @brief Structure to store details about an attachment of a pass.
+	 */
+    struct AttachmentDescription {
         AttachmentOperation store_operation;
         AttachmentOperation load_operation;
-
         vk::Format format;
     };
 
-    struct PassConfig
-    {
-        explicit PassConfig(std::vector<AttachmentDescription> attachments, Multisampling msaa = Multisampling::None) noexcept;
-        std::vector<AttachmentDescription> attachments{};
+	/**
+	 * @brief Structure to configure a pass for usage.
+	 */
+    struct PassConfig {
+		std::vector<AttachmentDescription> attachments;
         Multisampling msaa;
     };
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/PushConstants.hpp b/include/vkcv/PushConstants.hpp
index d974fbe6241daf948b13929305fb24aff5ec06f5..ca826ea52e9bcee72c14c26496c99937c27fb775 100644
--- a/include/vkcv/PushConstants.hpp
+++ b/include/vkcv/PushConstants.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Tobias Frisch, Alexander Gauggel
+ * @file vkcv/PushConstants.hpp
+ * @brief Class to manage push constants for pipeline recording.
+ */
 
 #include <vector>
 #include <vulkan/vulkan.hpp>
@@ -6,7 +11,10 @@
 #include "Logger.hpp"
 
 namespace vkcv {
-	
+
+    /**
+     * @brief Class to handle push constants data per drawcall.
+     */
 	class PushConstants {
 	private:
 		std::vector<uint8_t> m_data;
@@ -28,25 +36,55 @@ namespace vkcv {
 		PushConstants& operator=(const PushConstants& other) = default;
 		PushConstants& operator=(PushConstants&& other) = default;
 		
+		/**
+		 * @brief Returns the size of the data that is bound
+		 * per drawcall in bytes.
+		 *
+		 * @return Size of data per drawcall
+		 */
 		[[nodiscard]]
 		size_t getSizePerDrawcall() const {
 			return m_sizePerDrawcall;
 		}
 		
+		/**
+		 * @brief Returns the size of total data stored for
+		 * push constants in bytes
+		 *
+		 * @return Total size of data
+		 */
 		[[nodiscard]]
 		size_t getFullSize() const {
 			return m_data.size();
 		}
 		
+		/**
+		 * @brief Returns the number of drawcalls that data
+		 * is stored for.
+		 *
+		 * @return Number of drawcalls
+		 */
 		[[nodiscard]]
 		size_t getDrawcallCount() const {
 			return (m_data.size() / m_sizePerDrawcall);
 		}
 		
+		/**
+		 * @brief Clears the data for all drawcalls currently.
+		 * stored.
+		*/
 		void clear() {
 			m_data.clear();
 		}
 		
+		/**
+		 * @brief Appends data for a single drawcall to the
+		 * storage with a given type.
+		 * 
+		 * @tparam T Type of data (must match the size per drawcall)
+		 * @param[in] value Data to append
+		 * @return True, if operation was successfull, otherwise false
+		 */
 		template<typename T = uint8_t>
 		bool appendDrawcall(const T& value) {
 			if (sizeof(T) != m_sizePerDrawcall) {
@@ -61,24 +99,53 @@ namespace vkcv {
 			return true;
 		}
 		
+		/**
+		 * @brief Returns the data of the drawcall by a given index
+		 * as reference.
+		 * 
+		 * @tparam T Type of data
+		 * @param[in] index Index of the drawcall
+		 * @return Drawcall data
+		 */
 		template<typename T = uint8_t>
 		T& getDrawcall(size_t index) {
 			const size_t offset = (index * m_sizePerDrawcall);
 			return *reinterpret_cast<T*>(m_data.data() + offset);
 		}
 		
+		/**
+		 * @brief Returns the data of the drawcall by a given index
+		 * as const reference.
+		 *
+		 * @tparam T Type of data
+		 * @param[in] index Index of the drawcall
+		 * @return Drawcall data
+		 */
 		template<typename T = uint8_t>
 		const T& getDrawcall(size_t index) const {
 			const size_t offset = (index * m_sizePerDrawcall);
 			return *reinterpret_cast<const T*>(m_data.data() + offset);
 		}
 		
+		/**
+		 * @brief Returns the data of the drawcall by a given index
+		 * as a pointer.
+		 * 
+		 * @param[in] index Index of the drawcall
+		 * @return Drawcall data
+		 */
 		[[nodiscard]]
 		const void* getDrawcallData(size_t index) const {
 			const size_t offset = (index * m_sizePerDrawcall);
 			return reinterpret_cast<const void*>(m_data.data() + offset);
 		}
 		
+		/**
+		 * @brief Returns the pointer to the entire drawcall data which
+		 * might be nullptr if the data is empty.
+		 *
+		 * @return Pointer to the data
+		 */
 		[[nodiscard]]
 		const void* getData() const {
 			if (m_data.empty()) {
diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp
index 9d219c9d7a308cac29bec1580bd8894a70f68fb3..04a5d8a0a59b2655673d073a7a36467df0ab8a17 100644
--- a/include/vkcv/QueueManager.hpp
+++ b/include/vkcv/QueueManager.hpp
@@ -1,10 +1,27 @@
 #pragma once
+/**
+ * @authors Sebastian Gaida, Tobias Frisch, Alexander Gauggel
+ * @file vkcv/QueueManager.hpp
+ * @brief Types to manage queues of a device.
+ */
+ 
 #include <vulkan/vulkan.hpp>
 
 namespace vkcv {
 
-	enum class QueueType { Compute, Transfer, Graphics, Present };
+	/**
+	 * @brief Enum class to represent types of queues.
+	 */
+	enum class QueueType {
+		Compute,
+		Transfer,
+		Graphics,
+		Present
+	};
 
+	/**
+	 * @brief Structure to represent a queue and its details.
+	 */
 	struct Queue {
 		int familyIndex;
 		int queueIndex;
@@ -12,40 +29,69 @@ namespace vkcv {
 		vk::Queue handle;
 	};
 	
+	/**
+	 * @brief Class to manage queues of a device.
+	 */
 	class QueueManager {
 	public:
+		/**
+		 * @brief Creates a queue manager with the given pairs of queues.
+		 *
+		 * @param[in,out] device Vulkan device that holds the queues
+		 * @param[in] queuePairsGraphics Graphic queue pairs of queueFamily and queueIndex
+		 * @param[in] queuePairsCompute Compute queue pairs of queueFamily and queueIndex
+		 * @param[in] queuePairsTransfer Transfer queue pairs of queueFamily and queueIndex
+		 * @return New queue manager with the specified queue pairs
+		 */
 		static QueueManager create(vk::Device device,
-                            std::vector<std::pair<int, int>> &queuePairsGraphics,
-                            std::vector<std::pair<int, int>> &queuePairsCompute,
-                            std::vector<std::pair<int, int>> &queuePairsTransfer);
-
+								   const std::vector<std::pair<int, int>> &queuePairsGraphics,
+								   const std::vector<std::pair<int, int>> &queuePairsCompute,
+								   const std::vector<std::pair<int, int>> &queuePairsTransfer);
+		
+		/**
+		 * @brief Returns the default queue with present support.
+		 * Recommended to use the present queue in the swapchain.
+		 *
+		 * @return Default present queue
+		 */
         [[nodiscard]]
         const Queue &getPresentQueue() const;
-		
+
+		/**
+		 * @brief Returns all queues with the graphics flag.
+		 *
+		 * @return Vector of graphics queues
+		 */
 		[[nodiscard]]
 		const std::vector<Queue> &getGraphicsQueues() const;
-		
+
+		/**
+		 * @brief Returns all queues with the compute flag.
+		 *
+		 * @return Vector of compute queues
+		 */
 		[[nodiscard]]
         const std::vector<Queue> &getComputeQueues() const;
-		
+
+		/**
+		 * @brief Returns all queues with the transfer flag.
+		 *
+		 * @return Vector of transfer queues
+		 */
 		[[nodiscard]]
         const std::vector<Queue> &getTransferQueues() const;
-
-        static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
-                const std::vector<float> &queuePriorities,
-                const std::vector<vk::QueueFlagBits> &queueFlags,
-                std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
-                std::vector<std::pair<int, int>> &queuePairsGraphics,
-                std::vector<std::pair<int, int>> &queuePairsCompute,
-                std::vector<std::pair<int, int>> &queuePairsTransfer);
-
+		
 		/**
-		 * checks for surface support in the queues
-		 * @param physicalDevice to get the Queues
-		 * @param surface that needs to checked
-		 * @return
+		 * @brief Checks for presenting support of a given surface
+		 * in the queues and returns the queue family index of the
+		 * supporting queue.
+		 *
+		 * @param[in] physicalDevice Vulkan physical device
+		 * @param[in] surface Surface
+		 * @return Queue family index of the supporting present queue
 		 */
-		static uint32_t checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice, vk::SurfaceKHR &surface);
+		static uint32_t checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice,
+											const vk::SurfaceKHR &surface);
 
     private:
         std::vector<Queue> m_graphicsQueues;
@@ -54,6 +100,9 @@ namespace vkcv {
 		
 		size_t m_presentIndex;
 
-        QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex);
+        QueueManager(std::vector<Queue>&& graphicsQueues,
+					 std::vector<Queue>&& computeQueues,
+					 std::vector<Queue>&& transferQueues,
+					 size_t presentIndex);
 	};
 }
diff --git a/include/vkcv/Result.hpp b/include/vkcv/Result.hpp
index b78e444de9040f2982122d9242f584c7f9c340cf..328a44fa58c9b6303af872d7787cc1bcb7230256 100644
--- a/include/vkcv/Result.hpp
+++ b/include/vkcv/Result.hpp
@@ -1,12 +1,18 @@
 #pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Result.hpp
+ * @brief Enum to represent result values of function which can fail.
+ */
 
 namespace vkcv {
-	
+
+    /**
+     * @brief Enum class to specify the result of a function call.
+     */
 	enum class Result {
-		
 		SUCCESS = 0,
 		ERROR = 1
-		
 	};
 	
 }
diff --git a/include/vkcv/Sampler.hpp b/include/vkcv/Sampler.hpp
index e4f10cd9d3f1dd60021e62842acaa07d2aefb5ce..c65ef8218ff209e6eeaf0e45f9309e21d85e782e 100644
--- a/include/vkcv/Sampler.hpp
+++ b/include/vkcv/Sampler.hpp
@@ -1,17 +1,31 @@
 #pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Sampler.hpp
+ * @brief Enums for different sampler attributes.
+ */
 
 namespace vkcv {
 
+    /**
+     * @brief Enum class to specify a samplers type to filter during access.
+     */
 	enum class SamplerFilterType {
 		NEAREST = 1,
 		LINEAR = 2
 	};
-	
+
+    /**
+     * @brief Enum class to specify a samplers mode to access mipmaps.
+     */
 	enum class SamplerMipmapMode {
 		NEAREST = 1,
 		LINEAR = 2
 	};
-	
+
+    /**
+     * @brief Enum class to specify a samplers mode to access via address space.
+     */
 	enum class SamplerAddressMode {
 		REPEAT = 1,
 		MIRRORED_REPEAT = 2,
@@ -19,7 +33,10 @@ namespace vkcv {
 		MIRROR_CLAMP_TO_EDGE = 4,
 		CLAMP_TO_BORDER = 5
 	};
-	
+
+    /**
+     * @brief Enum class to specify a samplers color beyond a textures border.
+     */
 	enum class SamplerBorderColor {
 		INT_ZERO_OPAQUE = 1,
 		INT_ZERO_TRANSPARENT = 2,
diff --git a/include/vkcv/ShaderProgram.hpp b/include/vkcv/ShaderProgram.hpp
index d39f0da436089830fc90e5178b056d0be2cae910..c815834a3d7a948df3307769f34abe94cbd2ff22 100644
--- a/include/vkcv/ShaderProgram.hpp
+++ b/include/vkcv/ShaderProgram.hpp
@@ -1,8 +1,8 @@
 #pragma once
 /**
- * @authors Simeon Hermann, Leonie Franken
- * @file src/vkcv/ShaderProgram.hpp
- * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
+ * @authors Artur Wasmut, Leonie Franken, Tobias Frisch, Simeon Hermann, Alexander Gauggel, Mark Mints
+ * @file vkcv/ShaderProgram.hpp
+ * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline.
  */
 
 #include <unordered_map>
@@ -12,18 +12,16 @@
 #include <filesystem>
 #include <vulkan/vulkan.hpp>
 #include <spirv_cross.hpp>
+
 #include "VertexLayout.hpp"
 #include "DescriptorConfig.hpp"
 #include "ShaderStage.hpp"
 
 namespace vkcv {
 
-    struct Shader
-    {
-        std::vector<char> shaderCode;
-        ShaderStage shaderStage;
-    };
-
+    /**
+     * @brief Class to manage and reflect shaders as a program.
+     */
 	class ShaderProgram
 	{
     public:
@@ -31,47 +29,78 @@ namespace vkcv {
         ~ShaderProgram() = default; // dtor
 
         /**
-        * Adds a shader into the shader program.
-        * The shader is only added if the shader program does not contain the particular shader stage already.
-        * Contains: (1) reading of the code, (2) creation of a shader module, (3) creation of a shader stage, (4) adding to the shader stage list, (5) destroying of the shader module
-        * @param[in] flag that signals the respective shaderStage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
-        * @param[in] relative path to the shader code (e.g. "../../../../../shaders/vert.spv")
-        */
-        bool addShader(ShaderStage shaderStage, const std::filesystem::path &shaderPath);
+         * @brief Adds a shader into the shader program.
+         * The shader is only added if the shader program does not contain
+         * the particular shader stage already.
+         * Contains:
+         * (1) reading the SPIR-V file,
+         * (2) creating a shader module,
+         * (3) creating a shader stage,
+         * (4) adding to the shader stage list,
+         * (5) destroying of the shader module
+         *
+         * @param[in] stage The stage of the shader
+         * @param[in] path Path to the SPIR-V shader file
+         */
+        bool addShader(ShaderStage stage, const std::filesystem::path &path);
 
         /**
-        * Returns the shader program's shader of the specified shader.
-        * Needed for the transfer to the pipeline.
-        * @return Shader object consisting of buffer with shader code and shader stage enum
-        */
-        const Shader &getShader(ShaderStage shaderStage) const;
+         * @brief Returns the shader binary of a specified stage from the program.
+         * Needed for the transfer to the pipeline.
+         *
+         * @param[in] stage The stage of the shader
+         * @return Shader code binary of the given stage
+         */
+        const std::vector<uint32_t> &getShaderBinary(ShaderStage stage) const;
 
-        bool existsShader(ShaderStage shaderStage) const;
+		/**
+		 * @brief Returns whether a shader exists in the program for a
+		 * specified shader stage.
+		 *
+		 * @param[in] stage The stage of the shader
+		 * @return True, if a shader exists for the stage, else false
+		 */
+        bool existsShader(ShaderStage stage) const;
 
+		/**
+		 * @brief Returns the vertex attachments for the program and its
+		 * shader stages.
+		 *
+		 * @return Vertex attachments
+		 */
         const std::vector<VertexAttachment> &getVertexAttachments() const;
-		size_t getPushConstantSize() const;
+		
+		/**
+		 * @brief Returns the size of the programs push constants.
+		 *
+		 * @return Size of push constants
+		 */
+		size_t getPushConstantsSize() const;
 
 		/**
-		 * Returns the reflected descriptor sets/layouts/bindings in a map of maps.
-		 * First uint32_t serves as descriptor SET id.
-		 * Second uint32_t serves as the descriptor set's BINDING id.
-		 * @return
+		 * @brief Returns the reflected descriptor set bindings mapped via
+		 * their descriptor set id.
+		 *
+		 * @return Reflected descriptor set bindings
 		 */
-		const std::unordered_map<uint32_t, std::unordered_map<uint32_t, DescriptorBinding>>& getReflectedDescriptors() const;
+		const std::unordered_map<uint32_t, DescriptorBindings>& getReflectedDescriptors() const;
 
 	private:
 	    /**
-	     * Called after successfully adding a shader to the program.
+	     * @brief Called after successfully adding a shader to the program.
 	     * Fills vertex input attachments and descriptor sets (if present).
-	     * @param shaderStage the stage to reflect data from
+	     *
+	     * @param[in] shaderStage the stage to reflect data from
 	     */
         void reflectShader(ShaderStage shaderStage);
 
-        std::unordered_map<ShaderStage, Shader> m_Shaders;
+        std::unordered_map<ShaderStage, std::vector<uint32_t> > m_Shaders;
 
         // contains all vertex input attachments used in the vertex buffer
-        std::vector<VertexAttachment> m_VertexAttachments;
-        std::unordered_map<uint32_t, std::unordered_map<uint32_t, DescriptorBinding>> m_DescriptorSets;
-		size_t m_pushConstantSize = 0;
+        VertexAttachments m_VertexAttachments;
+        std::unordered_map<uint32_t, DescriptorBindings> m_DescriptorSets;
+		size_t m_pushConstantsSize = 0;
+
 	};
+
 }
diff --git a/include/vkcv/ShaderStage.hpp b/include/vkcv/ShaderStage.hpp
index 73cd6f5f37cc96cce384952080e32904915eee7b..39b250e80be79cbb0f39261e69ab0d80a71d4f31 100644
--- a/include/vkcv/ShaderStage.hpp
+++ b/include/vkcv/ShaderStage.hpp
@@ -1,9 +1,17 @@
 #pragma once
+/**
+ * @authors Artur Wasmut, Simeon Hermann, Tobias Frisch, Vanessa Karolek, Alexander Gauggel, Lars Hoerttrich
+ * @file vkcv/ShaderStage.hpp
+ * @brief Enum and struct to operate with multiple shader stages.
+ */
 
 #include <vulkan/vulkan.hpp>
 
 namespace vkcv {
 	
+	/**
+	 * @brief Enum class to specify the stage of a shader.
+	 */
 	enum class ShaderStage : VkShaderStageFlags {
 		VERTEX = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eVertex),
 		TESS_CONTROL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl),
@@ -72,4 +80,5 @@ namespace vkcv {
 	constexpr ShaderStages operator~(ShaderStage stage) noexcept {
 		return ~(ShaderStages(stage));
 	}
+	
 }
diff --git a/include/vkcv/Surface.hpp b/include/vkcv/Surface.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..47862b9c49661f434b64f9def17037cc5bcc110c
--- /dev/null
+++ b/include/vkcv/Surface.hpp
@@ -0,0 +1,107 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Surface.hpp
+ * @brief Class to manage the surface used by a swapchain.
+ */
+
+#include <vulkan/vulkan.hpp>
+
+#include "Context.hpp"
+#include "Window.hpp"
+
+namespace vkcv {
+	
+	const uint32_t MIN_SURFACE_SIZE = 2;
+
+    /**
+     * @brief Class to handle surfaces to use with a swapchain.
+     */
+	class Surface final {
+	private:
+		friend class Swapchain;
+		friend class SwapchainManager;
+		
+		const Context *m_Context;
+		vk::SurfaceKHR m_Handle;
+		uint32_t m_PresentQueueIndex;
+		vk::Extent2D m_Extent;
+		vk::Format m_Format;
+		vk::ColorSpaceKHR m_ColorSpace;
+		
+		Surface(const Context &context,
+				const vk::SurfaceKHR &handle,
+				uint32_t presentQueueIndex,
+				const vk::Extent2D &extent,
+				vk::Format format,
+				vk::ColorSpaceKHR colorSpace);
+		
+		vk::SwapchainKHR createVulkanSwapchain(const Window &window,
+											   const vk::SwapchainKHR &oldSwapchain);
+		
+	public:
+		Surface(const Surface& other) = default;
+		
+		Surface(Surface&& other) noexcept;
+		
+		Surface& operator=(const Surface& other) = default;
+		
+		Surface& operator=(Surface&& other) noexcept;
+		
+		~Surface();
+		
+		/**
+		 * @brief Creates a surface via a window and a current context.
+		 *
+		 * @param[in] window Window
+		 * @param[in] context Context
+		 * @return Created surface
+		 */
+		static Surface create(const Window &window,
+							  const Context &context);
+		
+		/**
+         * @brief Returns the Vulkan-Surface of the object.
+         *
+         * @return Current Vulkan-Surface
+         */
+		[[nodiscard]]
+		vk::SurfaceKHR getSurface() const;
+		
+		/**
+		 * @brief Returns the queue index of the present queue
+		 * for the surface.
+		 *
+		 * @return Present queue index
+		 */
+		[[nodiscard]]
+		uint32_t getPresentQueueIndex() const;
+		
+		/**
+		 * @brief Returns the extent of the surfaces resolution.
+		 *
+		 * @return Extent of surface
+		 */
+		[[nodiscard]]
+		const vk::Extent2D& getExtent() const;
+		
+		/**
+		 * @brief Returns the image format of the surface to
+		 * present an image.
+		 *
+		 * @return Vulkan image format
+		 */
+		[[nodiscard]]
+		vk::Format getFormat() const;
+		
+		/**
+		 * @brief Returns the color space of the surface.
+		 *
+		 * @return Color space
+		 */
+		[[nodiscard]]
+		vk::ColorSpaceKHR getColorSpace() const;
+		
+	};
+
+}
diff --git a/include/vkcv/Swapchain.hpp b/include/vkcv/Swapchain.hpp
index c7741c652926fad5d581ecf7465ed74af9e2db37..9380b97ca73e46d53e7dcfbb8ba804004698b5b3 100644
--- a/include/vkcv/Swapchain.hpp
+++ b/include/vkcv/Swapchain.hpp
@@ -1,77 +1,64 @@
 #pragma once
-#include "vulkan/vulkan.hpp"
-#include "Context.hpp"
-#include "vkcv/Window.hpp"
+/**
+ * @authors Sebastian Gaida, Tobias Frisch
+ * @file vkcv/Swapchain.hpp
+ * @brief Class to manage the state of a swapchain and its transitions.
+ */
 
 #include <atomic>
+#include <vulkan/vulkan.hpp>
+
+#include "Context.hpp"
+#include "Surface.hpp"
+#include "Window.hpp"
 
 namespace vkcv
 {
-	
-	const uint32_t MIN_SWAPCHAIN_SIZE = 2;
-	
+
+    /**
+     * @brief Class to handle swapchains using a context.
+     */
     class Swapchain final {
     private:
     	friend class Core;
     	friend class Window;
     	friend class SwapchainManager;
-
-        struct Surface
-        {
-            vk::SurfaceKHR handle;
-            std::vector<vk::SurfaceFormatKHR> formats;
-            vk::SurfaceCapabilitiesKHR capabilities;
-            std::vector<vk::PresentModeKHR> presentModes;
-			uint32_t presentQueueIndex;
-        };
-        
+     
+		const Context *m_Context;
         Surface m_Surface;
-
         vk::SwapchainKHR m_Swapchain;
-        vk::Format m_Format;
-        vk::ColorSpaceKHR m_ColorSpace;
-        vk::PresentModeKHR m_PresentMode;
-		uint32_t m_ImageCount;
-	
-		vk::Extent2D m_Extent;
-	
 		std::atomic<bool> m_RecreationRequired;
 
 		/**
-		 * Constructor of a SwapChain object
-		 * glfw is not initialized in this class because ist must be sure that there exists a context first
-		 * glfw is already initialized by the window class
-		 * @param surface used by the swapchain
-		 * @param swapchain to show images in the window
-		 * @param format of the swapchain
-		 * @param colorSpace of the swapchain
-		 * @param presentMode of the swapchain
-		 * @param imageCount of the swapchain
-		 * @param extent of the swapchain
+		 * @brief Constructor of the swapchain with the current context,
+		 * a surface and a given vulkan swapchain object.
+		 *
+		 * @param[in,out] context Current context
+		 * @param[in] surface used by the swapchain
+		 * @param[in,out] swapchain to show images in the window
 		 */
-        Swapchain(const Surface &surface,
-                  vk::SwapchainKHR swapchain,
-                  vk::Format format,
-                  vk::ColorSpaceKHR colorSpace,
-                  vk::PresentModeKHR presentMode,
-                  uint32_t imageCount,
-				  vk::Extent2D extent) noexcept;
+        Swapchain(const Context &context,
+				  const Surface &surface,
+                  vk::SwapchainKHR swapchain) noexcept;
 	
 		/**
-		 * checks if the update flag is true
-		 * @return if an update is needed
+		 * @brief Checks whether the swapchain needs to be recreated.
+		 *
+		 * @return True, if the swapchain should be updated,
+		 * otherwise false.
 		 */
 		bool shouldUpdateSwapchain() const;
 	
 		/**
-		 * recreates the swapchain
-		 * context
-		 * window
+		 * @brief Updates and recreates the swapchain.
+		 *
+		 * @param[in,out] context that holds the device to recreate the swapchain
+		 * @param[in] window that the new swapchain gets bound to
 		 */
 		void updateSwapchain(const Context &context, const Window &window);
 	
 		/**
-		 * signal that the swapchain needs to be recreated
+		 * @brief Signals the swapchain to be recreated.
 		 */
 		void signalSwapchainRecreation();
 
@@ -79,6 +66,8 @@ namespace vkcv
     	Swapchain(const Swapchain& other);
 
         /**
+         * @brief Returns the vulkan swapchain object of the swapchain.
+         *
          * @return The swapchain linked with the #SwapChain class
          * @note The reference to our Swapchain variable is needed for the recreation step
          */
@@ -86,48 +75,61 @@ namespace vkcv
         const vk::SwapchainKHR& getSwapchain() const;
 
         /**
-         * gets the current surface object
-         * @return current surface
+         * @brief Returns the current surface of the swapchain.
+         *
+         * @return Current surface
          */
         [[nodiscard]]
-        vk::SurfaceKHR getSurface() const;
+        const Surface& getSurface() const;
 
         /**
-         * gets the chosen swapchain format
-         * @return gets the chosen swapchain format
+         * @brief Returns the image format for the current surface
+         * of the swapchain.
+         *
+         * @return Swapchain image format
          */
         [[nodiscard]]
         vk::Format getFormat() const;
 
         /**
-         * creates a swap chain object out of the given window and the given context
-         * @param window a wrapper that represents a glfw window
-         * @param context of the application
-         * @return returns an object of swapChain
+         * @brief Creates a swapchain for a specific window and
+         * a given context.
+         *
+         * @param[in,out] window Window
+         * @param[in,out] context Context
+         * @return New created swapchain
          */
         static Swapchain create(const Window &window, const Context &context);
 
         /**
-         * Destructor of SwapChain
+         * Destructor of thw swapchain.
          */
         virtual ~Swapchain();
 
 		/**
-		 * @return number of images in swapchain
+		 * @brief Returns the amount of images for the swapchain.
+		 *
+		 * @return Number of images
 		*/
 		uint32_t getImageCount() const;
 	
         /**
-         * @return the 2d extent of the swapchain
+         * @brief Returns the extent from the current surface of
+         * the swapchain.
+         *
+         * @return Extent of the swapchains surface
          */
         [[nodiscard]]
 		const vk::Extent2D& getExtent() const;
 
 		/**
-		 * @return the familyQueueIndex for the surface
+		 * @brief Returns the present queue index to be used with
+		 * the swapchain and its current surface.
+		 *
+		 * @return Present queue family index
 		 */
 		[[nodiscard]]
-		const uint32_t& getPresentQueueIndex() const;
+		uint32_t getPresentQueueIndex() const;
 
 	};
     
diff --git a/include/vkcv/SyncResources.hpp b/include/vkcv/SyncResources.hpp
index c41019cc46ee1375a83323a6ecc877ecc1c1727a..1683855b6b4f9046b0af5fb2df65f3bca895da2a 100644
--- a/include/vkcv/SyncResources.hpp
+++ b/include/vkcv/SyncResources.hpp
@@ -1,15 +1,59 @@
 #pragma once
+/**
+ * @authors Alexander Gauggel, Tobias Frisch
+ * @file vkcv/SyncResources.hpp
+ * @brief Support functions to deal with synchronization resources.
+ */
+
 #include <vulkan/vulkan.hpp>
 
 namespace vkcv {
+	
+	/**
+	 * @brief Structure to store vulkan resources for presenting
+	 * with a pipeline.
+	 */
 	struct SyncResources {
-		vk::Semaphore	renderFinished;
-		vk::Semaphore	swapchainImageAcquired;
-		vk::Fence		presentFinished;
+		vk::Semaphore renderFinished;
+		vk::Semaphore swapchainImageAcquired;
+		vk::Fence presentFinished;
 	};
 
-	SyncResources	createSyncResources(const vk::Device &device);
-	void			destroySyncResources(const vk::Device &device, const SyncResources &resources);
-	vk::Fence		createFence(const vk::Device &device);
-	void			waitForFence(const vk::Device& device, const vk::Fence fence);
+	/**
+	 * @brief Creates new synchronization resources for drawing
+	 * and presenting with a swapchain.
+	 *
+	 * @param[in,out] device Vulkan-Device
+	 * @return New created synchronization resources
+	 */
+	SyncResources createSyncResources(const vk::Device &device);
+	
+	/**
+	 * @brief Destroys the synchronization resources with a
+	 * given device.
+	 *
+	 * @param[in,out] device Vulkan-Device
+	 * @param[in,out] resources Synchronizazion resources
+	 */
+	void destroySyncResources(const vk::Device &device,
+							  const SyncResources &resources);
+	
+	/**
+	 * @brief Creates a new fence with a given device and
+	 * returns it.
+	 *
+	 * @param[in,out] device Vulkan-Device
+	 * @return New created fence
+	 */
+	vk::Fence createFence(const vk::Device &device);
+	
+	/**
+	 * @brief Calls a given device to wait for a specific fence.
+	 *
+	 * @param[in,out] device Vulkan-Device
+	 * @param[in] fence Vulkan-Fence
+	 */
+	void waitForFence(const vk::Device& device,
+					  const vk::Fence& fence);
+	
 }
\ No newline at end of file
diff --git a/include/vkcv/VertexLayout.hpp b/include/vkcv/VertexLayout.hpp
index 0600b99a24a327605e89b2e8ec304c20dbf7ad2e..330be708525b3e1a90e15919abb9f3f2f2ea1729 100644
--- a/include/vkcv/VertexLayout.hpp
+++ b/include/vkcv/VertexLayout.hpp
@@ -1,11 +1,21 @@
 #pragma once
+/**
+ * @authors Alexander Gauggel, Artur Wasmut, Mara Vogt, Susanne Dötsch,
+ *          Trevor Hollmann, Leonie Franken, Simeon Hermann, Tobias Frisch
+ * @file vkcv/VertexLayout.hpp
+ * @brief Structures to handle vertex layout, bindings and attachments.
+ */
 
 #include <vector>
 #include <iostream>
 #include <string>
 
-namespace vkcv{
-    enum class VertexAttachmentFormat{
+namespace vkcv {
+	
+	/**
+	 * @brief Enum class to specify the format of vertex attributes.
+	 */
+    enum class VertexAttachmentFormat {
         FLOAT,
         FLOAT2,
         FLOAT3,
@@ -16,51 +26,65 @@ namespace vkcv{
         INT4
     };
 
+	/**
+	 * @brief Returns the size in bytes of a vertex with a
+	 * given vertex format.
+	 *
+	 * @param[in] format Vertex format
+	 * @return Size in bytes
+	 */
 	uint32_t getFormatSize(VertexAttachmentFormat format);
 
-    struct VertexAttachment{
-        friend struct VertexBinding;
-        /**
-         * Describes an individual vertex input attribute/attachment.
-         * @param inputLocation its location in the vertex shader.
-         * @param name the name referred to in the shader.
-         * @param format the format (and therefore, the size) this attachment is in.
-         * The offset is calculated when a collection of attachments forms a binding, hence the friend declaration.
-         */
-        VertexAttachment(uint32_t inputLocation, const std::string &name, VertexAttachmentFormat format) noexcept;
-        VertexAttachment() = delete;
-
-        uint32_t                inputLocation;
-        std::string             name;
-        VertexAttachmentFormat  format;
-        uint32_t                offset;
+	/**
+	 * @brief Structure to store the details of a vertex input attachment.
+	 *
+	 * Describes an individual vertex input attribute/attachment. The offset
+	 * is calculated when a collection of attachments forms a binding.
+	 */
+    struct VertexAttachment {
+        uint32_t inputLocation;
+        std::string name;
+        VertexAttachmentFormat format;
+        uint32_t offset;
     };
-
-    struct VertexBinding{
-        /**
-         * Describes all vertex input attachments _one_ buffer contains to create a vertex buffer binding.
-         * NOTE: multiple vertex layouts may contain various (mutually exclusive) vertex input attachments
-         * to form one complete vertex buffer binding!
-         * @param bindingLocation its entry in the buffers that make up the whole vertex buffer.
-         * @param attachments the vertex input attachments this specific buffer layout contains.
-         */
-        VertexBinding(uint32_t bindingLocation, const std::vector<VertexAttachment> &attachments) noexcept;
-        VertexBinding() = delete;
-
-        uint32_t                        bindingLocation;
-        uint32_t                        stride;
-        std::vector<VertexAttachment>   vertexAttachments;
+	
+	typedef std::vector<VertexAttachment> VertexAttachments;
+	
+	/**
+	 * @brief Structure to store the details of a vertex buffer binding.
+	 *
+	 * Describes all vertex input attachments _one_ buffer contains to create
+	 * a vertex buffer binding. NOTE: multiple vertex layouts may contain
+	 * various (mutually exclusive) vertex input attachments to form one
+	 * complete vertex buffer binding!
+	 */
+    struct VertexBinding {
+        uint32_t bindingLocation;
+        uint32_t stride;
+		VertexAttachments vertexAttachments;
     };
+	
+	/**
+	 * Creates a vertex binding with given parameters and calculates its strides
+	 * depending on its attachments.
+	 *
+	 * @param[in] bindingLocation Its entry in the buffers that make up the whole vertex buffer.
+	 * @param[in] attachments The vertex input attachments this specific buffer layout contains.
+	 * @return Vertex buffer binding with calculated stride
+	 */
+	VertexBinding createVertexBinding(uint32_t bindingLocation, const VertexAttachments &attachments);
+	
+	typedef std::vector<VertexBinding> VertexBindings;
 
-    struct VertexLayout{
-        /**
-         * Describes the complete layout of one vertex, e.g. all of the vertex input attachments used,
-         * and all of the buffer bindings that refer to the attachments (for when multiple buffers are used).
-         * @param bindings bindings the complete vertex buffer is comprised of.
-         */
-        VertexLayout() noexcept;
-        VertexLayout(const std::vector<VertexBinding> &bindings) noexcept;
-
-        std::vector<VertexBinding> vertexBindings;
+	/**
+	 * @brief Structure to store the details of a vertex layout.
+	 *
+	 * Describes the complete layout of one vertex, e.g. all of the vertex input
+	 * attachments used, and all of the buffer bindings that refer to the attachments
+	 * (for when multiple buffers are used).
+	 */
+    struct VertexLayout {
+		VertexBindings vertexBindings;
     };
+	
 }
diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp
index cef735632689cdd119b694674e9ac7af67471a3c..d1db4bf438b95e9c96824bb6676a1d8bf020a35f 100644
--- a/include/vkcv/Window.hpp
+++ b/include/vkcv/Window.hpp
@@ -1,6 +1,14 @@
 #pragma once
+/**
+ * @authors Tobias Frisch, Sebastian Gaida, Vanessa Karolek, Artur Wasmut
+ * @file vkcv/Window.hpp
+ * @brief Class to represent and manage a window with its input.
+ */
+
+#ifndef NOMINMAX
+#define NOMINMAX 1
+#endif
 
-#define NOMINMAX
 #include <algorithm>
 #include <string>
 
@@ -11,6 +19,9 @@ struct GLFWwindow;
 
 namespace vkcv {
 
+    /**
+     * @brief Class to handle a window.
+     */
     class Window {
 		friend class WindowManager;
 		friend class SwapchainManager;
@@ -25,12 +36,13 @@ namespace vkcv {
 
     public:
     	/**
-    	 * creates an uninitialized #Window
+    	 * @brief Constructor of an uninitialized #Window
     	 */
     	Window();
     	
     	/**
-    	 * creates a #Window with the parameters
+    	 * @brief Constructor of a #Window with an optional width,
+    	 * height and resizable attribute.
     	 *
          * @param[in] title title of the window
          * @param[in] width width of the window (optional)
@@ -40,55 +52,56 @@ namespace vkcv {
     	explicit Window(const char* title, int width = -1, int height = -1, bool resizable = false);
 	
 		/**
-		* Copy-constructor of #Window
+		* @brief Copy-constructor of a #Window
 		*
-		* @param other Other instance of #Window
+		* @param[in] other Other instance of #Window
 		*/
 		Window(const Window& other) = delete;
 	
 		/**
-		* Copy-operator of #Window
+		* @brief Copy-operator of a #Window
 		*
-		* @param other Other instance of #Window
+		* @param[in] other Other instance of #Window
 		* @return Reference to itself
 		*/
 		Window &operator=(const Window &other) = delete;
         
         /**
-         * checks if the window is still open, or the close event was called
-         * This function should be changed/removed later on
-         * @return bool if the window is still open
+         * @brief Checks if the window is still open, or the close event was called.
+         * TODO: This function should be changed/removed later on
+         *
+         * @return True, if the window is still open, else false
          */
         [[nodiscard]]
         bool isOpen() const;
 
 		/**
-		 * gets the currently focused window and returns it
-		 * only accessible to WindowManager
-		 * @return
+		 * @brief Returns the currently focused window.
+		 * TODO: only accessible to WindowManager
+		 *
+		 * @return Current window in focus
 		 */
 		static Window& getFocusedWindow();
 		
 		/**
-		 * checks if any GLFWWindows are open
-		 * @return bool if a window is open
+		 * @brief Checks if any windows are active and open.
+		 *
+		 * @return True, if any window is open, else false
 		 */
 		static bool hasOpenWindow();
 
         /**
-         * polls all events on the GLFWwindow
+         * @brief Polls all events on the active windows.
          */
         static void pollEvents();
 		
 		/**
+		 * @brief Returns the required extensions to use GLFW windows with Vulkan.
 		 *
-		 * @return
+		 * @return Required surface extensions
 		 */
 		static const std::vector<std::string>& getExtensions();
-
-        /**
-         * basic events of the window
-         */
+		
         event< int, int, int> e_mouseButton;
         event< double, double > e_mouseMove;
         event< double, double > e_mouseScroll;
@@ -98,60 +111,63 @@ namespace vkcv {
         event< int > e_gamepad;
 
         /**
-         * returns the current window
-         * @return window handle
+         * @brief Returns the GLFW window handle.
+         *
+         * @return GLFW window handle
          */
         [[nodiscard]]
         GLFWwindow *getWindow() const;
         
         /**
-         * gets the window title
-         * @return string with window title
+         * @brief Returns the title of the window.
+         *
+         * @return Window title
          */
         [[nodiscard]]
         const std::string& getTitle() const;
 
         /**
-         * gets the window width
-         * @return int with window width
+         * @brief Returns the width of the window.
+         *
+         * @return Window width
          */
         [[nodiscard]]
         int getWidth() const;
 
         /**
-         * gets the window height
-         * @return int with window height
+         * @brief Returns the height of the window.
+         *
+         * @return Window height
          */
         [[nodiscard]]
         int getHeight() const;
         
         /**
-         * is the window resizable
-         * @return bool with window resizable
+         * @brief Returns whether the window is resizable or not.
+         *
+         * @return True, if the window is resizable, else false
          */
         [[nodiscard]]
         bool isResizable() const;
 
         /**
-         * Destructor of #Window, terminates GLFW
+         * @brief Destructor of the window which terminates GLFW in case
+         * of the last window got destroyed.
          */
         virtual ~Window();
 
         /**
-         * destroys the window
-         */
-		//void destroyWindow();
-
-        /**
-         * gets the windows framebuffer size
-         * @param width
-         * @param height
+         * @brief Requests the windows framebuffer size.
+         *
+         * @param[out] width
+         * @param[out] height
          */
         void getFramebufferSize(int& width, int& height) const;
 
         /**
-         * gets the SwapchainHandle corresponding to the swapchain of the window
-         * @return
+         * @brief Retruns the handle of the swapchain in use by the window.
+         *
+         * @return Swapchain handle
          */
         SwapchainHandle getSwapchainHandle() const;
     };
diff --git a/lib/VulkanMemoryAllocator-Hpp b/lib/VulkanMemoryAllocator-Hpp
index da6ea76eecf12a1decc76f58a3e096bcc555bd94..2e6f3f6c13933c84b55d01c4c0cbc2e7385ac8c1 160000
--- a/lib/VulkanMemoryAllocator-Hpp
+++ b/lib/VulkanMemoryAllocator-Hpp
@@ -1 +1 @@
-Subproject commit da6ea76eecf12a1decc76f58a3e096bcc555bd94
+Subproject commit 2e6f3f6c13933c84b55d01c4c0cbc2e7385ac8c1
diff --git a/modules/asset_loader/config/NLOHMANN_JSON.cmake b/modules/asset_loader/config/NLOHMANN_JSON.cmake
index 4bd7f4475ef1e748e109814d440762e27948f495..3a082ae59c5778aa5d172fab9eb71b108b3f652b 100644
--- a/modules/asset_loader/config/NLOHMANN_JSON.cmake
+++ b/modules/asset_loader/config/NLOHMANN_JSON.cmake
@@ -1,10 +1,16 @@
 
-use_git_submodule("${vkcv_asset_loader_lib_path}/json" json_status)
+find_package(nlohmann_json QUIET)
 
-if (${json_status})
-	set(JSON_BuildTests OFF CACHE INTERNAL "")
+if (nlohmann_json_FOUND)
+	list(APPEND vkcv_libraries nlohmann_json::nlohmann_json)
+else()
+	use_git_submodule("${vkcv_asset_loader_lib_path}/json" json_status)
 	
-	add_subdirectory(${vkcv_asset_loader_lib}/json)
-	
-	list(APPEND vkcv_asset_loader_libraries nlohmann_json::nlohmann_json)
+	if (${json_status})
+		set(JSON_BuildTests OFF CACHE INTERNAL "")
+		
+		add_subdirectory(${vkcv_asset_loader_lib}/json)
+		
+		list(APPEND vkcv_asset_loader_libraries nlohmann_json::nlohmann_json)
+	endif ()
 endif ()
diff --git a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
index 25d7d5b36d00bad8587fbe082f8ebd041d84fde6..2362e560516fee3bf392ef150a756a25aa2420a0 100644
--- a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
+++ b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp
@@ -36,6 +36,12 @@
 
 namespace vkcv::asset {
 
+/**
+ * @defgroup vkcv_asset Asset Loader Module
+ * A module to load assets like scenes, meshes and textures.
+ * @{
+ */
+
 /**
  * These return codes are limited to the asset loader module. If unified return
  * codes are defined for the vkcv framework, these will be used instead.
@@ -321,4 +327,6 @@ int loadScene(const std::filesystem::path &path, Scene &scene);
  */
 Texture loadTexture(const std::filesystem::path& path);
 
+/** @} */
+
 }	// end namespace vkcv::asset
diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
index b322f9cc2011edd491d0694396ec095ca2c37a19..110a941ff6703e989174eaf311118b10b41491d4 100644
--- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
+++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
@@ -1,8 +1,8 @@
 #include "vkcv/asset/asset_loader.hpp"
 #include <iostream>
-#include <string.h>	// memcpy(3)
+#include <cstring>	// memcpy(3)
 #include <set>
-#include <stdlib.h>	// calloc(3)
+#include <cstdlib>	// calloc(3)
 #include <vulkan/vulkan.hpp>
 #include <fx/gltf.h>
 #include <stb_image.h>
diff --git a/modules/camera/include/vkcv/camera/Camera.hpp b/modules/camera/include/vkcv/camera/Camera.hpp
index 6ccafe4ebe65f4e50747f1341ed1306948fef242..b333fbbd696a4583bd4aa9f9591a75d4de532d1d 100644
--- a/modules/camera/include/vkcv/camera/Camera.hpp
+++ b/modules/camera/include/vkcv/camera/Camera.hpp
@@ -1,4 +1,9 @@
 #pragma once
+/**
+ * @authors Vanessa Karolek, Josch Morgenstern, Sebastian Gaida, Katharina Krämer, Tobias Frisch, Alexander Gauggel
+ * @file include/vkcv/camera/Camera.hpp
+ * @brief Camera class of the camera module for the vkcv framework.
+ */
 
 #include <glm/glm.hpp>
 #include <glm/gtc/matrix_transform.hpp>
@@ -9,6 +14,12 @@
 
 namespace vkcv::camera {
 
+    /**
+     * @defgroup vkcv_camera Camera Module
+     * A module to manage intrinsic and extrinsic parameters with camera instances.
+     * @{
+     */
+
     /**
      * @brief Used to create a camera which governs the view and projection matrices.
      */
@@ -208,4 +219,6 @@ namespace vkcv::camera {
         void setUp(const glm::vec3 &up);
     };
 
+    /** @} */
+
 }
diff --git a/modules/camera/include/vkcv/camera/CameraController.hpp b/modules/camera/include/vkcv/camera/CameraController.hpp
index 90fc97401851851194ec89a10757bbfb1453990d..d6efd8f2f300dead870b3546939dad2088cd466e 100644
--- a/modules/camera/include/vkcv/camera/CameraController.hpp
+++ b/modules/camera/include/vkcv/camera/CameraController.hpp
@@ -1,13 +1,25 @@
 #pragma once
+/**
+ * @authors Vanessa Karolek, Josch Morgenstern, Tobias Frisch
+ * @file include/vkcv/camera/CameraController.hpp
+ * @brief CameraController class of the camera module for the vkcv framework. A camera object is controlled by a camera
+ * controller object. Using inheritance of this base class a camera controller object defines a specific control
+ * behaviour of the camera object in the scene.
+ */
 
 #include "Camera.hpp"
 #include "vkcv/Window.hpp"
 
 namespace vkcv::camera {
 
+    /**
+     * @addtogroup vkcv_camera
+     * @{
+     */
+
     /**
      * @brief Used as a base class for defining camera controller classes with different behaviors, e.g. the
-     * #PilotCameraController.
+     * PilotCameraController.
      */
     class CameraController {
 
@@ -69,4 +81,6 @@ namespace vkcv::camera {
         virtual void gamepadCallback(int gamepadIndex, Camera &camera, double frametime) = 0;
     };
 
+    /** @} */
+
 }
\ No newline at end of file
diff --git a/modules/camera/include/vkcv/camera/CameraManager.hpp b/modules/camera/include/vkcv/camera/CameraManager.hpp
index c0777b09544893aa38cf11396c1cf60bd800a837..092e1fc8552a192368b06216e2f51d2b291946d7 100644
--- a/modules/camera/include/vkcv/camera/CameraManager.hpp
+++ b/modules/camera/include/vkcv/camera/CameraManager.hpp
@@ -1,4 +1,10 @@
 #pragma once
+/**
+ * @authors Vanessa Karolek, Josch Morgenstern, Sebastian Gaida, Katharina Krämer, Tobias Frisch, Alexander Gauggel
+ * @file include/vkcv/camera/CameraManager.hpp
+ * @brief CameraManager class of the camera module for the vkcv framework. The camera manager manages several camera
+ * controller objects. Camera objects can be created and bound to a specific camera controller via this class.
+ */
 
 #include "PilotCameraController.hpp"
 #include "TrackballCameraController.hpp"
@@ -9,6 +15,11 @@
 
 namespace vkcv::camera {
 
+    /**
+     * @addtogroup vkcv_camera
+     * @{
+     */
+
     /**
      * @brief Used for specifying existing types of camera controllers when adding a new controller object to the
      * #CameraManager.
@@ -192,4 +203,7 @@ namespace vkcv::camera {
          */
         void update(double deltaTime);
     };
+
+    /** @} */
+
 }
diff --git a/modules/camera/include/vkcv/camera/PilotCameraController.hpp b/modules/camera/include/vkcv/camera/PilotCameraController.hpp
index 67388818a59b66775598e9d4257fa4c36646332a..c23a2cccce6f3d4036e9648d39b7b39df1d7ce4b 100644
--- a/modules/camera/include/vkcv/camera/PilotCameraController.hpp
+++ b/modules/camera/include/vkcv/camera/PilotCameraController.hpp
@@ -1,9 +1,20 @@
 #pragma once
+/**
+ * @authors Vanessa Karolek, Josch Morgenstern, Tobias Frisch
+ * @file include/vkcv/camera/PilotCameraController.hpp
+ * @brief PilotCameraController class of the camera module for the vkcv framework. This class inherits from the base
+ * class @#CameraController and enables camera objects to be moved freely within the scene.
+ */
 
 #include <vkcv/camera/CameraController.hpp>
 
 namespace vkcv::camera {
 
+    /**
+     * @addtogroup vkcv_camera
+     * @{
+     */
+
     /**
      * @brief Used to move around a camera object in world space.
      */
@@ -111,4 +122,6 @@ namespace vkcv::camera {
         void gamepadCallback(int gamepadIndex, Camera &camera, double frametime);
     };
 
+    /** @} */
+
 }
\ No newline at end of file
diff --git a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp
index 20336f7a10644c73e451c5106f37545e84eb27f7..e4f40383218f8c25fd0bca41d9ff673ce5a3589e 100644
--- a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp
+++ b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp
@@ -1,9 +1,20 @@
 #pragma once
+/**
+ * @authors Vanessa Karolek, Josch Morgenstern, Sebastian Gaida,Tobias Frisch
+ * @file include/vkcv/camera/TrackballCameraController.hpp
+ * @brief TrackballCameraController class of the camera module for the vkcv framework. This class inherits from the base
+ * class @#CameraController and enables camera objects to be orbited around a specific center point.
+ */
 
 #include "CameraController.hpp"
 
 namespace vkcv::camera {
 
+    /**
+     * @addtogroup vkcv_camera
+     * @{
+     */
+
     /**
      * @brief Used to orbit a camera around its center point.
      */
@@ -106,4 +117,6 @@ namespace vkcv::camera {
         void gamepadCallback(int gamepadIndex, Camera &camera, double frametime);
     };
 
+    /** @} */
+
 }
\ No newline at end of file
diff --git a/modules/camera/src/vkcv/camera/Camera.cpp b/modules/camera/src/vkcv/camera/Camera.cpp
index 25b2a7339a46de8ced171c8ee9c10f962c3c0399..4b3ae9274733a070463f553bd79183789d0701b6 100644
--- a/modules/camera/src/vkcv/camera/Camera.cpp
+++ b/modules/camera/src/vkcv/camera/Camera.cpp
@@ -1,6 +1,6 @@
 #include "vkcv/camera/Camera.hpp"
 
-#include <math.h>
+#include <cmath>
 
 namespace vkcv::camera {
 
diff --git a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
index 78456da209233c67735b3fb1abe1a11ad8be5736..c8e51fe9716af0304687d6ae60fc0bea2a5d2cc6 100644
--- a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
+++ b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
@@ -272,13 +272,13 @@ namespace vkcv::effects {
 			DescriptorWrites mipDownsampleWrites;
 			
 			if (mipLevel > 0) {
-				mipDownsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, sample, mipLevel - 1, true)};
+				mipDownsampleWrites.writeSampledImage(0, sample, mipLevel - 1, true);
 			} else {
-				mipDownsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, input)};
+				mipDownsampleWrites.writeSampledImage(0, input);
 			}
 			
-			mipDownsampleWrites.samplerWrites      = {SamplerDescriptorWrite(1, m_linearSampler)};
-			mipDownsampleWrites.storageImageWrites = {StorageImageDescriptorWrite(2, sample, mipLevel) };
+			mipDownsampleWrites.writeSampler(1, m_linearSampler);
+			mipDownsampleWrites.writeStorageImage(2, sample, mipLevel);
 			
 			m_core.writeDescriptorSet(mipDescriptorSets[mipLevel], mipDownsampleWrites);
 			
@@ -325,9 +325,9 @@ namespace vkcv::effects {
 		for(uint32_t mipLevel = mipDescriptorSets.size(); mipLevel > 0; mipLevel--) {
 			// mip descriptor writes
 			DescriptorWrites mipUpsampleWrites;
-			mipUpsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, sample, mipLevel, true)};
-			mipUpsampleWrites.samplerWrites      = {SamplerDescriptorWrite(1, m_linearSampler)};
-			mipUpsampleWrites.storageImageWrites = {StorageImageDescriptorWrite(2, sample, mipLevel - 1) };
+			mipUpsampleWrites.writeSampledImage(0, sample, mipLevel, true);
+			mipUpsampleWrites.writeSampler(1, m_linearSampler);
+			mipUpsampleWrites.writeStorageImage(2, sample, mipLevel - 1);
 			
 			m_core.writeDescriptorSet(mipDescriptorSets[mipLevel - 1], mipUpsampleWrites);
 			
@@ -370,9 +370,9 @@ namespace vkcv::effects {
 		const uint32_t flaresHeight = m_core.getImageHeight(m_flaresImage);
 		
 		DescriptorWrites lensFlaresWrites;
-		lensFlaresWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, m_blurImage, 0)};
-		lensFlaresWrites.samplerWrites = {SamplerDescriptorWrite(1, m_linearSampler)};
-		lensFlaresWrites.storageImageWrites = {StorageImageDescriptorWrite(2, m_flaresImage, mipLevel)};
+		lensFlaresWrites.writeSampledImage(0, m_blurImage, 0);
+		lensFlaresWrites.writeSampler(1, m_linearSampler);
+		lensFlaresWrites.writeStorageImage(2, m_flaresImage, mipLevel);
 		
 		m_core.writeDescriptorSet(m_lensFlaresDescriptorSet, lensFlaresWrites);
 		
@@ -415,34 +415,33 @@ namespace vkcv::effects {
 		vkcv::DescriptorWrites compositeWrites;
 		
 		if (m_advanced) {
-			compositeWrites.sampledImageWrites = {
-					SampledImageDescriptorWrite(0, m_blurImage),
-					SampledImageDescriptorWrite(1, m_flaresImage),
-					SampledImageDescriptorWrite(4, m_radialLut),
-					SampledImageDescriptorWrite(6, m_lensDirt)
-			};
+			compositeWrites.writeSampledImage(
+					0, m_blurImage
+			).writeSampledImage(
+					1, m_flaresImage
+			).writeSampledImage(
+					4, m_radialLut
+			).writeSampledImage(
+					6, m_lensDirt
+			);
 			
-			compositeWrites.samplerWrites = {
-					SamplerDescriptorWrite(2, m_linearSampler),
-					SamplerDescriptorWrite(5, m_radialLutSampler)
-			};
+			compositeWrites.writeSampler(
+					2, m_linearSampler
+			).writeSampler(
+					5, m_radialLutSampler
+			);
 			
-			compositeWrites.storageImageWrites = {
-					StorageImageDescriptorWrite(3, output)
-			};
+			compositeWrites.writeStorageImage(3, output);
 		} else {
-			compositeWrites.sampledImageWrites = {
-					SampledImageDescriptorWrite(0, m_blurImage),
-					SampledImageDescriptorWrite(1, m_flaresImage)
-			};
+			compositeWrites.writeSampledImage(
+					0, m_blurImage
+			).writeSampledImage(
+					1, m_flaresImage
+			);
 			
-			compositeWrites.samplerWrites = {
-					SamplerDescriptorWrite(2, m_linearSampler)
-			};
+			compositeWrites.writeSampler(2, m_linearSampler);
 			
-			compositeWrites.storageImageWrites = {
-					StorageImageDescriptorWrite(3, output)
-			};
+			compositeWrites.writeStorageImage(3, output);
 		}
 		
 		m_core.writeDescriptorSet(m_compositeDescriptorSet, compositeWrites);
@@ -477,11 +476,11 @@ namespace vkcv::effects {
 				0.0f, 1.0f, 1.0f, 1.0f
 		});
 		
-		const uint32_t halfWidth = static_cast<uint32_t>(std::ceil(
+		const auto halfWidth = static_cast<uint32_t>(std::ceil(
 				static_cast<float>(m_core.getImageWidth(output)) * 0.5f
 		));
 		
-		const uint32_t halfHeight = static_cast<uint32_t>(std::ceil(
+		const auto halfHeight = static_cast<uint32_t>(std::ceil(
 				static_cast<float>(m_core.getImageHeight(output)) * 0.5f
 		));
 		
diff --git a/modules/gui/include/vkcv/gui/GUI.hpp b/modules/gui/include/vkcv/gui/GUI.hpp
index 8826cdbac057e39f2655844bfe9a252da43a4596..303fbb2c0920b400cb7637641a70e26665b4dabd 100644
--- a/modules/gui/include/vkcv/gui/GUI.hpp
+++ b/modules/gui/include/vkcv/gui/GUI.hpp
@@ -9,29 +9,73 @@
 
 namespace vkcv::gui {
 
+    /**
+     * @defgroup vkcv_gui GUI Module
+     * A module to manage ImGUI integration for VkCV applications.
+     * @{
+     */
+
+    /**
+     * Class to manage ImGui integration for VkCV.
+     */
 	class GUI final {
 	private:
+        /**
+         * Window handle of the currently used window to draw user interface on.
+         */
 		WindowHandle m_windowHandle;
+
+        /**
+         * Reference to the current Core instance.
+         */
 		Core& m_core;
-		
+
+        /**
+         * Reference to the current Context instance.
+         */
 		const Context& m_context;
-		
+
+        /**
+         * ImGui context for drawing GUI.
+         */
 		ImGuiContext* m_gui_context;
-		
+
+        /**
+         * Vulkan handle for the ImGui descriptor pool.
+         */
 		vk::DescriptorPool m_descriptor_pool;
+
+        /**
+         * Vulkan handle for the ImGui render pass.
+         */
 		vk::RenderPass m_render_pass;
-		
+
+        /**
+         * Event handle for pressing a mouse button.
+         */
 		event_handle<int,int,int> f_mouseButton;
+
+        /**
+         * Event handle for scrolling with the mouse or touchpad.
+         */
 		event_handle<double,double> f_mouseScroll;
+
+        /**
+         * Event handle for pressing a key.
+         */
 		event_handle<int,int,int,int> f_key;
+
+        /**
+         * Event handle for typing a character.
+         */
 		event_handle<unsigned int> f_char;
 		
 	public:
 		/**
-		 * Constructor of a new instance of ImGui management
+		 * Constructor of a new instance for ImGui management.
 		 *
-		 * @param core Valid #Core instance of the framework
-		 * @param window Valid #Window instance of the framework
+		 * @param[in,out] core Valid Core instance of the framework
+		 * @param[in,out] windowHandle Valid Window handle of the framework
 		 */
 		GUI(Core& core, WindowHandle& windowHandle);
 		
@@ -42,12 +86,12 @@ namespace vkcv::gui {
 		GUI& operator=(GUI&& other) = delete;
 		
 		/**
-		 * Destructor of a #GUI instance
+		 * Destructor of a GUI instance.
 		 */
 		virtual ~GUI();
 		
 		/**
-		 * Sets up a new frame for ImGui to draw
+		 * Sets up a new frame for ImGui to draw.
 		 */
 		void beginGUI();
 		
@@ -59,4 +103,6 @@ namespace vkcv::gui {
 		
 	};
 
+    /** @} */
+
 }
diff --git a/modules/material/include/vkcv/material/Material.hpp b/modules/material/include/vkcv/material/Material.hpp
index 41ee8aecce98072981be80ccf9803c43c6464746..7251bda151cab9f812114f8a7a707597c476ad21 100644
--- a/modules/material/include/vkcv/material/Material.hpp
+++ b/modules/material/include/vkcv/material/Material.hpp
@@ -6,51 +6,177 @@
 #include <vkcv/Handles.hpp>
 
 namespace vkcv::material {
-	
+
+    /**
+     * @defgroup vkcv_material Material Module
+     * A module to manage standardized materials for rendering.
+     * @{
+     */
+
+    /**
+     * Enum to handle standardized material types.
+     */
 	enum class MaterialType {
+        /**
+         * The material can be used for physically based rendering.
+         */
 		PBR_MATERIAL = 1,
-		
+
+        /**
+         * The type is unknown.
+         */
 		UNKNOWN = 0
 	};
-	
+
+    /**
+     * Class to manage required handles for materials using
+     * a wide range of textures with separate samplers and factors.
+     */
 	class Material {
 	private:
+
+        /**
+         * A nested structure for textures used by a material.
+         */
 		struct Texture {
+            /**
+             * The image handle of a texture.
+             */
 			ImageHandle m_Image;
+
+            /**
+             * The sampler handle of a texture.
+             */
 			SamplerHandle m_Sampler;
+
+            /**
+             * The list of custom factors for a given texture.
+             */
 			std::vector<float> m_Factors;
 		};
-		
+
+        /**
+         * The type of a material.
+         */
 		MaterialType m_Type;
+
+        /**
+         * The descriptor set handle of a material.
+         */
 		DescriptorSetHandle m_DescriptorSet;
+
+        /**
+         * The descriptor set layout used by a material.
+         */
 		DescriptorSetLayoutHandle m_DescriptorSetLayout;
+
+        /**
+         * The list of textures used by a material.
+         */
 		std::vector<Texture> m_Textures;
 		
 	public:
+        /**
+         * Default constructor to create an invalid material instance.
+         */
 		Material();
+		
+		/**
+		 * Destructor to release handles and resources of a material instance.
+		 */
 		~Material() = default;
 		
+		/**
+		 * Copy-constructor to copy a given material instance.
+		 * @param other Other material
+		 */
 		Material(const Material& other) = default;
+		
+		/**
+		 * Move-constructor to move a given material instance.
+		 * @param other Other material
+		 */
 		Material(Material&& other) = default;
 		
+		/**
+		 * Copy-operator to copy a given material instance.
+		 * @param other Other material
+		 * @return Reference to the material
+		 */
 		Material& operator=(const Material& other) = default;
-		Material& operator=(Material&& other) = default;
 		
+		/**
+		 * Move-operator to move a given material instance.
+		 * @param other Other material
+		 * @return Reference to the material
+		 */
+		Material& operator=(Material&& other) = default;
+
+        /**
+         * Returns the type of a material as MaterialType.
+         * @return Type of material
+         */
 		[[nodiscard]]
 		MaterialType getType() const;
-		
+
+        /**
+         * Returns the descriptor set handle of the material.
+         * @return Descriptor set handle
+         */
 		[[nodiscard]]
 		const DescriptorSetHandle& getDescriptorSet() const;
 
+        /**
+         * Returns the descriptor set layout handle used by the material.
+         * @return Descriptor set layout handle
+         */
 		[[nodiscard]]
 		const DescriptorSetLayoutHandle& getDescriptorSetLayout() const;
-		
+
+        /**
+         * Checks if the material is valid and returns the status
+         * as boolean value.
+         * @return true if the material is valid, otherwise false
+         */
 		explicit operator bool() const;
-		
+
+        /**
+         * Checks if the material is invalid and returns the status
+         * as boolean value.
+         * @return true if the material is invalid, otherwise false
+         */
 		bool operator!() const;
-		
-		static const std::unordered_map<uint32_t ,DescriptorBinding>& getDescriptorBindings(MaterialType type);
-		
+
+        /**
+         * Returns the descriptor bindings required by a given material
+         * type to create the descriptor set layout.
+         * @param[in] type Type of material
+         * @return Descriptor bindings of a material type
+         */
+		static const DescriptorBindings& getDescriptorBindings(MaterialType type);
+
+        /**
+         * Creates a new valid material which supports physically based
+         * rendering.
+         * @param[in,out] core Reference to Core instance
+         * @param[in] colorImg Base color image handle
+         * @param[in] colorSmp Base color sampler handle
+         * @param[in] normalImg Normal map image handle
+         * @param[in] normalSmp Normal map sampler handle
+         * @param[in] metRoughImg Metallic and roughness image handle
+         * @param[in] metRoughSmp Metallic and roughness sampler handle
+         * @param[in] occlusionImg Occlusion map image handle
+         * @param[in] occlusionSmp Occlusion map sampler handle
+         * @param[in] emissiveImg Emissive image handle
+         * @param[in] emissiveSmp Emissive sampler handle
+         * @param[in] baseColorFactor 4D vector of base color factors
+         * @param[in] metallicFactor Metallic factor
+         * @param[in] roughnessFactor Roughness factor
+         * @param[in] normalScale Scale of normal map
+         * @param[in] occlusionStrength Strength of occlusion
+         * @param[in] emissiveFactor 3D vector of emmisive factors
+         * @return New material instance
+         */
 		static Material createPBR(Core &core,
 								  const ImageHandle &colorImg,
 								  const SamplerHandle &colorSmp,
@@ -70,5 +196,7 @@ namespace vkcv::material {
 								  const float emissiveFactor [3]);
 	
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index bd26733b878634e3caf5b927e8c0307432279212..2bd18e8342a24d6311182c9c0c2d640d3cbfa185 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -201,8 +201,8 @@ namespace vkcv::material {
 		vkcv::DescriptorWrites setWrites;
 		
 		for (size_t i = 0; i < material.m_Textures.size(); i++) {
-			setWrites.sampledImageWrites.emplace_back(i * 2, material.m_Textures[i].m_Image);
-			setWrites.samplerWrites.emplace_back(i * 2 + 1, material.m_Textures[i].m_Sampler);
+			setWrites.writeSampledImage(i * 2, material.m_Textures[i].m_Image);
+			setWrites.writeSampler(i * 2 + 1, material.m_Textures[i].m_Sampler);
 		}
 		
 		core.writeDescriptorSet(material.m_DescriptorSet, setWrites);
diff --git a/modules/meshlet/include/vkcv/meshlet/Forsyth.hpp b/modules/meshlet/include/vkcv/meshlet/Forsyth.hpp
index 43dc9a3b6bb81ea915268de7a7b53b18efd27638..90625bd470ac4ecbc27f2e6f95ab9e18734557f8 100644
--- a/modules/meshlet/include/vkcv/meshlet/Forsyth.hpp
+++ b/modules/meshlet/include/vkcv/meshlet/Forsyth.hpp
@@ -4,15 +4,24 @@
 
 namespace vkcv::meshlet
 {
- /**
-  * Reorders the index buffer, simulating a LRU cache, so that vertices are grouped together in close triangle patches
-  * @param idxBuf current IndexBuffer
-  * @param vertexCount of the mesh
-  * @return new reordered index buffer to replace the input index buffer
-  * References:
-  * https://tomforsyth1000.github.io/papers/fast_vert_cache_opt.html
-  * https://www.martin.st/thesis/efficient_triangle_reordering.pdf
-  * https://github.com/vivkin/forsyth/blob/master/forsyth.h
-  */
- VertexCacheReorderResult forsythReorder(const std::vector<uint32_t> &idxBuf, const size_t vertexCount);
+
+    /**
+     * @addtogroup vkcv_meshlet
+     * @{
+     */
+
+    /**
+    * Reorders the index buffer, simulating a LRU cache, so that vertices are grouped together in close triangle patches
+    * @param idxBuf current IndexBuffer
+    * @param vertexCount of the mesh
+    * @return new reordered index buffer to replace the input index buffer
+    * References:
+    * https://tomforsyth1000.github.io/papers/fast_vert_cache_opt.html
+    * https://www.martin.st/thesis/efficient_triangle_reordering.pdf
+    * https://github.com/vivkin/forsyth/blob/master/forsyth.h
+    */
+    VertexCacheReorderResult forsythReorder(const std::vector<uint32_t> &idxBuf, const size_t vertexCount);
+
+    /** @} */
+
 }
diff --git a/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp b/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
index 9900dffaf28c85753d367ba79bbdf5c19a2cf479..ee32878726123a8d51c3816c9df2644da4ae9b6c 100644
--- a/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
+++ b/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
@@ -7,6 +7,12 @@
 
 namespace vkcv::meshlet {
 
+    /**
+     * @defgroup vkcv_meshlet Meshlet Module
+     * A module to convert meshes into meshlets for rendering via mesh shaders.
+     * @{
+     */
+
     struct Vertex {
         glm::vec3   position;
         float       padding0;
@@ -56,4 +62,6 @@ namespace vkcv::meshlet {
             const std::vector<uint8_t>& indexData,
             vkcv::asset::IndexType indexType);
 
+    /** @} */
+
 }
\ No newline at end of file
diff --git a/modules/meshlet/include/vkcv/meshlet/Tipsify.hpp b/modules/meshlet/include/vkcv/meshlet/Tipsify.hpp
index 6fb4b37d9c17c82642c3b5e7667c3e8acc50b8c0..3c808f9565ee1e73b14356dc0f4c8f4cd7c6dd9c 100644
--- a/modules/meshlet/include/vkcv/meshlet/Tipsify.hpp
+++ b/modules/meshlet/include/vkcv/meshlet/Tipsify.hpp
@@ -5,6 +5,12 @@
 #include <iostream>
 
 namespace vkcv::meshlet {
+
+    /**
+     * @addtogroup vkcv_meshlet
+     * @{
+     */
+
     /**
      * reorders the IndexBuffer, so all usages of vertices to triangle are as close as possible
      * @param indexBuffer32Bit current IndexBuffer
@@ -20,4 +26,7 @@ namespace vkcv::meshlet {
      */
     VertexCacheReorderResult tipsifyMesh(const std::vector<uint32_t> &indexBuffer32Bit,
                                          const int vertexCount, const unsigned int cacheSize = 20);
+
+    /** @} */
+
 }
\ No newline at end of file
diff --git a/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp b/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
index c5762100bc37eccbe3e4f6b4c94e5f0e580c53c7..101a777d4ef52d31579355f52c562a88e058cbb5 100644
--- a/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
+++ b/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
@@ -18,18 +18,18 @@ namespace vkcv::meshlet {
 
     /**
      * searches for the next VertexIndex that was used before or returns any vertexIndex if no used was found
-     * @param livingTriangles
-     * @param usedVerticeStack
-     * @param usedVerticeCount
-     * @param usedVerticeOffset
-     * @param vertexCount
-     * @param lowestLivingVertexIndex
-     * @param currentTriangleIndex
-     * @param skippedIndices
+     * @param livingVertices vertice that still has a living triangle
+     * @param usedVerticeStack stack of vertices that are recently used
+     * @param usedVerticeCount number of last used vertices that maxes at @param maxUsedVertices
+     * @param usedVerticeOffset the @param usedVerticeStack wraps around and overrides old vertices, this offset keeps the wrapping intact
+     * @param vertexCount total vertex count to terminate correctly
+     * @param lowestLivingVertexIndex vertexIndex with the lowest number
+     * @param currentTriangleIndex index of the currently fanned triangle
+     * @param skippedIndices indices that define a new meshlet, even if they are close in memory
      * @return a VertexIndex to be used as fanningVertexIndex
      */
     int skipDeadEnd(
-            const std::vector<uint8_t> &livingTriangles,
+            const std::vector<uint8_t> &livingVertices,
             const std::vector<uint32_t> &usedVerticeStack,
             int &usedVerticeCount,
             int &usedVerticeOffset,
@@ -43,14 +43,14 @@ namespace vkcv::meshlet {
             // iterate from the latest to the oldest. + maxUsedVertices to always make it a positive number in the range 0 to maxUsedVertices -1
             int nextVertex = usedVerticeStack[mod(--usedVerticeCount)];
 
-            if (livingTriangles[nextVertex] > 0) {
+            if (livingVertices[nextVertex] > 0) {
                 return nextVertex;
             }
         }
         // returns any vertexIndex since no last used has a living triangle
         while (lowestLivingVertexIndex + 1 < vertexCount) {
             lowestLivingVertexIndex++;
-            if (livingTriangles[lowestLivingVertexIndex] > 0) {
+            if (livingVertices[lowestLivingVertexIndex] > 0) {
                 // add index of the vertex to skippedIndices
                 skippedIndices.push_back(static_cast<uint32_t>(currentTriangleIndex * 3));
                 return lowestLivingVertexIndex;
@@ -61,19 +61,19 @@ namespace vkcv::meshlet {
 
     /**
      * searches for the best next candidate as a fanningVertexIndex
-     * @param vertexCount
-     * @param lowestLivingVertexIndex
-     * @param cacheSize
-     * @param possibleCandidates
-     * @param numPossibleCandidates
-     * @param lastTimestampCache
-     * @param currentTimeStamp
-     * @param livingTriangles
-     * @param usedVerticeStack
-     * @param usedVerticeCount
-     * @param usedVerticeOffset
-     * @param currentTriangleIndex
-     * @param skippedIndices
+     * @param vertexCount total vertexCount of the mesh
+     * @param lowestLivingVertexIndex vertexIndex with the lowest number
+     * @param cacheSize number to determine in which range vertices are prioritized to me reused
+     * @param possibleCandidates candidates for the next vertex to be fanned out
+     * @param numPossibleCandidates number of all possible candidates
+     * @param lastTimestampCache number of the last iteration the vertex was used
+     * @param currentTimeStamp current iteration of all vertices
+     * @param livingVertices vertice that still has a living triangle
+     * @param usedVerticeStack stack of vertices that are recently used
+     * @param usedVerticeCount number of last used vertices that maxes at @param maxUsedVertices
+     * @param usedVerticeOffset the @param usedVerticeStack wraps around and overrides old vertices, this offset keeps the wrapping intact
+     * @param currentTriangleIndex index of the currently fanned triangle
+     * @param skippedIndices indices that define a new meshlet, even if they are close in memory
      * @return a VertexIndex to be used as fanningVertexIndex
      */
     int getNextVertexIndex(int vertexCount,
@@ -83,7 +83,7 @@ namespace vkcv::meshlet {
                            int numPossibleCandidates,
                            const std::vector<uint32_t> &lastTimestampCache,
                            int currentTimeStamp,
-                           const std::vector<uint8_t> &livingTriangles,
+                           const std::vector<uint8_t> &livingVertices,
                            const std::vector<uint32_t> &usedVerticeStack,
                            int &usedVerticeCount,
                            int &usedVerticeOffset,
@@ -96,12 +96,12 @@ namespace vkcv::meshlet {
             int vertexIndex = possibleCandidates[j];
 
             // the candidate needs to be not fanned out yet
-            if (livingTriangles[vertexIndex] > 0) {
+            if (livingVertices[vertexIndex] > 0) {
                 int priority = -1;
 
                 // prioritizes recent used vertices, but tries not to pick one that has many triangles -> fills holes better
-                if ( currentTimeStamp - lastTimestampCache[vertexIndex] + 2 * livingTriangles[vertexIndex] <=
-                    cacheSize) {
+                if ( currentTimeStamp - lastTimestampCache[vertexIndex] + 2 * livingVertices[vertexIndex] <=
+					 cacheSize) {
                     priority = currentTimeStamp - lastTimestampCache[vertexIndex];
                 }
                 // select the vertexIndex with the highest priority
@@ -115,14 +115,14 @@ namespace vkcv::meshlet {
         // if no candidate is alive, try and find another one
         if (nextVertexIndex == -1) {
             nextVertexIndex = skipDeadEnd(
-                    livingTriangles,
-                    usedVerticeStack,
-                    usedVerticeCount,
-                    usedVerticeOffset,
-                    vertexCount,
-                    lowestLivingVertexIndex,
-                    currentTriangleIndex,
-                    skippedIndices);
+					livingVertices,
+					usedVerticeStack,
+					usedVerticeCount,
+					usedVerticeOffset,
+					vertexCount,
+					lowestLivingVertexIndex,
+					currentTriangleIndex,
+					skippedIndices);
         }
         return nextVertexIndex;
     }
diff --git a/modules/scene/include/vkcv/scene/Bounds.hpp b/modules/scene/include/vkcv/scene/Bounds.hpp
index 07cdf88828d786982b0fe8e7919d543557794c42..8ad5806506610dbef6e4f1e0e26d66dfe0dbb63b 100644
--- a/modules/scene/include/vkcv/scene/Bounds.hpp
+++ b/modules/scene/include/vkcv/scene/Bounds.hpp
@@ -5,65 +5,205 @@
 #include <glm/vec3.hpp>
 
 namespace vkcv::scene {
-	
+
+    /**
+     * @addtogroup vkcv_scene
+     * @{
+     */
+
+    /**
+     * A basic class to represent axis aligned bounding boxes.
+     */
 	class Bounds {
 	private:
+        /**
+         * Minimum values of the box as 3D vector.
+         */
 		glm::vec3 m_min;
+
+        /**
+         * Maximum values of the box as 3D vector.
+         */
 		glm::vec3 m_max;
 		
 	public:
+        /**
+         * Default constructor creating a zero volume axis aligned bounding
+         * box.
+         */
 		Bounds();
+		
+		/**
+         * Constructor creating a zero volume axis aligned bounding
+         * box around a certain point.
+         * @param[in] point Center of the box as 3D vector
+         */
+		Bounds(const glm::vec3& point);
+
+        /**
+         * Constructor creating an axis aligned bounding box with given
+         * boundaries, defined through minimum and maximum values.
+         * @param[in] min Minimum values of the box as 3D vector
+         * @param[in] max Maximum values of the box as 3D vector
+         */
 		Bounds(const glm::vec3& min, const glm::vec3& max);
+
+        /**
+         * Destructor of an axis aligned bounding box.
+         */
 		~Bounds() = default;
-		
+
+        /**
+         * Copy-constructor of an axis aligned bounding box.
+         * @param[in] other Other box as Bounds
+         */
 		Bounds(const Bounds& other) = default;
-		Bounds(Bounds&& other) = default;
-		
+
+        /**
+         * Move-constructor of an axis aligned bounding box.
+         * @param[in,out] other Other box as Bounds
+         */
+        Bounds(Bounds&& other) = default;
+
+        /**
+         * Copy-operator of an axis aligned bounding box.
+         * @param[in] other Other box as Bounds
+         * @return Reference to this box
+         */
 		Bounds& operator=(const Bounds& other) = default;
+
+        /**
+         * Move-operator of an axis aligned bounding box.
+         * @param[in,out] other Other box as Bounds
+         * @return Reference to this box
+         */
 		Bounds& operator=(Bounds&& other) = default;
-		
+
+        /**
+         * Set and replace the minimum values of the box
+         * via a 3D vector.
+         * @param[in] min New minimum values of the box as 3D vector
+         */
 		void setMin(const glm::vec3& min);
-		
+
+        /**
+         * Return the current minimum values of the box as
+         * 3D vector.
+         * @return Minimum values of the box as 3D vector
+         */
 		[[nodiscard]]
 		const glm::vec3& getMin() const;
-		
+
+        /**
+         * Set and replace the maximum values of the box
+         * via a 3D vector.
+         * @param[in] max New maximum values of the box as 3D vector
+         */
 		void setMax(const glm::vec3& max);
-		
+
+        /**
+         * Return the current maximum values of the box as
+         * 3D vector.
+         * @return Maximum values of the box as 3D vector
+         */
 		[[nodiscard]]
 		const glm::vec3& getMax() const;
-		
+
+        /**
+         * Set the new center of the box by moving it and keeping
+         * its current volume.
+         * @param[in] center New center as 3D vector
+         */
 		void setCenter(const glm::vec3& center);
-		
+
+        /**
+         * Return the current center of the box as 3D vector.
+         * @return Center as 3D vector
+         */
 		[[nodiscard]]
 		glm::vec3 getCenter() const;
-		
+
+        /**
+         * Set the new size of the box by scaling it from its center,
+         * keeping the center position but replacing its volume.
+         * @param[in] size New size as 3D vector
+         */
 		void setSize(const glm::vec3& size);
-		
+
+        /**
+         * Return the current size of the box as 3D vector.
+         * @return Size as 3D vector
+         */
 		[[nodiscard]]
 		glm::vec3 getSize() const;
-		
+
+        /**
+         * Return a fixed size array containing all corners of
+         * the box as 3D vectors in absolute positions.
+         * @return Array of corners as 3D vectors
+         */
 		[[nodiscard]]
 		std::array<glm::vec3, 8> getCorners() const;
-		
+
+        /**
+         * Resize the box to include a given point, provided
+         * in absolute position as 3D vector.
+         * @param[in] point Point as 3D vector
+         */
 		void extend(const glm::vec3& point);
-		
+
+        /**
+         * Return if a given point, provided in absolute position,
+         * is inside this box or not.
+         * @param[in] point Point as 3D vector
+         * @return true if the point is inside, otherwise false
+         */
 		[[nodiscard]]
 		bool contains(const glm::vec3& point) const;
-		
+
+        /**
+         * Return if a given other axis aligned bounding box is
+         * inside this box or not.
+         * @param[in] other Other box as Bounds
+         * @return true if the box is inside, otherwise false
+         */
 		[[nodiscard]]
 		bool contains(const Bounds& other) const;
-		
+
+        /**
+         * Return if a given other axis aligned bounding box is
+         * intersecting this box or not.
+         * @param[in] other Other box as Bounds
+         * @return true if the boxes are intersecting, otherwise false
+         */
 		[[nodiscard]]
 		bool intersects(const Bounds& other) const;
-		
+
+        /**
+         * Return if the defined bounding box is valid (min <= max).
+         * @return true if the box is valid, otherwise false
+         */
 		[[nodiscard]]
 		explicit operator bool() const;
-		
+
+        /**
+         * Return if the defined bounding box is invalid (min > max).
+         * @return true if the box is invalid, otherwise false
+         */
 		[[nodiscard]]
 		bool operator!() const;
 	
 	};
-	
+
+    /**
+     * Stream-operator of the axis aligned bounding box to print
+     * it as readable output to logs or the console.
+     * @param[out] out Output stream
+     * @param[in] bounds Axis aligned bounding box
+     * @return Accessed output stream
+     */
 	std::ostream& operator << (std::ostream& out, const Bounds& bounds);
+
+    /** @} */
 	
 }
diff --git a/modules/scene/include/vkcv/scene/Frustum.hpp b/modules/scene/include/vkcv/scene/Frustum.hpp
index de3917575a9aed32459e6403fab1d6d8fe131b0a..e40092240614a5ee76fe3f5aa5a43db98d39970a 100644
--- a/modules/scene/include/vkcv/scene/Frustum.hpp
+++ b/modules/scene/include/vkcv/scene/Frustum.hpp
@@ -4,9 +4,42 @@
 #include "vkcv/scene/Bounds.hpp"
 
 namespace vkcv::scene {
+
+    /**
+     * @addtogroup vkcv_scene
+     * @{
+     */
 	
-	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool* negative_w = nullptr);
-	
+	/**
+     * Transform a given axis aligned bounding box into frustum coordinates
+     * using a given 4x4 transformation matrix to return a new axis aligned
+     * bounding box containing that transformed box.
+     * @param[in] transform Frustum defining 4x4 matrix
+     * @param[in] bounds Axis aligned bounding box
+     * @return Bounds containing box in frustum coordinates
+     */
+	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds);
+
+    /**
+     * Transform a given axis aligned bounding box into frustum coordinates
+     * using a given 4x4 transformation matrix to return a new axis aligned
+     * bounding box containing that transformed box.
+     * @param[in] transform Frustum defining 4x4 matrix
+     * @param[in] bounds Axis aligned bounding box
+     * @param[out] negative_w Flag if w-coordinate is negative
+     * @return Bounds containing box in frustum coordinates
+     */
+	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool& negative_w);
+
+    /**
+     * Check if an axis aligned bounding box is intersecting a given frustum
+     * defined by a 4x4 transformation matrix.
+     * @param[in] transform Frustum defining 4x4 matrix
+     * @param[in] bounds Axis aligned bounding box
+     * @return true if the box and frustum are intersecting, otherwise false
+     */
 	bool checkFrustum(const glm::mat4& transform, const Bounds& bounds);
+
+    /** @} */
 	
 }
diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp
index bc82af4bfabed5e8bfc286bc53cd7b89791726fc..3118696bdc270506bc6197e7d853148072294663 100644
--- a/modules/scene/include/vkcv/scene/Mesh.hpp
+++ b/modules/scene/include/vkcv/scene/Mesh.hpp
@@ -7,46 +7,128 @@
 #include "MeshPart.hpp"
 
 namespace vkcv::scene {
-	
+
+    /**
+     * @addtogroup vkcv_scene
+     * @{
+     */
+
+    /**
+     * An event function type to be called on per drawcall recording level to adjust data
+     * like push constants with provided matrices.
+     */
 	typedef typename event_function<const glm::mat4&, const glm::mat4&, PushConstants&, vkcv::DrawcallInfo&>::type RecordMeshDrawcallFunction;
 	
 	class Node;
-	
+
+    /**
+     * A class to represent a whole mesh to render.
+     */
 	class Mesh {
 		friend class Node;
 		
 	private:
+        /**
+         * Parent scene of the mesh.
+         */
 		Scene& m_scene;
+
+        /**
+         * List of the meshes parts.
+         */
 		std::vector<MeshPart> m_parts;
+
+        /**
+         * List of the meshes drawcalls to render.
+         */
 		std::vector<DrawcallInfo> m_drawcalls;
+
+        /**
+         * Local transformation matrix of the mesh.
+         */
 		glm::mat4 m_transform;
+
+        /**
+         * Axis aligned bounding box of the mesh.
+         */
 		Bounds m_bounds;
-		
+
+        /**
+         * Constructor of a new mesh with a given scene as parent.
+         * @param[in,out] scene Scene
+         */
 		explicit Mesh(Scene& scene);
-		
+
+        /**
+         * Load mesh data from a scene structure from the asset loader
+         * creating and loading all mesh parts being required.
+         * @param[in] scene Scene structure from asset loader
+         * @param[in] mesh Mesh structure from asset loader
+         */
 		void load(const asset::Scene& scene,
 				  const asset::Mesh& mesh);
-		
+
+        /**
+         * Record drawcalls of the mesh, equally to all its visible parts.
+         * @param[in] viewProjection View-transformation and projection as 4x4 matrix
+         * @param[out] pushConstants Structure to store push constants per drawcall
+         * @param[out] drawcalls List of drawcall structures
+         * @param[in] record Drawcall recording event function
+         */
 		void recordDrawcalls(const glm::mat4& viewProjection,
 							 PushConstants& pushConstants,
 							 std::vector<DrawcallInfo>& drawcalls,
 							 const RecordMeshDrawcallFunction& record);
-		
+
+        /**
+         * Return the amount of drawcalls of the mesh
+         * as sum of all its parts.
+         * @return Amount of drawcalls
+         */
 		[[nodiscard]]
 		size_t getDrawcallCount() const;
 	
 	public:
+        /**
+         * Destructor of a mesh.
+         */
 		~Mesh();
-		
+
+        /**
+         * Copy-constructor of a mesh.
+         * @param[in] other Other mesh instance
+         */
 		Mesh(const Mesh& other) = default;
-		Mesh(Mesh&& other) = default;
-		
+
+        /**
+         * Move-constructor of a mesh.
+         * @param[in,out] other Other mesh instance
+         */
+        Mesh(Mesh&& other) = default;
+
+        /**
+         * Copy-operator of a mesh.
+         * @param[in] other Other mesh instance
+         * @return Reference to this mesh instance
+         */
 		Mesh& operator=(const Mesh& other);
+
+        /**
+         * Move-operator of a mesh.
+         * @param[in,out] other Other mesh instance
+         * @return Reference to this mesh instance
+         */
 		Mesh& operator=(Mesh&& other) noexcept;
-		
+
+        /**
+         * Return the axis aligned bounding box of the mesh.
+         * @return Axis aligned bounding box of this mesh
+         */
 		[[nodiscard]]
 		const Bounds& getBounds() const;
 	
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp
index 0d3467c6b57fcece69eb6f0c609c604fb99907d2..8d77efd7a112ea92a6c4192e5a5cf43cea53e800 100644
--- a/modules/scene/include/vkcv/scene/MeshPart.hpp
+++ b/modules/scene/include/vkcv/scene/MeshPart.hpp
@@ -9,46 +9,140 @@
 #include "Bounds.hpp"
 
 namespace vkcv::scene {
+
+    /**
+     * @addtogroup vkcv_scene
+     * @{
+     */
 	
 	class Scene;
 	class Mesh;
-	
+
+    /**
+     * A class to represent a group of vertices to render
+     * a part of a mesh.
+     */
 	class MeshPart {
 		friend class Mesh;
 	
 	private:
+        /**
+         * Parent scene of the mesh part.
+         */
 		Scene& m_scene;
+
+        /**
+         * The buffer handle of its vertex buffer.
+         */
 		BufferHandle m_vertices;
+
+        /**
+         * The list of the used vertex buffer bindings.
+         */
 		std::vector<VertexBufferBinding> m_vertexBindings;
+
+        /**
+         * The buffer handle of its index buffer.
+         */
 		BufferHandle m_indices;
+
+        /**
+         * The amount of indices in its index buffer.
+         */
 		size_t m_indexCount;
+
+        /**
+         * Axis aligned bounding box of the mesh part.
+         */
 		Bounds m_bounds;
+
+        /**
+         * The index of the material used to render
+         * this part of the mesh.
+         */
 		size_t m_materialIndex;
-		
+
+        /**
+         * Constructor of a new mesh part with a given scene as parent.
+         * @param[in,out] scene Scene
+         */
 		explicit MeshPart(Scene& scene);
-		
+
+        /**
+         * Load vertex and index data from structures provided by the asset loader
+         * and add a matching drawcall to the list if the loaded mesh part is valid.
+         * @param[in] scene Scene structure from asset loader
+         * @param[in] vertexGroup Vertex group structure from asset loader
+         * @param[out] drawcalls List of drawcalls
+         */
 		void load(const asset::Scene& scene,
 				  const asset::VertexGroup& vertexGroup,
 				  std::vector<DrawcallInfo>& drawcalls);
 	
 	public:
+        /**
+         * Destructor of a mesh part.
+         */
 		~MeshPart();
-		
+
+        /**
+         * Copy-constructor of a mesh part.
+         * @param[in] other Other mesh part
+         */
 		MeshPart(const MeshPart& other);
-		MeshPart(MeshPart&& other);
-		
+
+        /**
+         * Move-constructor of a mesh part.
+         * @param[in,out] other Other mesh part
+         */
+        MeshPart(MeshPart&& other) noexcept;
+
+        /**
+         * Copy-operator of a mesh part.
+         * @param[in] other Other mesh part
+         * @return Reference to this mesh part
+         */
 		MeshPart& operator=(const MeshPart& other);
-		MeshPart& operator=(MeshPart&& other) noexcept;
-		
+
+        /**
+         * Move-operator of a mesh part.
+         * @param[in,out] other Other mesh part
+         * @return Reference to this mesh part
+         */
+        MeshPart& operator=(MeshPart&& other) noexcept;
+
+        /**
+         * Get the material used by this specific part of
+         * the mesh for rendering.
+         * @return Material
+         */
 		[[nodiscard]]
 		const material::Material& getMaterial() const;
-		
+
+        /**
+         * Return the axis aligned bounding box of this
+         * specific part of the mesh.
+         * @return Axis aligned bounding box of this mesh part
+         */
 		[[nodiscard]]
 		const Bounds& getBounds() const;
-		
+
+        /**
+         * Return the status if this part of the mesh is valid
+         * as boolean value.
+         * @return true if the mesh part is valid, otherwise false
+         */
 		explicit operator bool() const;
+
+        /**
+         * Return the status if this part of the mesh is invalid
+         * as boolean value.
+         * @return true if the mesh part is invalid, otherwise false
+         */
 		bool operator!() const;
 		
 	};
 
+    /** @} */
+
 }
diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp
index 1fcca5b9cbecf1064070d7737d008d2b108371db..51088f2564fb56a9d63d99238cb0665c6989bc9e 100644
--- a/modules/scene/include/vkcv/scene/Node.hpp
+++ b/modules/scene/include/vkcv/scene/Node.hpp
@@ -8,54 +8,151 @@
 #include "Mesh.hpp"
 
 namespace vkcv::scene {
+
+    /**
+     * @addtogroup vkcv_scene
+     * @{
+     */
 	
 	class Scene;
-	
+
+    /**
+     * A class to represent a graph node in a scene graph.
+     */
 	class Node {
 		friend class Scene;
 		
 	private:
+        /**
+         * Parent scene of the node.
+         */
 		Scene& m_scene;
-		
+
+        /**
+         * List of meshes added the node.
+         */
 		std::vector<Mesh> m_meshes;
+
+        /**
+         * List of child nodes added the node.
+         */
 		std::vector<Node> m_nodes;
+
+        /**
+         * Axis aligned bounding box of the node.
+         */
 		Bounds m_bounds;
-		
+
+        /**
+         * Constructor of a new node with a given scene as parent.
+         * @param[in,out] scene Scene
+         */
 		explicit Node(Scene& scene);
-		
+
+        /**
+         * Add a given mesh to this node for drawcall recording.
+         * @param[in] mesh Mesh
+         */
 		void addMesh(const Mesh& mesh);
-		
+
+        /**
+         * Load and add a mesh from a scene preloaded with the asset loader.
+         * @param[in] asset_scene Scene structure from asset loader
+         * @param[in] asset_mesh Mesh structure from asset loader
+         */
 		void loadMesh(const asset::Scene& asset_scene, const asset::Mesh& asset_mesh);
-		
+
+        /**
+         * Record drawcalls of all meshes of this node and its child nodes.
+         * @param[in] viewProjection View-transformation and projection as 4x4 matrix
+         * @param[out] pushConstants Structure to store push constants per drawcall
+         * @param[out] drawcalls List of drawcall structures
+         * @param[in] record Drawcall recording event function
+         */
 		void recordDrawcalls(const glm::mat4& viewProjection,
 							 PushConstants& pushConstants,
 							 std::vector<DrawcallInfo>& drawcalls,
 							 const RecordMeshDrawcallFunction& record);
-		
+
+        /**
+         * Splits child nodes into tree based graphs of nodes
+         * until all nodes contain an amount of meshes below
+         * a given maximum.
+         * @param[in] maxMeshesPerNode Maximum amount of meshes per node
+         */
 		void splitMeshesToSubNodes(size_t maxMeshesPerNode);
-		
+
+        /**
+         * Return the sum of drawcalls in the graph of this node.
+         * @return Amount of drawcalls
+         */
 		[[nodiscard]]
 		size_t getDrawcallCount() const;
-		
+
+        /**
+         * Add a new node as child to the scene graph with this node
+         * as parent and return its index.
+         * @return Index of the new node
+         */
 		size_t addNode();
-		
+
+        /**
+         * Get a reference to the child node with a given index.
+         * @param[in] index Valid index of a child node
+         * @return Matching child node
+         */
 		Node& getNode(size_t index);
-		
+
+        /**
+         * Get a const reference to the child node with a given index.
+         * @param[in] index Valid index of a child node
+         * @return Matching child node
+         */
 		[[nodiscard]]
 		const Node& getNode(size_t index) const;
 	
 	public:
+        /**
+         * Destructor of a scene node.
+         */
 		~Node();
-		
+
+        /**
+         * Copy-constructor of a scene node.
+         * @param[in] other Other scene node
+         */
 		Node(const Node& other) = default;
+
+        /**
+         * Move-constructor of a scene node.
+         * @param[in,out] other Other scene node
+         */
 		Node(Node&& other) = default;
-		
+
+        /**
+         * Copy-operator of a scene node.
+         * @param[in] other Other scene node
+         * @return Reference of this node
+         */
 		Node& operator=(const Node& other);
+
+        /**
+         * Move-operator of a scene node.
+         * @param[in,out] other Other scene node
+         * @return Reference of this node
+         */
 		Node& operator=(Node&& other) noexcept;
-		
+
+        /**
+         * Return the axis aligned bounding box of the
+         * scene node.
+         * @return Axis aligned bounding box of this node
+         */
 		[[nodiscard]]
 		const Bounds& getBounds() const;
 		
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp
index 095c5e278e9e3f76544e884bdb87cea10770307a..c482b464a8a24e83f1ba12d8294749d7b0cae48a 100644
--- a/modules/scene/include/vkcv/scene/Scene.hpp
+++ b/modules/scene/include/vkcv/scene/Scene.hpp
@@ -11,50 +11,159 @@
 #include "Node.hpp"
 
 namespace vkcv::scene {
-	
+
+    /**
+     * @defgroup vkcv_scene Scene Module
+     * A module to manage basic scene rendering with CPU-side frustum culling.
+     * @{
+     */
+
+    /**
+     * A class to represent a scene graph.
+     */
 	class Scene {
 		friend class MeshPart;
 		
 	private:
+        /**
+         * A nested structure to manage material storage.
+         */
 		struct Material {
+            /**
+             * The amount of active usages of the material.
+             */
 			size_t m_usages;
+
+            /**
+             * The actual material data.
+             */
 			material::Material m_data;
 		};
-		
+
+        /**
+         * A pointer to the current Core instance.
+         */
 		Core* m_core;
-		
+
+        /**
+         * A list of currently used materials.
+         */
 		std::vector<Material> m_materials;
+
+        /**
+         * A list of nodes in the first level of the scene graph.
+         */
 		std::vector<Node> m_nodes;
-		
+
+        /**
+         * Constructor of a scene instance with a given Core instance.
+         * @param[in,out] core Pointer to valid Core instance
+         */
 		explicit Scene(Core* core);
-		
+
+        /**
+         * Add a new node to the first level of the scene graph with
+         * this scene as parent and return its index.
+         * @return Index of the new node
+         */
 		size_t addNode();
-		
+
+        /**
+         * Get a reference to the first-level node with a given index.
+         * @param[in] index Valid index of a first-level node
+         * @return Matching first-level node
+         */
 		Node& getNode(size_t index);
-		
+
+        /**
+        * Get a const reference to the first-level node with a given index.
+        * @param[in] index Valid index of a first-level node
+        * @return Matching first-level node
+        */
+        [[nodiscard]]
 		const Node& getNode(size_t index) const;
-		
+
+        /**
+         * Increase the amount of usages for a certain material via its index.
+         * @param[in] index Index of a material
+         */
 		void increaseMaterialUsage(size_t index);
-		
+
+        /**
+         * Decrease the amount of usages for a certain material via its index.
+         * @param[in] index Index of a material
+         */
 		void decreaseMaterialUsage(size_t index);
-		
+
+        /**
+         * Load a material from a scene preloaded with the asset loader via
+         * its index.
+         * @param[in] index Valid index of a material
+         * @param[in] scene Scene structure from asset loader
+         * @param[in] material Material structure from asset loader
+         */
 		void loadMaterial(size_t index, const asset::Scene& scene,
 						  const asset::Material& material);
 		
 	public:
+        /**
+         * Destructor of a scene instance.
+         */
 		~Scene();
-		
+
+        /**
+         * Copy-constructor of a scene instance.
+         * @param[in] other Other scene instance
+         */
 		Scene(const Scene& other);
-		Scene(Scene&& other) noexcept;
-		
+
+        /**
+         * Move-constructor of a scene instance.
+         * @param[in,out] other Other scene instance
+         */
+        Scene(Scene&& other) noexcept;
+
+        /**
+         * Copy-operator of a scene instance.
+         * @param[in] other Other scene instance
+         * @return Reference to this scene
+         */
 		Scene& operator=(const Scene& other);
-		Scene& operator=(Scene&& other) noexcept;
-		
+
+        /**
+         * Move-operator of a scene instance.
+         * @param[in,out] other Other scene instance
+         * @return Reference to this scene
+         */
+        Scene& operator=(Scene&& other) noexcept;
+
+        /**
+         * Return the amount of materials managed by this scene.
+         * @return Amount of materials
+         */
+        [[nodiscard]]
 		size_t getMaterialCount() const;
-		
+
+        /**
+         * Get the material data by its certain index.
+         * The material can still be invalid if it was not loaded properly.
+         * @param[in] index Valid index of material
+         * @return Material
+         */
 		[[nodiscard]]
 		const material::Material& getMaterial(size_t index) const;
-		
+
+        /**
+         * Record drawcalls of all meshes of this scene with CPU-side frustum culling.
+         * @param cmdStream Command stream handle
+         * @param camera Scene viewing camera
+         * @param pass Render pass handle
+         * @param pipeline Graphics pipeline handle
+         * @param pushConstantsSizePerDrawcall Size of push constants per drawcall
+         * @param record Drawcall recording event function
+         * @param renderTargets Actual render targets
+         * @param windowHandle Window handle to use
+         */
 		void recordDrawcalls(CommandStreamHandle       		  &cmdStream,
 							 const camera::Camera			  &camera,
 							 const PassHandle                 &pass,
@@ -63,11 +172,25 @@ namespace vkcv::scene {
 							 const RecordMeshDrawcallFunction &record,
 							 const std::vector<ImageHandle>   &renderTargets,
 							 const WindowHandle               &windowHandle);
-		
+
+        /**
+         * Instantiation function to create a new scene instance.
+         * @param core Current Core instance
+         * @return New scene instance
+         */
 		static Scene create(Core& core);
-		
+
+        /**
+         * Load function to create a new scene instance with materials and meshes
+         * loaded from a file using the asset loader.
+         * @param core Current Core instance
+         * @param path Path of a valid file to load via asset loader
+         * @return New scene instance
+         */
 		static Scene load(Core& core, const std::filesystem::path &path);
 		
 	};
+
+    /** @} */
 	
 }
\ No newline at end of file
diff --git a/modules/scene/src/vkcv/scene/Bounds.cpp b/modules/scene/src/vkcv/scene/Bounds.cpp
index 731d81e928deae4c27f5c857de5b94dc3180888b..9614208d2d523117eef09e1432ff755005b5c51f 100644
--- a/modules/scene/src/vkcv/scene/Bounds.cpp
+++ b/modules/scene/src/vkcv/scene/Bounds.cpp
@@ -7,6 +7,11 @@ namespace vkcv::scene {
 	m_min(glm::vec3(0)),
 	m_max(glm::vec3(0)) {}
 	
+	Bounds::Bounds(const glm::vec3 &point) :
+	m_min(point),
+	m_max(point)
+	{}
+	
 	Bounds::Bounds(const glm::vec3 &min, const glm::vec3 &max) :
 	m_min(min),
 	m_max(max)
diff --git a/modules/scene/src/vkcv/scene/Frustum.cpp b/modules/scene/src/vkcv/scene/Frustum.cpp
index 1f63eb1d07002d24add81872627777048642dcdb..10af3bc44e4f585f990577bd9d95ecfade7acca8 100644
--- a/modules/scene/src/vkcv/scene/Frustum.cpp
+++ b/modules/scene/src/vkcv/scene/Frustum.cpp
@@ -3,10 +3,9 @@
 
 namespace vkcv::scene {
 	
-	static glm::vec3 transformPoint(const glm::mat4& transform, const glm::vec3& point, bool* negative_w) {
+	static glm::vec3 transformPoint(const glm::mat4& transform, const glm::vec3& point, bool& negative_w) {
 		const glm::vec4 position = transform * glm::vec4(point, 1.0f);
 		
-		
 		/*
 		 * We divide by the absolute of the 4th coorditnate because
 		 * clipping is weird and points have to move to the other
@@ -16,39 +15,35 @@ namespace vkcv::scene {
 		 * to know if all corners are behind the camera. So these can
 		 * be culled as well
 		 */
-		if (negative_w) {
-			const float perspective = std::abs(position[3]);
-			
-			*negative_w &= (position[3] < 0.0f);
-			
-			return glm::vec3(
-					position[0] / perspective,
-					position[1] / perspective,
-					position[2] / perspective
-			);
-		} else {
-			return glm::vec3(
-					position[0],
-					position[1],
-					position[2]
-			);
-		}
+		const float perspective = std::abs(position[3]);
+		negative_w &= (position[3] < 0.0f);
+		return glm::vec3(
+				position[0] / perspective,
+				position[1] / perspective,
+				position[2] / perspective
+		);
 	}
 	
-	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool* negative_w) {
+	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds) {
 		const auto corners = bounds.getCorners();
 		
-		if (negative_w) {
-			*negative_w = true;
+		Bounds result (glm::vec3(transform * glm::vec4(corners[0], 1.0f)));
+		
+		for (size_t j = 1; j < corners.size(); j++) {
+			result.extend(glm::vec3(transform * glm::vec4(corners[j], 1.0f)));
 		}
 		
-		auto projected = transformPoint(transform, corners[0], negative_w);
+		return result;
+	}
+	
+	Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool& negative_w) {
+		const auto corners = bounds.getCorners();
+		negative_w = true;
 		
-		Bounds result (projected, projected);
+		Bounds result (transformPoint(transform, corners[0], negative_w));
 		
 		for (size_t j = 1; j < corners.size(); j++) {
-			projected = transformPoint(transform, corners[j], negative_w);
-			result.extend(projected);
+			result.extend(transformPoint(transform, corners[j], negative_w));
 		}
 		
 		return result;
@@ -61,7 +56,7 @@ namespace vkcv::scene {
 		);
 		
 		bool negative_w;
-		auto box = transformBounds(transform, bounds, &negative_w);
+		auto box = transformBounds(transform, bounds, negative_w);
 		
 		if (negative_w) {
 			return false;
diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp
index c334cc3649550b33d9ecffd18c10865429e51591..50d14ed49d43496ada3853034be1455b044bd902 100644
--- a/modules/scene/src/vkcv/scene/MeshPart.cpp
+++ b/modules/scene/src/vkcv/scene/MeshPart.cpp
@@ -108,7 +108,7 @@ namespace vkcv::scene {
 		m_scene.increaseMaterialUsage(m_materialIndex);
 	}
 	
-	MeshPart::MeshPart(MeshPart &&other) :
+	MeshPart::MeshPart(MeshPart &&other) noexcept :
 			m_scene(other.m_scene),
 			m_vertices(other.m_vertices),
 			m_vertexBindings(other.m_vertexBindings),
diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
index cabc2a2628557254f0faed222b6b9f5c27429ad1..f62190753ec440c7d732551b6229276c5a42cfc1 100644
--- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp
@@ -9,33 +9,93 @@
 #include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::shader {
-	
+
+    /**
+     * @defgroup vkcv_shader Shader Compiler Module
+     * A module to use runtime shader compilation.
+     * @{
+     */
+
+    /**
+     * An event function type to be called on compilation completion.
+     */
 	typedef typename event_function<ShaderStage, const std::filesystem::path&>::type ShaderCompiledFunction;
+	
+	/**
+     * An event function type to be called on program compilation completion.
+     */
 	typedef typename event_function<ShaderProgram&>::type ShaderProgramCompiledFunction;
 	
+	/**
+     * An abstract class to handle runtime shader compilation.
+     */
 	class Compiler {
 	private:
 	protected:
+        /**
+         * A map containing macros for shader compilation.
+         */
 		std::unordered_map<std::string, std::string> m_defines;
 		
 	public:
+        /**
+         * Compile a shader from source for a target stage with a custom shader
+         * include path and an event function called if the compilation completes.
+         * @param[in] shaderStage Shader pipeline stage
+         * @param[in] shaderSource Source of shader
+         * @param[in] compiled Shader compilation event
+         * @param[in] includePath Include path for shaders
+         * @return Result if the compilation succeeds
+         */
 		virtual bool compileSource(ShaderStage shaderStage, const char* shaderSource,
 								   const ShaderCompiledFunction& compiled,
 								   const std::filesystem::path& includePath) = 0;
-		
+
+        /**
+         * Compile a shader from a specific file path for a target stage with
+         * a custom shader include path and an event function called if the
+         * compilation completes.
+         * @param[in] shaderStage Shader pipeline stage
+         * @param[in] shaderPath Filepath of shader
+         * @param[in] compiled Shader compilation event
+         * @param[in] includePath Include path for shaders
+         * @param[in] update Flag to update shaders during runtime
+         */
 		virtual void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath,
 							 const ShaderCompiledFunction& compiled,
 							 const std::filesystem::path& includePath, bool update) = 0;
 		
+		/**
+         * Compile a shader program from a specific map of given file paths for
+         * target pipeline stages with a custom shader include path and an event
+         * function called if the compilation completes.
+         * @param[in,out] program Shader program
+         * @param[in] stages Shader pipeline stages
+         * @param[in] compiled Shader program compilation event
+         * @param[in] includePath Include path for shaders
+         * @param[in] update Flag to update shaders during runtime
+         */
 		void compileProgram(ShaderProgram& program,
 							const std::unordered_map<ShaderStage, const std::filesystem::path>& stages,
 							const ShaderProgramCompiledFunction& compiled,
 							const std::filesystem::path& includePath = "", bool update = false);
 		
+		/**
+         * Return the definition value of a macro for shader compilation.
+         * @param[in] name Macro definition name
+         * @return Macro definition value
+         */
 		std::string getDefine(const std::string& name) const;
-		
+
+        /**
+         * Set a macro for shader compilation.
+         * @param[in] name Macro definition name
+         * @param[in] value Macro definition value
+         */
 		void setDefine(const std::string& name, const std::string& value);
 		
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
index eca84def118625e21df1c645cfc71b6bcddf7393..e457874ad2abc4cc3bfe9ab74fdb8d35446b5db1 100644
--- a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
+++ b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp
@@ -6,28 +6,83 @@
 #include "Compiler.hpp"
 
 namespace vkcv::shader {
-	
+
+    /**
+     * @addtogroup vkcv_shader
+     * @{
+     */
+
+    /**
+     * A class to handle GLSL runtime shader compilation.
+     */
 	class GLSLCompiler : public Compiler {
 	private:
 	public:
+        /**
+         * The constructor of a runtime GLSL shader compiler instance.
+         */
 		GLSLCompiler();
-		
+
+        /**
+         * The copy-constructor of a runtime GLSL shader compiler instance.
+         * @param[in] other Other instance of a GLSL shader compiler instance
+         */
 		GLSLCompiler(const GLSLCompiler& other);
+
+        /**
+         * The move-constructor of a runtime GLSL shader compiler instance.
+         * @param[out] other Other instance of a GLSL shader compiler instance
+         */
 		GLSLCompiler(GLSLCompiler&& other) = default;
-	
+
+        /**
+         * The destructor of a runtime GLSL shader compiler instance.
+         */
 		~GLSLCompiler();
-		
+
+        /**
+         * The copy-operator of a runtime GLSL shader compiler instance.
+         * @param[in] other Other instance of a GLSL shader compiler instance
+         * @return Reference to this instance
+         */
 		GLSLCompiler& operator=(const GLSLCompiler& other);
-		GLSLCompiler& operator=(GLSLCompiler&& other) = default;
-		
+
+        /**
+         * The copy-operator of a runtime GLSL shader compiler instance.
+         * @param[out] other Other instance of a GLSL shader compiler instance
+         * @return Reference to this instance
+         */
+        GLSLCompiler& operator=(GLSLCompiler&& other) = default;
+
+        /**
+         * Compile a GLSL shader from source for a target stage with a custom shader
+         * include path and an event function called if the compilation completes.
+         * @param[in] shaderStage Shader pipeline stage
+         * @param[in] shaderSource Source of shader
+         * @param[in] compiled Shader compilation event
+         * @param[in] includePath Include path for shaders
+         * @return Result if the compilation succeeds
+         */
 		bool compileSource(ShaderStage shaderStage, const char* shaderSource,
 						   const ShaderCompiledFunction& compiled,
-						   const std::filesystem::path& includePath);
-		
+						   const std::filesystem::path& includePath) override;
+
+        /**
+         * Compile a GLSL shader from a specific file path for a target stage with
+         * a custom shader include path and an event function called if the
+         * compilation completes.
+         * @param[in] shaderStage Shader pipeline stage
+         * @param[in] shaderPath Filepath of shader
+         * @param[in] compiled Shader compilation event
+         * @param[in] includePath Include path for shaders
+         * @param[in] update Flag to update shaders during runtime
+         */
 		void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath,
 					 const ShaderCompiledFunction& compiled,
 					 const std::filesystem::path& includePath = "", bool update = false) override;
 		
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
index 522b9f7e2798c194969112c984b59a832801d0ad..52569467e07a5155e1cf3619755bd092ecf6979b 100644
--- a/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp
@@ -3,16 +3,38 @@
 #include "Upscaling.hpp"
 
 namespace vkcv::upscaling {
-	
+
+    /**
+     * @addtogroup vkcv_upscaling
+     * @{
+     */
+
+    /**
+     * A class to handle upscaling via bilinear interpolation.
+     */
 	class BilinearUpscaling : public Upscaling {
 	private:
 	public:
+        /**
+         * Constructor to create instance for bilinear upscaling.
+         * @param[in,out] core Reference to a Core instance
+         */
 		explicit BilinearUpscaling(Core& core);
-		
+
+        /**
+         * Record the comands of the bilinear upscaling instance to
+         * scale the image of the input handle to the resolution of
+         * the output image handle via bilinear interpolation.
+         * @param[in] cmdStream Command stream handle to record commands
+         * @param[in] input Input image handle
+         * @param[in] output Output image handle
+         */
 		void recordUpscaling(const CommandStreamHandle& cmdStream,
 							 const ImageHandle& input,
 							 const ImageHandle& output) override;
 	
 	};
 
+    /** @} */
+
 }
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index 7b2e96bb62544db29775faa4473d0feccd2e813c..04f9ea72ffad7510f62163e045c89140b6fdecf7 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -5,46 +5,162 @@
 #include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::upscaling {
-	
+
+    /**
+     * @addtogroup vkcv_upscaling
+     * @{
+     */
+
+    /**
+     * Enum to set the mode of quality for
+     * FSR upscaling.
+     */
 	enum class FSRQualityMode : int {
+        /**
+         * Don't upscale anything.
+         */
 		NONE = 0,
+
+        /**
+         * Highest quality of FSR upscaling:
+         * 1.3x per dimension
+         */
 		ULTRA_QUALITY = 1,
+
+        /**
+         * High quality of FSR upscaling:
+         * 1.5x per dimension
+         */
 		QUALITY = 2,
+
+        /**
+         * Medium quality of FSR upscaling:
+         * 1.7x per dimension
+         */
 		BALANCED = 3,
+
+        /**
+         * Low quality of FSR upscaling:
+         * 2.0x per dimension
+         */
 		PERFORMANCE = 4
 	};
-	
+
+    /**
+     * Calculates the internal resolution for actual rendering if
+     * a specific mode of quality is used for upscaling with FSR.
+     * @param[in] mode Mode of quality
+     * @param[in] outputWidth Final resolution width
+     * @param[in] outputHeight Final resolution height
+     * @param[out] inputWidth Internal resolution width
+     * @param[out] inputHeight Internal resolution height
+     */
 	void getFSRResolution(FSRQualityMode mode,
 						  uint32_t outputWidth, uint32_t outputHeight,
 						  uint32_t &inputWidth, uint32_t &inputHeight);
-	
+
+    /**
+     * Returns the matching negative lod bias to reduce artifacts
+     * upscaling with FSR under a given mode of quality.
+     * @param mode Mode of quality
+     * @return Lod bias
+     */
 	float getFSRLodBias(FSRQualityMode mode);
-	
+
+    /**
+     * A structure to exchange required configuration
+     * with the shaders used by FSR upscaling.
+     */
 	struct FSRConstants {
+        /**
+         * 0th FSR constant.
+         */
 		uint32_t Const0 [4];
-		uint32_t Const1 [4];
-		uint32_t Const2 [4];
-		uint32_t Const3 [4];
-		uint32_t Sample [4];
+
+        /**
+         * 1st FSR constant.
+         */
+        uint32_t Const1 [4];
+
+        /**
+         * 2nd FSR constant.
+         */
+        uint32_t Const2 [4];
+
+        /**
+         * 3rd FSR constant.
+         */
+        uint32_t Const3 [4];
+
+        /**
+         * 4th FSR constant.
+         */
+        uint32_t Sample [4];
 	};
-	
+
+    /**
+     * A class to handle upscaling via FidelityFX Super Resolution.
+     * https://github.com/GPUOpen-Effects/FidelityFX-FSR
+     */
 	class FSRUpscaling : public Upscaling {
 	private:
+        /**
+         * The EASU compute pipeline of the FSR upscaling.
+         */
 		ComputePipelineHandle m_easuPipeline;
+
+        /**
+         * The RCAS compute pipeline of the FSR upscaling.
+         */
 		ComputePipelineHandle m_rcasPipeline;
 
+        /**
+         * The descriptor set layout of the EASU pipeline.
+         */
 		DescriptorSetLayoutHandle m_easuDescriptorSetLayout;
 
+        /**
+         * The descriptor set for the EASU pipeline.
+         */
 		DescriptorSetHandle m_easuDescriptorSet;
 
+        /**
+         * The descriptor set layout of the RCAS pipeline.
+         */
 		DescriptorSetLayoutHandle m_rcasDescriptorSetLayout;
+
+        /**
+         * The descriptor set for the RCAS pipeline.
+         */
 		DescriptorSetHandle m_rcasDescriptorSet;
-		
+
+        /**
+         * The buffer template to handle FSR constants for
+         * the EASU pipeline.
+         */
 		Buffer<FSRConstants> m_easuConstants;
+
+        /**
+         * The buffer template to handle FSR constants for
+         * the RCAS pipeline.
+         */
 		Buffer<FSRConstants> m_rcasConstants;
+
+        /**
+         * The image handle to store the intermidiate state of
+         * the FSR upscaling.
+         */
 		ImageHandle m_intermediateImage;
+
+        /**
+         * The sampler handle to use for accessing the images
+         * in the FSR upscaling process.
+         */
 		SamplerHandle m_sampler;
-		
+
+        /**
+         * Current state of HDR support.
+         */
 		bool m_hdr;
 		
 		/**
@@ -61,22 +177,54 @@ namespace vkcv::upscaling {
 		float m_sharpness;
 	
 	public:
+        /**
+         * Constructor to create instance for FSR upscaling.
+         * @param[in,out] core Reference to a Core instance
+         */
 		explicit FSRUpscaling(Core& core);
-		
+
+        /**
+         * Record the comands of the FSR upscaling instance to
+         * scale the image of the input handle to the resolution of
+         * the output image handle via FidelityFX Super Resolution.
+         * @param[in] cmdStream Command stream handle to record commands
+         * @param[in] input Input image handle
+         * @param[in] output Output image handle
+         */
 		void recordUpscaling(const CommandStreamHandle& cmdStream,
 							 const ImageHandle& input,
 							 const ImageHandle& output) override;
-		
+
+        /**
+         * Checks if HDR support is enabled and returns the status as boolean.
+         * @return true if HDR is supported, otherwise false
+         */
 		[[nodiscard]]
 		bool isHdrEnabled() const;
-		
+
+        /**
+         * Changes the status of HDR support of the FSR upscaling instance.
+         * @param[in] enabled New status of HDR support
+         */
 		void setHdrEnabled(bool enabled);
-		
+
+        /**
+         * Returns the amount of sharpness the FSR upscaling instance is using.
+         * @return The amount of sharpness
+         */
 		[[nodiscard]]
 		float getSharpness() const;
-		
+
+        /**
+         * Changes the amount of sharpness of the FSR upscaling instance.
+         * The new sharpness value is restricted by 0.0f as lower and 1.0f
+         * as upper boundary.
+         * @param[in] sharpness New sharpness value
+         */
 		void setSharpness(float sharpness);
 		
 	};
 
+    /** @} */
+
 }
diff --git a/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
index da6d5426237ee8e92d62f3755180d28bf316d4f5..12ba21a8576b3c638510b58341810df7aa039bfa 100644
--- a/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp
@@ -4,20 +4,46 @@
 #include <vkcv/Handles.hpp>
 
 namespace vkcv::upscaling {
-	
+
+    /**
+     * @defgroup vkcv_upscaling Upscaling Module
+     * A module to upscale an image from an internal resolution to a final resolution in realtime.
+     * @{
+     */
+
+    /**
+     * An abstract class to handle upscaling of images in realtime.
+     */
 	class Upscaling {
 	protected:
+        /**
+         * Reference to the current Core instance.
+         */
 		Core& m_core;
 	
 	public:
+        /**
+         * Constructor to create an upscaling instance.
+         * @param[in,out] core Reference to a Core instance
+         */
 		explicit Upscaling(Core& core);
 		
 		~Upscaling() = default;
-		
+
+        /**
+         * Record the comands of the given upscaling instance to
+         * scale the image of the input handle to the resolution of
+         * the output image handle.
+         * @param[in] cmdStream Command stream handle to record commands
+         * @param[in] input Input image handle
+         * @param[in] output Output image handle
+         */
 		virtual void recordUpscaling(const CommandStreamHandle& cmdStream,
 									 const ImageHandle& input,
 							 		 const ImageHandle& output) = 0;
 	
 	};
+
+    /** @} */
 	
 }
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 0a5e08acfd543ac8b2f439b423e97823d272e473..a2009440acffd1e9a82c4832b0d2cf4e1c92b34b 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -1,8 +1,8 @@
 
 #include "vkcv/upscaling/FSRUpscaling.hpp"
 
-#include <stdint.h>
-#include <math.h>
+#include <cstdint>
+#include <cmath>
 
 #define A_CPU 1
 #include <ffx_a.h>
@@ -240,11 +240,11 @@ namespace vkcv::upscaling {
 
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_easuConstants.getHandle(),true
 			);
 			
-			writes.samplerWrites.emplace_back(3, m_sampler);
+			writes.writeSampler(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 		}
@@ -261,11 +261,11 @@ namespace vkcv::upscaling {
 			}});
 
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_rcasConstants.getHandle(),true
 			);
 			
-			writes.samplerWrites.emplace_back(3, m_sampler);
+			writes.writeSampler(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
 		}
@@ -329,15 +329,15 @@ namespace vkcv::upscaling {
 		if (rcasEnabled) {
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, input);
-				writes.storageImageWrites.emplace_back(2, m_intermediateImage);
+				writes.writeSampledImage(1, input);
+				writes.writeStorageImage(2, m_intermediateImage);
 				
 				m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 			}
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, m_intermediateImage);
-				writes.storageImageWrites.emplace_back(2, output);
+				writes.writeSampledImage(1, m_intermediateImage);
+				writes.writeStorageImage(2, output);
 				
 				m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
 			}
@@ -374,8 +374,8 @@ namespace vkcv::upscaling {
 		} else {
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, input);
-				writes.storageImageWrites.emplace_back(2, output);
+				writes.writeSampledImage(1, input);
+				writes.writeStorageImage(2, output);
 				
 				m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 			}
diff --git a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
index 998d7f83e7a05d456dfe544a87953769181eada4..2fd8e23f6c0a3c615ec6085ad1abfdad1a9794ab 100644
--- a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
@@ -186,13 +186,13 @@ namespace vkcv::upscaling {
 			
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_scalerConstants.getHandle(), true
 			);
 			
-			writes.samplerWrites.emplace_back(1, m_sampler);
-			writes.sampledImageWrites.emplace_back(4, m_coefScaleImage);
-			writes.sampledImageWrites.emplace_back(5, m_coefUsmImage);
+			writes.writeSampler(1, m_sampler);
+			writes.writeSampledImage(4, m_coefScaleImage);
+			writes.writeSampledImage(5, m_coefUsmImage);
 			
 			m_core.writeDescriptorSet(m_scalerDescriptorSet, writes);
 		}
@@ -242,8 +242,8 @@ namespace vkcv::upscaling {
 		
 		{
 			DescriptorWrites writes;
-			writes.sampledImageWrites.emplace_back(2, input);
-			writes.storageImageWrites.emplace_back(3, output);
+			writes.writeSampledImage(2, input);
+			writes.writeStorageImage(3, output);
 			
 			m_core.writeDescriptorSet(m_scalerDescriptorSet, writes);
 		}
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index f8fa8db91fb9566771862b59ad9314c9fae2e288..0986b0910b6e7486c2dc3fc244269672a58d0730 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -109,7 +109,7 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 
-	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment }, vkcv::Multisampling::None);
 	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
 
 	if (!firstMeshPass) {
@@ -134,11 +134,10 @@ int main(int argc, const char** argv) {
     const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
 	
-	const vkcv::VertexLayout firstMeshLayout (bindings);
-
+	const vkcv::VertexLayout firstMeshLayout { bindings };
 	const std::unordered_map<uint32_t, vkcv::DescriptorBinding> &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0);
 
     std::unordered_map<uint32_t, vkcv::DescriptorBinding> adjustedBindings = descriptorBindings;
@@ -188,18 +187,20 @@ int main(int argc, const char** argv) {
 		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
 
 	vkcv::DescriptorWrites setWrites;
-	std::vector<vkcv::SampledImageDescriptorWrite> texturesArrayWrites;
+	
 	for(uint32_t i = 0; i < 6; i++)
 	{
-	    texturesArrayWrites.push_back(vkcv::SampledImageDescriptorWrite(1,
-                                                                        texturesArray[i].getHandle(),
-                                                                        0,
-                                                                        false,
-                                                                        i));
+		
+		setWrites.writeSampledImage(
+				1,
+				texturesArray[i].getHandle(),
+				0,
+				false,
+				i
+		);
 	}
 
-	setWrites.sampledImageWrites	= texturesArrayWrites;
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(0, sampler) };
+	setWrites.writeSampler(0, sampler);
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index c8da98abd87579c2b91b2422dda544dd257b03af..fe8acb3cfbb65de71763c2c30b50daf5f598234d 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -59,7 +59,11 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 
-	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassConfig firstMeshPassDefinition(
+			{ present_color_attachment, depth_attachment },
+			vkcv::Multisampling::None
+	);
+
 	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
 
 	if (!firstMeshPass) {
@@ -84,11 +88,10 @@ int main(int argc, const char** argv) {
     const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
 	
-	const vkcv::VertexLayout firstMeshLayout (bindings);
-
+	const vkcv::VertexLayout firstMeshLayout { bindings };
 
 	// since we only use one descriptor set (namely, desc set 0), directly address it
 	// recreate copies of the bindings and the handles (to check whether they are properly reused instead of actually recreated)
@@ -140,8 +143,8 @@ int main(int argc, const char** argv) {
 		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
 
 	vkcv::DescriptorWrites setWrites;
-	setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
+	setWrites.writeSampledImage(0, texture.getHandle());
+	setWrites.writeSampler(1, sampler);
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 	
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 3e424919d2289c45e129c6b476ff026455403982..3c4f51bb119f585e449aa48de2aef086d0789dd7 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -50,7 +50,11 @@ int main(int argc, const char** argv) {
 		vk::Format::eD32Sfloat
 	);
 
-	vkcv::PassConfig scenePassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassConfig scenePassDefinition(
+			{ present_color_attachment, depth_attachment },
+			vkcv::Multisampling::None
+	);
+	
 	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
 
 	if (!scenePass) {
@@ -68,12 +72,12 @@ int main(int argc, const char** argv) {
 
 	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
+	
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
 
-	const vkcv::VertexLayout sceneLayout(bindings);
-	
+	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
 
 	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 3bdefe3ae55fc89879461ed37025f8fe00e39a8a..c2d8bf817dd1d6b2c7cc069f2037ee090abc4415 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -33,7 +33,7 @@ int main(int argc, const char** argv) {
 		vkcv::AttachmentOperation::CLEAR,
 		core.getSwapchain(windowHandle).getFormat());
 
-	vkcv::PassConfig trianglePassDefinition({ present_color_attachment });
+	vkcv::PassConfig trianglePassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
 	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
 
 	if (!trianglePass)
@@ -51,8 +51,6 @@ int main(int argc, const char** argv) {
 		{vkcv::ShaderStage::VERTEX, "shaders/shader.vert"},
 		{ vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" }
 	}, nullptr);
-	
-	const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 
 	const vkcv::GraphicsPipelineConfig trianglePipelineDefinition {
 		triangleShaderProgram,
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 3eeec03a47d8051385523e8f3e3e146e0829aeda..89fb5e08d1c4a5ceec8c43f3c4043f8978d5d404 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -66,10 +66,18 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 	
-	vkcv::PassConfig linePassDefinition({ color_attachment0, depth_attachment0 });
+	vkcv::PassConfig linePassDefinition(
+			{ color_attachment0, depth_attachment0 },
+			vkcv::Multisampling::None
+	);
+	
 	vkcv::PassHandle linePass = core.createPass(linePassDefinition);
 	
-	vkcv::PassConfig scenePassDefinition({ color_attachment1, depth_attachment1 });
+	vkcv::PassConfig scenePassDefinition(
+			{ color_attachment1, depth_attachment1 },
+			vkcv::Multisampling::None
+	);
+	
 	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
 	
 	if ((!scenePass) || (!linePass)) {
@@ -95,8 +103,9 @@ int main(int argc, const char** argv) {
 	
 	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
+	
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
 	
 	const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(1);
@@ -113,9 +122,7 @@ int main(int argc, const char** argv) {
 	clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 	
 	vkcv::DescriptorWrites clipWrites;
-	clipWrites.uniformBufferWrites = {
-			vkcv::BufferDescriptorWrite(0, clipBuffer.getHandle())
-	};
+	clipWrites.writeUniformBuffer(0, clipBuffer.getHandle());
 	
 	core.writeDescriptorSet(clipDescriptorSet, clipWrites);
 	
@@ -141,8 +148,7 @@ int main(int argc, const char** argv) {
 		}
 	});
 	
-	const vkcv::VertexLayout sceneLayout(bindings);
-	
+	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
 	
 	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index cc897e68651de65c7122188b52598535e6637335..e6885b8e7dfa71c00335dbb2cee5c5994ce4eccc 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -73,8 +73,8 @@ bool App::initialize() {
 	m_cameraManager.getCamera(cameraIndex).setNearFar(0.1f, 30.f);
 	
 	vkcv::DescriptorWrites meshPassDescriptorWrites;
-	meshPassDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_gridTexture) };
-	meshPassDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
+	meshPassDescriptorWrites.writeSampledImage(0, m_gridTexture);
+	meshPassDescriptorWrites.writeSampler(1, m_linearSampler);
 	m_core.writeDescriptorSet(m_meshPass.descriptorSet, meshPassDescriptorWrites);
 
 	return true;
@@ -317,12 +317,9 @@ void App::run() {
 
 		// gamma correction
 		vkcv::DescriptorWrites gammaCorrectionDescriptorWrites;
-		gammaCorrectionDescriptorWrites.sampledImageWrites = {
-			vkcv::SampledImageDescriptorWrite(0, motionBlurOutput) };
-		gammaCorrectionDescriptorWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
-		gammaCorrectionDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(2, swapchainInput) };
+		gammaCorrectionDescriptorWrites.writeSampledImage(0, motionBlurOutput);
+		gammaCorrectionDescriptorWrites.writeSampler(1, m_linearSampler);
+		gammaCorrectionDescriptorWrites.writeStorageImage(2, swapchainInput);
 
 		m_core.writeDescriptorSet(m_gammaCorrectionPass.descriptorSet, gammaCorrectionDescriptorWrites);
 
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 1d40204b1ab7c6cd49a0c7924fa1fdbf6c2cc24e..342d2d705f831bc98705c9ecaaa5b369befda7b6 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -115,10 +115,10 @@ bool loadGraphicPass(
 	const std::vector<vkcv::VertexAttachment> vertexAttachments = shaderProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
 
-	const vkcv::VertexLayout vertexLayout(bindings);
+	const vkcv::VertexLayout vertexLayout { bindings };
 
 	const auto descriptorBindings = shaderProgram.getReflectedDescriptors();
 	const bool hasDescriptor = descriptorBindings.size() > 0;
@@ -169,7 +169,10 @@ bool loadMeshPass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 		core,
 		"assets/shaders/mesh.vert",
 		"assets/shaders/mesh.frag",
-		vkcv::PassConfig({ colorAttachment, depthAttachment }),
+		vkcv::PassConfig(
+				{ colorAttachment, depthAttachment },
+				vkcv::Multisampling::None
+		),
 		vkcv::DepthTest::Equal,
 		outHandles);
 }
@@ -192,7 +195,10 @@ bool loadSkyPass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 		core,
 		"assets/shaders/sky.vert",
 		"assets/shaders/sky.frag",
-		vkcv::PassConfig({ colorAttachment, depthAttachment }),
+		vkcv::PassConfig(
+				{ colorAttachment, depthAttachment },
+				vkcv::Multisampling::None
+		),
 		vkcv::DepthTest::Equal,
 		outHandles);
 }
@@ -214,7 +220,10 @@ bool loadPrePass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 		core,
 		"assets/shaders/prepass.vert",
 		"assets/shaders/prepass.frag",
-		vkcv::PassConfig({ motionAttachment, depthAttachment }),
+		vkcv::PassConfig(
+				{ motionAttachment, depthAttachment },
+				vkcv::Multisampling::None
+		),
 		vkcv::DepthTest::LessEqual,
 		outHandles);
 }
@@ -236,7 +245,10 @@ bool loadSkyPrePass(vkcv::Core& core, GraphicPassHandles* outHandles) {
 		core,
 		"assets/shaders/skyPrepass.vert",
 		"assets/shaders/skyPrepass.frag",
-		vkcv::PassConfig({ motionAttachment, depthAttachment }),
+		vkcv::PassConfig(
+				{ motionAttachment, depthAttachment },
+				vkcv::Multisampling::None
+		),
 		vkcv::DepthTest::LessEqual,
 		outHandles);
 }
diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp
index 30116c84b79ae71c683ee865dbf93dd1a37923e9..c9345684225e64f792a13ade2e5d11297ab7c444 100644
--- a/projects/indirect_dispatch/src/MotionBlur.cpp
+++ b/projects/indirect_dispatch/src/MotionBlur.cpp
@@ -75,14 +75,16 @@ bool MotionBlur::initialize(vkcv::Core* corePtr, const uint32_t targetWidth, con
 		true).getHandle();
 
 	vkcv::DescriptorWrites tileResetDescriptorWrites;
-	tileResetDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, m_fullPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(1, m_copyPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(2, m_fastPathWorkTileBuffer) };
+	tileResetDescriptorWrites.writeStorageBuffer(
+			0, m_fullPathWorkTileBuffer
+	).writeStorageBuffer(
+			1, m_copyPathWorkTileBuffer
+	).writeStorageBuffer(
+			2, m_fastPathWorkTileBuffer
+	);
 
 	m_core->writeDescriptorSet(m_tileResetPass.descriptorSet, tileResetDescriptorWrites);
 
-
 	m_renderTargets = MotionBlurSetup::createRenderTargets(targetWidth, targetHeight, *m_core);
 
 	m_nearestSampler = m_core->createSampler(
@@ -129,15 +131,20 @@ vkcv::ImageHandle MotionBlur::render(
 
 	// work tile classification
 	vkcv::DescriptorWrites tileClassificationDescriptorWrites;
-	tileClassificationDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, m_renderTargets.motionMaxNeighbourhood),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMinNeighbourhood) };
-	tileClassificationDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	tileClassificationDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, m_fullPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(4, m_copyPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(5, m_fastPathWorkTileBuffer) };
+	tileClassificationDescriptorWrites.writeSampledImage(
+			0, m_renderTargets.motionMaxNeighbourhood
+	).writeSampledImage(
+			1, m_renderTargets.motionMinNeighbourhood
+	);
+	
+	tileClassificationDescriptorWrites.writeSampler(2, m_nearestSampler);
+	tileClassificationDescriptorWrites.writeStorageBuffer(
+			3, m_fullPathWorkTileBuffer
+	).writeStorageBuffer(
+			4, m_copyPathWorkTileBuffer
+	).writeStorageBuffer(
+			5, m_fastPathWorkTileBuffer
+	);
 
 	m_core->writeDescriptorSet(m_tileClassificationPass.descriptorSet, tileClassificationDescriptorWrites);
 
@@ -174,44 +181,41 @@ vkcv::ImageHandle MotionBlur::render(
 	m_core->recordBufferMemoryBarrier(cmdStream, m_fastPathWorkTileBuffer);
 
 	vkcv::DescriptorWrites motionBlurDescriptorWrites;
-	motionBlurDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer),
-		vkcv::SampledImageDescriptorWrite(1, depthBuffer),
-		vkcv::SampledImageDescriptorWrite(2, motionBufferFullRes),
-		vkcv::SampledImageDescriptorWrite(3, m_renderTargets.motionMaxNeighbourhood) };
-	motionBlurDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(4, m_nearestSampler) };
-	motionBlurDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(5, m_renderTargets.outputColor) };
-	motionBlurDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(6, m_fullPathWorkTileBuffer)};
+	motionBlurDescriptorWrites.writeSampledImage(
+			0, colorBuffer
+	).writeSampledImage(
+			1, depthBuffer
+	).writeSampledImage(
+			2, motionBufferFullRes
+	).writeSampledImage(
+			3, m_renderTargets.motionMaxNeighbourhood
+	);
+	
+	motionBlurDescriptorWrites.writeSampler(4, m_nearestSampler);
+	motionBlurDescriptorWrites.writeStorageImage(5, m_renderTargets.outputColor);
+	motionBlurDescriptorWrites.writeStorageBuffer(6, m_fullPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_motionBlurPass.descriptorSet, motionBlurDescriptorWrites);
 
-
 	vkcv::DescriptorWrites colorCopyDescriptorWrites;
-	colorCopyDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-	colorCopyDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	colorCopyDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor) };
-	colorCopyDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, m_copyPathWorkTileBuffer) };
+	colorCopyDescriptorWrites.writeSampledImage(0, colorBuffer);
+	colorCopyDescriptorWrites.writeSampler(1, m_nearestSampler);
+	colorCopyDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
+	colorCopyDescriptorWrites.writeStorageBuffer(3, m_copyPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_colorCopyPass.descriptorSet, colorCopyDescriptorWrites);
 
 
 	vkcv::DescriptorWrites fastPathDescriptorWrites;
-	fastPathDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMaxNeighbourhood) };
-	fastPathDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	fastPathDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.outputColor) };
-	fastPathDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(4, m_fastPathWorkTileBuffer) };
+	fastPathDescriptorWrites.writeSampledImage(
+			0, colorBuffer
+	).writeSampledImage(
+			1, m_renderTargets.motionMaxNeighbourhood
+	);
+	
+	fastPathDescriptorWrites.writeSampler(2, m_nearestSampler);
+	fastPathDescriptorWrites.writeStorageImage(3, m_renderTargets.outputColor);
+	fastPathDescriptorWrites.writeStorageBuffer(4, m_fastPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_motionBlurFastPathPass.descriptorSet, fastPathDescriptorWrites);
 
@@ -279,16 +283,17 @@ vkcv::ImageHandle MotionBlur::render(
 	else if (mode == eMotionBlurMode::TileVisualisation) {
 
 		vkcv::DescriptorWrites visualisationDescriptorWrites;
-		visualisationDescriptorWrites.sampledImageWrites = { 
-			vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-		visualisationDescriptorWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-		visualisationDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor)};
-		visualisationDescriptorWrites.storageBufferWrites = {
-			vkcv::BufferDescriptorWrite(3, m_fullPathWorkTileBuffer),
-			vkcv::BufferDescriptorWrite(4, m_copyPathWorkTileBuffer),
-			vkcv::BufferDescriptorWrite(5, m_fastPathWorkTileBuffer) };
+		visualisationDescriptorWrites.writeSampledImage(0, colorBuffer);
+		visualisationDescriptorWrites.writeSampler(1, m_nearestSampler);
+		visualisationDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
+		
+		visualisationDescriptorWrites.writeStorageBuffer(
+				3, m_fullPathWorkTileBuffer
+		).writeStorageBuffer(
+				4, m_copyPathWorkTileBuffer
+		).writeStorageBuffer(
+				5, m_fastPathWorkTileBuffer
+		);
 
 		m_core->writeDescriptorSet(m_tileVisualisationPass.descriptorSet, visualisationDescriptorWrites);
 
@@ -345,12 +350,9 @@ vkcv::ImageHandle MotionBlur::renderMotionVectorVisualisation(
 	}
 
 	vkcv::DescriptorWrites motionVectorVisualisationDescriptorWrites;
-	motionVectorVisualisationDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, visualisationInput) };
-	motionVectorVisualisationDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	motionVectorVisualisationDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor) };
+	motionVectorVisualisationDescriptorWrites.writeSampledImage(0, visualisationInput);
+	motionVectorVisualisationDescriptorWrites.writeSampler(1, m_nearestSampler);
+	motionVectorVisualisationDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
 
 	m_core->writeDescriptorSet(
 		m_motionVectorVisualisationPass.descriptorSet,
@@ -383,13 +385,13 @@ void MotionBlur::computeMotionTiles(
 
 	// motion vector min max tiles
 	vkcv::DescriptorWrites motionVectorMaxTilesDescriptorWrites;
-	motionVectorMaxTilesDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, motionBufferFullRes) };
-	motionVectorMaxTilesDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	motionVectorMaxTilesDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.motionMax),
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.motionMin) };
+	motionVectorMaxTilesDescriptorWrites.writeSampledImage(0, motionBufferFullRes);
+	motionVectorMaxTilesDescriptorWrites.writeSampler(1, m_nearestSampler);
+	motionVectorMaxTilesDescriptorWrites.writeStorageImage(
+			2, m_renderTargets.motionMax
+	).writeStorageImage(
+			3, m_renderTargets.motionMin
+	);
 
 	m_core->writeDescriptorSet(m_motionVectorMinMaxPass.descriptorSet, motionVectorMaxTilesDescriptorWrites);
 
@@ -411,14 +413,18 @@ void MotionBlur::computeMotionTiles(
 
 	// motion vector min max neighbourhood
 	vkcv::DescriptorWrites motionVectorMaxNeighbourhoodDescriptorWrites;
-	motionVectorMaxNeighbourhoodDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, m_renderTargets.motionMax),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMin) };
-	motionVectorMaxNeighbourhoodDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	motionVectorMaxNeighbourhoodDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.motionMaxNeighbourhood),
-		vkcv::StorageImageDescriptorWrite(4, m_renderTargets.motionMinNeighbourhood) };
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeSampledImage(
+			0, m_renderTargets.motionMax
+	).writeSampledImage(
+			1, m_renderTargets.motionMin
+	);
+	
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeSampler(2, m_nearestSampler);
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeStorageImage(
+			3, m_renderTargets.motionMaxNeighbourhood
+	).writeStorageImage(
+			4, m_renderTargets.motionMinNeighbourhood
+	);
 
 	m_core->writeDescriptorSet(m_motionVectorMinMaxNeighbourhoodPass.descriptorSet, motionVectorMaxNeighbourhoodDescriptorWrites);
 
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index 2a213a2ad7b8ecdaf4b4a51cf4327addc7a881a5..16e3e83994a1a7ca14fa2163799ee8d034eb8deb 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -334,7 +334,7 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 
-	vkcv::PassConfig passDefinition({ present_color_attachment, depth_attachment });
+	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;
@@ -361,7 +361,9 @@ int main(int argc, const char** argv) {
 
     // vertex layout for the pipeline. (assumed to be) used by all sponza meshes.
     const std::vector<vkcv::VertexAttachment> vertexAttachments = sponzaProgram.getVertexAttachments();
-	const vkcv::VertexLayout sponzaVertexLayout({ vkcv::VertexBinding(0, { vertexAttachments }) });
+	const vkcv::VertexLayout sponzaVertexLayout {
+		{ vkcv::createVertexBinding(0, { vertexAttachments }) }
+	};
 
     std::vector<uint8_t> compiledVertexBuffer; // IGNORED, since the vertex buffer is not interleaved!
 
@@ -444,18 +446,17 @@ int main(int argc, const char** argv) {
             vkcv::SamplerMipmapMode::LINEAR,
             vkcv::SamplerAddressMode::REPEAT
     );
-
+	
+	vkcv::DescriptorWrites setWrites;
+	
     std::vector<vkcv::SampledImageDescriptorWrite> textureArrayWrites;
     for(uint32_t i = 0; i < compiledMaterial.baseColor.size(); i++)
     {
-        vkcv::SampledImageDescriptorWrite baseColorWrite(2, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
-        textureArrayWrites.push_back(baseColorWrite);
+		setWrites.writeSampledImage(2, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
     }
-
-    vkcv::DescriptorWrites setWrites;
-    setWrites.sampledImageWrites	= textureArrayWrites;
-    setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(0, standardSampler) };
-	setWrites.storageBufferWrites   = { vkcv::BufferDescriptorWrite(1, modelBuffer.getHandle())};
+    
+    setWrites.writeSampler(0, standardSampler);
+	setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
 	const vkcv::GraphicsPipelineConfig sponzaPipelineConfig {
@@ -481,29 +482,10 @@ int main(int argc, const char** argv) {
             vkcv::BufferType::UNIFORM,
             1);
 
-    //Plane dummyPlane{};
-    //dummyPlane.pointOnPlane = glm::vec3(0.0f);
-    //dummyPlane.padding0 = 0.0f;
-    //dummyPlane.normal = glm::vec3(0.0f);
-    //dummyPlane.padding1 = 0.0f;
-
-    //CameraPlanes dummyCameraPlane{};
-    //dummyCameraPlane.planes[0] = dummyPlane;
-    //dummyCameraPlane.planes[1] = dummyPlane;
-    //dummyCameraPlane.planes[2] = dummyPlane;
-    //dummyCameraPlane.planes[3] = dummyPlane;
-    //dummyCameraPlane.planes[4] = dummyPlane;
-    //dummyCameraPlane.planes[5] = dummyPlane;
-
-    //cameraPlaneBuffer.fill(&dummyCameraPlane);
-
-    vkcv::BufferDescriptorWrite cameraPlaneWrite(0, cameraPlaneBuffer.getHandle());
-    vkcv::BufferDescriptorWrite drawCommandsWrite(1, indirectBuffer.getHandle());
-    vkcv::BufferDescriptorWrite boundingBoxWrite(2, boundingBoxBuffer.getHandle());
-
     vkcv::DescriptorWrites cullingWrites;
-    cullingWrites.storageBufferWrites = {drawCommandsWrite, boundingBoxWrite};
-    cullingWrites.uniformBufferWrites = {cameraPlaneWrite};
+	cullingWrites.writeStorageBuffer(1, indirectBuffer.getHandle());
+	cullingWrites.writeStorageBuffer(2, boundingBoxBuffer.getHandle());
+    cullingWrites.writeUniformBuffer(0, cameraPlaneBuffer.getHandle());
     core.writeDescriptorSet(cullingDescSet, cullingWrites);
 
 
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index afaec1a8ba5dded5f16bad65c68f25f442029091..a74561ca07f7a052fe71c9e1d1efc751c2ab258c 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -168,7 +168,11 @@ int main(int argc, const char** argv) {
             vk::Format::eD32Sfloat
     );
 
-	vkcv::PassConfig bunnyPassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassConfig bunnyPassDefinition(
+			{ present_color_attachment, depth_attachment },
+			vkcv::Multisampling::None
+	);
+	
 	vkcv::PassHandle renderPass = core.createPass(bunnyPassDefinition);
 
 	if (!renderPass)
@@ -193,9 +197,9 @@ int main(int argc, const char** argv) {
     const std::vector<vkcv::VertexAttachment> vertexAttachments = bunnyShaderProgram.getVertexAttachments();
     std::vector<vkcv::VertexBinding> bindings;
     for (size_t i = 0; i < vertexAttachments.size(); i++) {
-        bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+        bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
     }
-    const vkcv::VertexLayout bunnyLayout (bindings);
+    const vkcv::VertexLayout bunnyLayout { bindings };
 
     vkcv::DescriptorSetLayoutHandle vertexShaderDescriptorSetLayout = core.createDescriptorSetLayout(bunnyShaderProgram.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle vertexShaderDescriptorSet = core.createDescriptorSet(vertexShaderDescriptorSetLayout);
@@ -218,7 +222,7 @@ int main(int argc, const char** argv) {
 	vkcv::Buffer<ObjectMatrices> matrixBuffer = core.createBuffer<ObjectMatrices>(vkcv::BufferType::STORAGE, objectCount);
 
 	vkcv::DescriptorWrites vertexShaderDescriptorWrites;
-	vertexShaderDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, matrixBuffer.getHandle()) };
+	vertexShaderDescriptorWrites.writeStorageBuffer(0, matrixBuffer.getHandle());
 	core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
 
 	vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
@@ -271,16 +275,19 @@ int main(int argc, const char** argv) {
 	vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(vkcv::BufferType::UNIFORM, 1);
 
 	vkcv::DescriptorWrites meshShaderWrites;
-	meshShaderWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, meshShaderVertexBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(1, meshShaderIndexBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(2, meshletBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(4, matrixBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(5, meshletBuffer.getHandle()),
-	};
-	meshShaderWrites.uniformBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, cameraPlaneBuffer.getHandle()),
-	};
+	meshShaderWrites.writeStorageBuffer(
+			0, meshShaderVertexBuffer.getHandle()
+	).writeStorageBuffer(
+			1, meshShaderIndexBuffer.getHandle()
+	).writeStorageBuffer(
+			2, meshletBuffer.getHandle()
+	).writeStorageBuffer(
+			4, matrixBuffer.getHandle()
+	).writeStorageBuffer(
+			5, meshletBuffer.getHandle()
+	);
+	
+	meshShaderWrites.writeUniformBuffer(3, cameraPlaneBuffer.getHandle());
 
     core.writeDescriptorSet( meshShaderDescriptorSet, meshShaderWrites);
 
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index f1490e6f035b1a378afcb59436814986b3aca51f..db538796201ee4c1cf5830bfd82036f16a82e693 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -39,7 +39,7 @@ int main(int argc, const char **argv) {
             colorFormat);
 
 
-    vkcv::PassConfig particlePassDefinition({present_color_attachment});
+    vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
     vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
 
     vkcv::PassConfig computePassDefinition({});
@@ -83,9 +83,9 @@ int main(int argc, const char **argv) {
 
     std::vector<vkcv::VertexBinding> computeBindings;
     for (size_t i = 0; i < computeVertexAttachments.size(); i++) {
-        computeBindings.push_back(vkcv::VertexBinding(i, { computeVertexAttachments[i] }));
+        computeBindings.push_back(vkcv::createVertexBinding(i, { computeVertexAttachments[i] }));
     }
-    const vkcv::VertexLayout computeLayout(computeBindings);
+    const vkcv::VertexLayout computeLayout { computeBindings };
 
     vkcv::ShaderProgram particleShaderProgram{};
     compiler.compile(vkcv::ShaderStage::VERTEX, "shaders/shader.vert", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
@@ -110,10 +110,10 @@ int main(int argc, const char **argv) {
 
     std::vector<vkcv::VertexBinding> bindings;
     for (size_t i = 0; i < vertexAttachments.size(); i++) {
-        bindings.push_back(vkcv::VertexBinding(i, {vertexAttachments[i]}));
+        bindings.push_back(vkcv::createVertexBinding(i, {vertexAttachments[i]}));
     }
 
-    const vkcv::VertexLayout particleLayout(bindings);
+    const vkcv::VertexLayout particleLayout { bindings };
 
     vkcv::GraphicsPipelineConfig particlePipelineDefinition{
             particleShaderProgram,
@@ -161,13 +161,12 @@ int main(int argc, const char **argv) {
     particleBuffer.fill(particleSystem.getParticles());
 
     vkcv::DescriptorWrites setWrites;
-    setWrites.uniformBufferWrites = {vkcv::BufferDescriptorWrite(0,color.getHandle()),
-                                     vkcv::BufferDescriptorWrite(1,position.getHandle())};
-    setWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(2,particleBuffer.getHandle())};
+    setWrites.writeUniformBuffer(0, color.getHandle()).writeUniformBuffer(1, position.getHandle());
+    setWrites.writeStorageBuffer(2, particleBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
     vkcv::DescriptorWrites computeWrites;
-    computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,particleBuffer.getHandle())};
+    computeWrites.writeStorageBuffer(0, particleBuffer.getHandle());
     core.writeDescriptorSet(computeDescriptorSet, computeWrites);
 
     if (!particlePipeline || !computePipeline)
@@ -308,10 +307,12 @@ int main(int argc, const char **argv) {
         core.prepareImageForStorage(cmdStream, swapchainInput);
 
         vkcv::DescriptorWrites tonemappingDescriptorWrites;
-        tonemappingDescriptorWrites.storageImageWrites = {
-            vkcv::StorageImageDescriptorWrite(0, colorBuffer),
-            vkcv::StorageImageDescriptorWrite(1, swapchainInput)
-        };
+        tonemappingDescriptorWrites.writeStorageImage(
+				0, colorBuffer
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
         core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites);
 
         uint32_t tonemappingDispatchCount[3];
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index b7c495c070bd354dd58c0fad3f857489ad7408e7..670986fff81d4f308aa063e6275f41872bc8e878 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -11,7 +11,7 @@ int main(int argc, const char** argv) {
 	// structs must match shader version
 	struct Material {
 		Material(const glm::vec3& emission, const glm::vec3& albedo, float ks, float roughness, const glm::vec3& f0)
-			: emission(emission), albedo(albedo), ks(ks), roughness(roughness), f0(f0){}
+			: emission(emission), ks(ks), albedo(albedo), roughness(roughness), f0(f0), padding() {}
 
 		glm::vec3   emission;
 		float       ks;
@@ -22,7 +22,8 @@ int main(int argc, const char** argv) {
 	};
 
 	struct Sphere {
-		Sphere(const glm::vec3& c, const float& r, const int m) : center(c), radius(r), materialIndex(m) {}
+		Sphere(const glm::vec3& c, const float& r, const int m)
+			: center(c), radius(r), materialIndex(m), padding() {}
 
 		glm::vec3   center;
 		float       radius;
@@ -32,7 +33,7 @@ int main(int argc, const char** argv) {
 
 	struct Plane {
 		Plane(const glm::vec3& c, const glm::vec3& n, const glm::vec2 e, int m)
-			: center(c), normal(n), extent(e), materialIndex(m) {}
+			: center(c), materialIndex(m), normal(n), padding1(), extent(e), padding3() {}
 
 		glm::vec3   center;
 		uint32_t    materialIndex;
@@ -107,10 +108,7 @@ int main(int argc, const char** argv) {
 	});
 
 	vkcv::DescriptorWrites imageCombineDescriptorWrites;
-	imageCombineDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(0, outputImage),
-		vkcv::StorageImageDescriptorWrite(1, meanImage)
-	};
+	imageCombineDescriptorWrites.writeStorageImage(0, outputImage).writeStorageImage(1, meanImage);
 	core.writeDescriptorSet(imageCombineDescriptorSet, imageCombineDescriptorWrites);
 
 	// image present shader
@@ -144,9 +142,7 @@ int main(int argc, const char** argv) {
 	});
 
 	vkcv::DescriptorWrites imageClearDescriptorWrites;
-	imageClearDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(0, meanImage)
-	};
+	imageClearDescriptorWrites.writeStorageImage(0, meanImage);
 	core.writeDescriptorSet(imageClearDescriptorSet, imageClearDescriptorWrites);
 
 	// buffers
@@ -193,12 +189,15 @@ int main(int argc, const char** argv) {
 		materialSettings.size());
 
 	vkcv::DescriptorWrites traceDescriptorWrites;
-	traceDescriptorWrites.storageBufferWrites = { 
-		vkcv::BufferDescriptorWrite(0, sphereBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(1, planeBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(2, materialBuffer.getHandle())};
-	traceDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, outputImage)};
+	traceDescriptorWrites.writeStorageBuffer(
+			0, sphereBuffer.getHandle()
+	).writeStorageBuffer(
+			1, planeBuffer.getHandle()
+	).writeStorageBuffer(
+			2, materialBuffer.getHandle()
+	);
+	
+	traceDescriptorWrites.writeStorageImage(3, outputImage);
 	core.writeDescriptorSet(traceDescriptorSet, traceDescriptorWrites);
 
 	vkcv::ComputePipelineHandle tracePipeline = core.createComputePipeline({
@@ -271,21 +270,20 @@ int main(int argc, const char** argv) {
 				true).getHandle();
 
 			// update descriptor sets
-			traceDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(3, outputImage) };
+			traceDescriptorWrites.writeStorageImage(3, outputImage);
 			core.writeDescriptorSet(traceDescriptorSet, traceDescriptorWrites);
 
 			vkcv::DescriptorWrites imageCombineDescriptorWrites;
-			imageCombineDescriptorWrites.storageImageWrites = {
-				vkcv::StorageImageDescriptorWrite(0, outputImage),
-				vkcv::StorageImageDescriptorWrite(1, meanImage)
-			};
+			imageCombineDescriptorWrites.writeStorageImage(
+					0, outputImage
+			).writeStorageImage(
+					1, meanImage
+			);
+			
 			core.writeDescriptorSet(imageCombineDescriptorSet, imageCombineDescriptorWrites);
 
 			vkcv::DescriptorWrites imageClearDescriptorWrites;
-			imageClearDescriptorWrites.storageImageWrites = {
-				vkcv::StorageImageDescriptorWrite(0, meanImage)
-			};
+			imageClearDescriptorWrites.writeStorageImage(0, meanImage);
 			core.writeDescriptorSet(imageClearDescriptorSet, imageClearDescriptorWrites);
 
 			widthPrevious  = swapchainWidth;
@@ -396,9 +394,12 @@ int main(int argc, const char** argv) {
 		const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
 		vkcv::DescriptorWrites presentDescriptorWrites;
-		presentDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(0, meanImage),
-			vkcv::StorageImageDescriptorWrite(1, swapchainInput) };
+		presentDescriptorWrites.writeStorageImage(
+				0, meanImage
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
 		core.writeDescriptorSet(presentDescriptorSet, presentDescriptorWrites);
 
 		core.prepareImageForStorage(cmdStream, swapchainInput);
diff --git a/projects/rtx_ambient_occlusion/src/RTX/RTX.cpp b/projects/rtx_ambient_occlusion/src/RTX/RTX.cpp
index 00533bc3668a54f245777c7bca4abb56afd3f056..47560b4d9fddb867dd5573c64fe57c24c69095ce 100644
--- a/projects/rtx_ambient_occlusion/src/RTX/RTX.cpp
+++ b/projects/rtx_ambient_occlusion/src/RTX/RTX.cpp
@@ -147,23 +147,23 @@ namespace vkcv::rtx {
 
     void RTXModule::createRTXPipelineAndLayout(uint32_t pushConstantSize, std::vector<DescriptorSetLayoutHandle> descriptorSetLayouts, ShaderProgram &rtxShader) {
         // -- process vkcv::ShaderProgram into vk::ShaderModule
-        std::vector<char> rayGenShaderCode = rtxShader.getShader(ShaderStage::RAY_GEN).shaderCode;
+        std::vector<uint32_t> rayGenShaderCode = rtxShader.getShaderBinary(ShaderStage::RAY_GEN);
 
         vk::ShaderModuleCreateInfo rayGenShaderModuleInfo(
             vk::ShaderModuleCreateFlags(), // vk::ShaderModuleCreateFlags flags_,
-            rayGenShaderCode.size(), // size_t codeSize
-            (const uint32_t*)rayGenShaderCode.data() // const uint32_t* pCode
+            rayGenShaderCode.size() * sizeof(uint32_t), // size_t codeSize
+            rayGenShaderCode.data() // const uint32_t* pCode
         );
         vk::ShaderModule rayGenShaderModule = m_core->getContext().getDevice().createShaderModule(rayGenShaderModuleInfo);
         if (!rayGenShaderModule) {
             vkcv_log(LogLevel::ERROR, "The Ray Generation Shader Module could not be created!");
         }
 
-        std::vector<char> rayMissShaderCode = rtxShader.getShader(ShaderStage::RAY_MISS).shaderCode;
+        std::vector<uint32_t> rayMissShaderCode = rtxShader.getShaderBinary(ShaderStage::RAY_MISS);
         vk::ShaderModuleCreateInfo rayMissShaderModuleInfo(
             vk::ShaderModuleCreateFlags(), // vk::ShaderModuleCreateFlags flags_,
-            rayMissShaderCode.size(), //size_t codeSize
-            (const uint32_t*)rayMissShaderCode.data() // const uint32_t* pCode
+            rayMissShaderCode.size() * sizeof(uint32_t), //size_t codeSize
+            rayMissShaderCode.data() // const uint32_t* pCode
         );
 
         vk::ShaderModule rayMissShaderModule = m_core->getContext().getDevice().createShaderModule(rayMissShaderModuleInfo);
@@ -171,11 +171,11 @@ namespace vkcv::rtx {
             vkcv_log(LogLevel::ERROR, "The Ray Miss Shader Module could not be created!");
         }
 
-        std::vector<char> rayClosestHitShaderCode = rtxShader.getShader(ShaderStage::RAY_CLOSEST_HIT).shaderCode;
+        std::vector<uint32_t> rayClosestHitShaderCode = rtxShader.getShaderBinary(ShaderStage::RAY_CLOSEST_HIT);
         vk::ShaderModuleCreateInfo rayClosestHitShaderModuleInfo(
             vk::ShaderModuleCreateFlags(), // vk::ShaderModuleCreateFlags flags_,
-            rayClosestHitShaderCode.size(), //size_t codeSize
-            (const uint32_t*)rayClosestHitShaderCode.data() // const uint32_t* pCode_
+            rayClosestHitShaderCode.size() * sizeof(uint32_t), //size_t codeSize
+            rayClosestHitShaderCode.data() // const uint32_t* pCode_
         );
         vk::ShaderModule rayClosestHitShaderModule = m_core->getContext().getDevice().createShaderModule(rayClosestHitShaderModuleInfo);
         if (!rayClosestHitShaderModule) {
diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp
index becd80c4e4478da38a8e3722cbf30d39fd159ca6..0276f05db5bece4416578d89da1fd7a7b31336ca 100644
--- a/projects/rtx_ambient_occlusion/src/main.cpp
+++ b/projects/rtx_ambient_occlusion/src/main.cpp
@@ -135,7 +135,7 @@ int main(int argc, const char** argv) {
 
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
-		rtxWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, swapchainInput) };
+		rtxWrites.writeStorageImage(0, swapchainInput);
 		core.writeDescriptorSet(rtxShaderDescriptorSet, rtxWrites);
 
 		core.prepareImageForStorage(cmdStream, swapchainInput);
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 84087c1eabe8aa32e3ac3f9ebe9c7d9936f52d9e..68bc546ded40e7f45454d62bfc4e8cd7227da4b7 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -5,10 +5,9 @@
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <chrono>
-#include <limits>
 #include <cmath>
 #include <vector>
-#include <string.h>	// memcpy(3)
+#include <cstring>
 #include "safrScene.hpp"
 
 
@@ -87,9 +86,9 @@ int main(int argc, const char** argv) {
 
 	std::vector<vkcv::VertexBinding> computeBindings;
 	for (size_t i = 0; i < computeVertexAttachments.size(); i++) {
-		computeBindings.push_back(vkcv::VertexBinding(i, { computeVertexAttachments[i] }));
+		computeBindings.push_back(vkcv::createVertexBinding(i, { computeVertexAttachments[i] }));
 	}
-	const vkcv::VertexLayout computeLayout(computeBindings);
+	const vkcv::VertexLayout computeLayout { computeBindings };
 	
 	/*
 	* create the scene
@@ -146,8 +145,12 @@ int main(int argc, const char** argv) {
 	sphereBuffer.fill(spheres);
 
 	vkcv::DescriptorWrites computeWrites;
-	computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,lightsBuffer.getHandle()),
-                                          vkcv::BufferDescriptorWrite(1,sphereBuffer.getHandle())};
+	computeWrites.writeStorageBuffer(
+			0, lightsBuffer.getHandle()
+	).writeStorageBuffer(
+			1, sphereBuffer.getHandle()
+	);
+	
     core.writeDescriptorSet(computeDescriptorSet, computeWrites);
 
 	auto safrIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
@@ -160,7 +163,7 @@ int main(int argc, const char** argv) {
 		vkcv::AttachmentOperation::CLEAR,
 		core.getSwapchain(windowHandle).getFormat());
 
-	vkcv::PassConfig safrPassDefinition({ present_color_attachment });
+	vkcv::PassConfig safrPassDefinition({ present_color_attachment }, vkcv::Multisampling::None);
 	vkcv::PassHandle safrPass = core.createPass(safrPassDefinition);
 
 	if (!safrPass)
@@ -254,7 +257,7 @@ int main(int argc, const char** argv) {
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
 		//configure the outImage for compute shader (render into the swapchain image)
-        computeWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, swapchainInput)};
+        computeWrites.writeStorageImage(2, swapchainInput);
         core.writeDescriptorSet(computeDescriptorSet, computeWrites);
         core.prepareImageForStorage (cmdStream, swapchainInput);
 
diff --git a/projects/saf_r/src/safrScene.hpp b/projects/saf_r/src/safrScene.hpp
index 33a298f82121971021d1912e6c1205e9c48a49f0..fc149a7b6ba11fd832cf7ec1040d57c401bab87a 100644
--- a/projects/saf_r/src/safrScene.hpp
+++ b/projects/saf_r/src/safrScene.hpp
@@ -28,7 +28,7 @@ public:
 	*/
 	struct Material {
 		Material(const glm::vec4& a, const glm::vec3& color, const float& spec, const float& r) : albedo(a), diffuse_color(color), specular_exponent(spec), refractive_index(r) {}
-		Material() : refractive_index(1), albedo(1, 0, 0, 0), diffuse_color(), specular_exponent() {}
+		Material() : albedo(1, 0, 0, 0), diffuse_color(), specular_exponent(), refractive_index(1) {}
         glm::vec4 albedo;
         alignas(16) glm::vec3 diffuse_color;
         float specular_exponent;
diff --git a/projects/sph/src/PipelineInit.cpp b/projects/sph/src/PipelineInit.cpp
index 052c983cb094114853d19dac3e76149db99116db..e507f1edebf6e39fb65bf81dbd4cf4915602313b 100644
--- a/projects/sph/src/PipelineInit.cpp
+++ b/projects/sph/src/PipelineInit.cpp
@@ -15,9 +15,9 @@ vkcv::DescriptorSetHandle PipelineInit::ComputePipelineInit(vkcv::Core *pCore, v
 
     std::vector<vkcv::VertexBinding> bindings;
     for (size_t i = 0; i < vertexAttachments.size(); i++) {
-        bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+        bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
     }
-    const vkcv::VertexLayout layout(bindings);
+    const vkcv::VertexLayout layout { bindings };
 
     pipeline = pCore->createComputePipeline({
             shaderProgram,
diff --git a/projects/sph/src/PipelineInit.hpp b/projects/sph/src/PipelineInit.hpp
index e628af0eef9c0558719b405790246946d8720d47..54979cfdaffb2aba0915f87552e75e6d2ad3a958 100644
--- a/projects/sph/src/PipelineInit.hpp
+++ b/projects/sph/src/PipelineInit.hpp
@@ -5,6 +5,14 @@
 
 class PipelineInit{
 public:
+    /**
+     * Helperfunction to initialize a compute Pipeline. Goal is to reduce repetitive code in main.
+     * @param pCore Pointer to core object
+     * @param shaderStage Type of shaderstage - currently only supports COMPUTE
+     * @param includePath filepath to shaderprogram
+     * @param pipeline handle of the pipeline that is to be initialized. This handle is replaced with the handle of the generated pipeline
+     * @return returns the descriptorset handle from the generated descriptorset of the reflected shader
+     */
     static vkcv::DescriptorSetHandle ComputePipelineInit(vkcv::Core *pCore,
                                                          vkcv::ShaderStage shaderStage,
                                                          std::filesystem::path includePath,
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index dafea94220345d0ec4b01b77fecd970d2a23c6b1..601075421a7bf2814e10514ae010fc83b7024f0a 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -1,13 +1,9 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
-#include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <random>
-#include <glm/glm.hpp>
-#include <glm/gtc/matrix_access.hpp>
-#include <glm/gtc/matrix_transform.hpp>
-#include <time.h>
+#include <ctime>
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <vkcv/effects/BloomAndFlaresEffect.hpp>
 #include "PipelineInit.hpp"
@@ -16,6 +12,7 @@
 int main(int argc, const char **argv) {
     const char *applicationName = "SPH";
 
+    // creating core object that will handle all vulkan objects
     vkcv::Core core = vkcv::Core::create(
         applicationName,
         VK_MAKE_VERSION(0, 0, 1),
@@ -41,7 +38,7 @@ int main(int argc, const char **argv) {
             colorFormat);
 
 
-    vkcv::PassConfig particlePassDefinition({present_color_attachment});
+    vkcv::PassConfig particlePassDefinition({present_color_attachment}, vkcv::Multisampling::None);
     vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
 
     vkcv::PassConfig computePassDefinition({});
@@ -68,26 +65,26 @@ int main(int argc, const char **argv) {
     }
 	vkcv::shader::GLSLCompiler compiler;
 
-// comp shader 1
-    vkcv::ComputePipelineHandle computePipeline1;
-    vkcv::DescriptorSetHandle computeDescriptorSet1 = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
-                                                                          "shaders/pressure.comp", computePipeline1);
-// comp shader 2
-    vkcv::ComputePipelineHandle computePipeline2;
-    vkcv::DescriptorSetHandle computeDescriptorSet2 = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
-                                                                          "shaders/force.comp", computePipeline2);
-
-//comp shader 3
-    vkcv::ComputePipelineHandle computePipeline3;
-    vkcv::DescriptorSetHandle computeDescriptorSet3 = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
-                                                                           "shaders/updateData.comp", computePipeline3);
-
-//comp shader 4
-    vkcv::ComputePipelineHandle computePipeline4;
-    vkcv::DescriptorSetHandle computeDescriptorSet4 = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
-                                                                            "shaders/flip.comp", computePipeline4);
-
-// shader
+    // pressure shader --> computes the pressure for all particles
+    vkcv::ComputePipelineHandle pressurePipeline;
+    vkcv::DescriptorSetHandle pressureDescriptorSet = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
+                                                                                        "shaders/pressure.comp", pressurePipeline);
+    // force shader --> computes the force that effects the particles
+    vkcv::ComputePipelineHandle forcePipeline;
+    vkcv::DescriptorSetHandle forceDescriptorSet = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
+                                                                                     "shaders/force.comp", forcePipeline);
+
+    // update data shader --> applies the force on all particles and updates their position
+    vkcv::ComputePipelineHandle updateDataPipeline;
+    vkcv::DescriptorSetHandle updateDataDescriptorSet = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
+                                                                                          "shaders/updateData.comp", updateDataPipeline);
+
+    // flip shader --> flips input and output buffer
+    vkcv::ComputePipelineHandle flipPipeline;
+    vkcv::DescriptorSetHandle flipDescriptorSet = PipelineInit::ComputePipelineInit(&core, vkcv::ShaderStage::COMPUTE,
+                                                                                    "shaders/flip.comp", flipPipeline);
+
+    // particle rendering shaders
     vkcv::ShaderProgram particleShaderProgram{};
     compiler.compile(vkcv::ShaderStage::VERTEX, "shaders/shader.vert", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
         particleShaderProgram.addShader(shaderStage, path);
@@ -96,6 +93,7 @@ int main(int argc, const char **argv) {
         particleShaderProgram.addShader(shaderStage, path);
     });
 
+    // generating descriptorsets from shader reflection
     vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(
             particleShaderProgram.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
@@ -111,11 +109,12 @@ int main(int argc, const char **argv) {
 
     std::vector<vkcv::VertexBinding> bindings;
     for (size_t i = 0; i < vertexAttachments.size(); i++) {
-        bindings.push_back(vkcv::VertexBinding(i, {vertexAttachments[i]}));
+        bindings.push_back(vkcv::createVertexBinding(i, {vertexAttachments[i]}));
     }
 
-    const vkcv::VertexLayout particleLayout(bindings);
+    const vkcv::VertexLayout particleLayout { bindings };
 
+    // initializing graphics pipeline
     vkcv::GraphicsPipelineConfig particlePipelineDefinition{
             particleShaderProgram,
             UINT32_MAX,
@@ -145,6 +144,7 @@ int main(int argc, const char **argv) {
             1
     );
 
+    // generating particles
     int numberParticles = 20000;
     std::vector<Particle> particles;
     for (int i = 0; i < numberParticles; i++) {
@@ -164,6 +164,7 @@ int main(int argc, const char **argv) {
         particles.push_back(Particle(pos, vel));
     }
 
+    // creating and filling particle buffer
     vkcv::Buffer<Particle> particleBuffer1 = core.createBuffer<Particle>(
             vkcv::BufferType::STORAGE,
             numberParticles * sizeof(glm::vec4) * 3
@@ -179,24 +180,26 @@ int main(int argc, const char **argv) {
 	particleBuffer2.fill(particles);
 
     vkcv::DescriptorWrites setWrites;
-    setWrites.uniformBufferWrites = {vkcv::BufferDescriptorWrite(0,color.getHandle()),
-                                     vkcv::BufferDescriptorWrite(1,position.getHandle())};
-    setWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(2,particleBuffer1.getHandle()),
-									  vkcv::BufferDescriptorWrite(3,particleBuffer2.getHandle())};
+    setWrites.writeUniformBuffer(0, color.getHandle()).writeUniformBuffer(1, position.getHandle());
+    setWrites.writeStorageBuffer(2, particleBuffer1.getHandle()).writeStorageBuffer(3, particleBuffer2.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
     vkcv::DescriptorWrites computeWrites;
-    computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,particleBuffer1.getHandle()),
-										  vkcv::BufferDescriptorWrite(1,particleBuffer2.getHandle())};
+    computeWrites.writeStorageBuffer(
+			0, particleBuffer1.getHandle()
+	).writeStorageBuffer(
+			1, particleBuffer2.getHandle()
+	);
     
-    core.writeDescriptorSet(computeDescriptorSet1, computeWrites);
-	core.writeDescriptorSet(computeDescriptorSet2, computeWrites);
-    core.writeDescriptorSet(computeDescriptorSet3, computeWrites);
-	core.writeDescriptorSet(computeDescriptorSet4, computeWrites);
+    core.writeDescriptorSet(pressureDescriptorSet, computeWrites);
+	core.writeDescriptorSet(forceDescriptorSet, computeWrites);
+    core.writeDescriptorSet(updateDataDescriptorSet, computeWrites);
+	core.writeDescriptorSet(flipDescriptorSet, computeWrites);
 
-    if (!particlePipeline || !computePipeline1 || !computePipeline2 || !computePipeline3 || !computePipeline4)
+    // error message if creation of one pipeline failed
+    if (!particlePipeline || !pressurePipeline || !forcePipeline || !updateDataPipeline || !flipPipeline)
     {
-        std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
+        std::cout << "Error. Could not create at least one pipeline. Exiting." << std::endl;
         return EXIT_FAILURE;
     }
 
@@ -340,38 +343,42 @@ int main(int argc, const char **argv) {
         pushConstantsCompute.appendDrawcall(pushData);
 
         uint32_t computeDispatchCount[3] = {static_cast<uint32_t> (std::ceil(numberParticles/256.f)),1,1};
-        
+
+        // computing pressure pipeline
         core.recordComputeDispatchToCmdStream(cmdStream,
-                                              computePipeline1,
+                                              pressurePipeline,
                                               computeDispatchCount,
-                                              {vkcv::DescriptorSetUsage(0, computeDescriptorSet1)},
+                                              {vkcv::DescriptorSetUsage(0, pressureDescriptorSet)},
 											  pushConstantsCompute);
 
         core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle());
 		core.recordBufferMemoryBarrier(cmdStream, particleBuffer2.getHandle());
 
+        // computing force pipeline
 		core.recordComputeDispatchToCmdStream(cmdStream,
-											  computePipeline2,
+											  forcePipeline,
 											  computeDispatchCount,
-											  {vkcv::DescriptorSetUsage(0, computeDescriptorSet2)},
+											  {vkcv::DescriptorSetUsage(0, forceDescriptorSet)},
 											  pushConstantsCompute);
 
 		core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle());
 		core.recordBufferMemoryBarrier(cmdStream, particleBuffer2.getHandle());
 
+        // computing update data pipeline
         core.recordComputeDispatchToCmdStream(cmdStream,
-                                              computePipeline3,
+                                              updateDataPipeline,
                                               computeDispatchCount,
-                                              { vkcv::DescriptorSetUsage(0, computeDescriptorSet3) },
+                                              { vkcv::DescriptorSetUsage(0, updateDataDescriptorSet) },
                                               pushConstantsCompute);
 
         core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle());
         core.recordBufferMemoryBarrier(cmdStream, particleBuffer2.getHandle());
 
+        // computing flip pipeline
         core.recordComputeDispatchToCmdStream(cmdStream,
-                                              computePipeline4,
+                                              flipPipeline,
                                               computeDispatchCount,
-                                              { vkcv::DescriptorSetUsage(0, computeDescriptorSet4) },
+                                              { vkcv::DescriptorSetUsage(0, flipDescriptorSet) },
                                               pushConstantsCompute);
 
         core.recordBufferMemoryBarrier(cmdStream, particleBuffer1.getHandle());
@@ -398,10 +405,12 @@ int main(int argc, const char **argv) {
         core.prepareImageForStorage(cmdStream, swapchainInput);
 
         vkcv::DescriptorWrites tonemappingDescriptorWrites;
-        tonemappingDescriptorWrites.storageImageWrites = {
-            vkcv::StorageImageDescriptorWrite(0, colorBuffer),
-            vkcv::StorageImageDescriptorWrite(1, swapchainInput)
-        };
+        tonemappingDescriptorWrites.writeStorageImage(
+				0, colorBuffer
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
         core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites);
 
         uint32_t tonemappingDispatchCount[3];
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 5ae7eb6047200b2cdb7a3ac38ce8512cdcaa3d53..53a11ceb1306c8a567834e943d70a8862a34afa8 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -195,9 +195,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
     m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { m_depthToMomentsDescriptorSetLayout }});
 
 	vkcv::DescriptorWrites depthToMomentDescriptorWrites;
-	depthToMomentDescriptorWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) };
-	depthToMomentDescriptorWrites.samplerWrites         = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	depthToMomentDescriptorWrites.storageImageWrites    = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	depthToMomentDescriptorWrites.writeSampledImage(0, m_shadowMapDepth.getHandle());
+	depthToMomentDescriptorWrites.writeSampler(1, m_shadowSampler);
+	depthToMomentDescriptorWrites.writeStorageImage(2, m_shadowMap.getHandle());
 	corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites);
 
 	// shadow blur X
@@ -207,9 +207,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	m_shadowBlurXPipe                       = corePtr->createComputePipeline({ shadowBlurXShader, { m_shadowBlurXDescriptorSetLayout }});
 
 	vkcv::DescriptorWrites shadowBlurXDescriptorWrites;
-	shadowBlurXDescriptorWrites.sampledImageWrites   = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) };
-	shadowBlurXDescriptorWrites.samplerWrites        = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	shadowBlurXDescriptorWrites.storageImageWrites   = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) };
+	shadowBlurXDescriptorWrites.writeSampledImage(0, m_shadowMap.getHandle());
+	shadowBlurXDescriptorWrites.writeSampler(1, m_shadowSampler);
+	shadowBlurXDescriptorWrites.writeStorageImage(2, m_shadowMapIntermediate.getHandle());
 	corePtr->writeDescriptorSet(m_shadowBlurXDescriptorSet, shadowBlurXDescriptorWrites);
 
 	// shadow blur Y
@@ -219,9 +219,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
     m_shadowBlurYPipe                       = corePtr->createComputePipeline({ shadowBlurYShader, { m_shadowBlurYDescriptorSetLayout }});
 
     vkcv::DescriptorWrites shadowBlurYDescriptorWrites;
-	shadowBlurYDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) };
-	shadowBlurYDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	shadowBlurYDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	shadowBlurYDescriptorWrites.writeSampledImage(0, m_shadowMapIntermediate.getHandle());
+	shadowBlurYDescriptorWrites.writeSampler(1, m_shadowSampler);
+	shadowBlurYDescriptorWrites.writeStorageImage(2, m_shadowMap.getHandle());
 	corePtr->writeDescriptorSet(m_shadowBlurYDescriptorSet, shadowBlurYDescriptorWrites);
 }
 
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index faa03d38127d5a23c931fdef0470c1e24131d206..616eed83e0687e03c1d9bfe0ee3127a72457d241 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -92,10 +92,13 @@ Voxelization::Voxelization(
 
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
 
-	const vkcv::PassConfig voxelizationPassConfig({vkcv::AttachmentDescription(
-		vkcv::AttachmentOperation::DONT_CARE, 
-		vkcv::AttachmentOperation::DONT_CARE, 
-		voxelizationDummyFormat) });
+	const vkcv::PassConfig voxelizationPassConfig {{
+		  {
+				  vkcv::AttachmentOperation::DONT_CARE,
+				  vkcv::AttachmentOperation::DONT_CARE,
+				  voxelizationDummyFormat
+		  }
+	}, vkcv::Multisampling::None };
 	m_voxelizationPass = m_corePtr->createPass(voxelizationPassConfig);
 
 	m_voxelizationDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelizationShader.getReflectedDescriptors().at(0));
@@ -117,14 +120,16 @@ Voxelization::Voxelization(
 	m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig);
 
 	vkcv::DescriptorWrites voxelizationDescriptorWrites;
-	voxelizationDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	voxelizationDescriptorWrites.uniformBufferWrites = { 
-		vkcv::BufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(3, lightInfoBuffer)
-	};
-	voxelizationDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(4, shadowMap) };
-	voxelizationDescriptorWrites.samplerWrites      = { vkcv::SamplerDescriptorWrite(5, shadowSampler) };
-	voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImageIntermediate.getHandle()) };
+	voxelizationDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	voxelizationDescriptorWrites.writeUniformBuffer(
+			1, m_voxelInfoBuffer.getHandle()
+	).writeUniformBuffer(
+			3, lightInfoBuffer
+	);
+	
+	voxelizationDescriptorWrites.writeSampledImage(4, shadowMap);
+	voxelizationDescriptorWrites.writeSampler(5, shadowSampler);
+	voxelizationDescriptorWrites.writeStorageImage(2, m_voxelImageIntermediate.getHandle());
 	m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites);
 
 	vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader();
@@ -144,9 +149,11 @@ Voxelization::Voxelization(
 		dependencies.depthBufferFormat
 	);
 
-	vkcv::PassConfig voxelVisualisationPassDefinition(
-		{ voxelVisualisationColorAttachments, voxelVisualisationDepthAttachments });
-	voxelVisualisationPassDefinition.msaa = msaa;
+	vkcv::PassConfig voxelVisualisationPassDefinition{
+		{ voxelVisualisationColorAttachments, voxelVisualisationDepthAttachments },
+		msaa
+	};
+	
 	m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition);
 
 	vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig{
@@ -180,7 +187,7 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites resetVoxelWrites;
-	resetVoxelWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
+	resetVoxelWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites);
 
 	// buffer to image
@@ -194,8 +201,8 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites bufferToImageDescriptorWrites;
-	bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) };
+	bufferToImageDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	bufferToImageDescriptorWrites.writeStorageImage(1, m_voxelImageIntermediate.getHandle());
 	m_corePtr->writeDescriptorSet(m_bufferToImageDescriptorSet, bufferToImageDescriptorWrites);
 
 	// secondary bounce
@@ -209,11 +216,11 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites secondaryBounceDescriptorWrites;
-	secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	secondaryBounceDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) };
-	secondaryBounceDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(2, voxelSampler) };
-	secondaryBounceDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(3, m_voxelImage.getHandle()) };
-	secondaryBounceDescriptorWrites.uniformBufferWrites = { vkcv::BufferDescriptorWrite(4, m_voxelInfoBuffer.getHandle()) };
+	secondaryBounceDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	secondaryBounceDescriptorWrites.writeSampledImage(1, m_voxelImageIntermediate.getHandle());
+	secondaryBounceDescriptorWrites.writeSampler(2, voxelSampler);
+	secondaryBounceDescriptorWrites.writeStorageImage(3, m_voxelImage.getHandle());
+	secondaryBounceDescriptorWrites.writeUniformBuffer(4, m_voxelInfoBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_secondaryBounceDescriptorSet, secondaryBounceDescriptorWrites);
 }
 
@@ -345,10 +352,8 @@ void Voxelization::renderVoxelVisualisation(
 
 	// write descriptor set
 	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
-	voxelVisualisationDescriptorWrite.storageImageWrites =
-	{ vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle(), mipLevel) };
-	voxelVisualisationDescriptorWrite.uniformBufferWrites =
-	{ vkcv::BufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
+	voxelVisualisationDescriptorWrite.writeStorageImage(0, m_voxelImage.getHandle(), mipLevel);
+	voxelVisualisationDescriptorWrite.writeUniformBuffer(1, m_voxelInfoBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite);
 
 	uint32_t drawVoxelCount = voxelCount / exp2(mipLevel);
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index f01b87a79b287609822635ecc67f7541e1a8e3b6..02533e447724ad8d83c7af415b01acc2350126eb 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -195,9 +195,9 @@ int main(int argc, const char** argv) {
 
 	std::vector<vkcv::VertexBinding> vertexBindings;
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		vertexBindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+		vertexBindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
 	}
-	const vkcv::VertexLayout vertexLayout (vertexBindings);
+	const vkcv::VertexLayout vertexLayout { vertexBindings };
 
 	vkcv::DescriptorSetLayoutHandle forwardShadingDescriptorSetLayout = core.createDescriptorSetLayout(forwardProgram.getReflectedDescriptors().at(0));
 	vkcv::DescriptorSetHandle forwardShadingDescriptorSet = core.createDescriptorSet(forwardShadingDescriptorSetLayout);
@@ -217,9 +217,9 @@ int main(int argc, const char** argv) {
 
 	std::vector<vkcv::VertexBinding> prepassVertexBindings;
 	for (size_t i = 0; i < prepassVertexAttachments.size(); i++) {
-		prepassVertexBindings.push_back(vkcv::VertexBinding(i, { prepassVertexAttachments[i] }));
+		prepassVertexBindings.push_back(vkcv::createVertexBinding(i, { prepassVertexAttachments[i] }));
 	}
-	const vkcv::VertexLayout prepassVertexLayout(prepassVertexBindings);
+	const vkcv::VertexLayout prepassVertexLayout { prepassVertexBindings };
 
 	const vkcv::AttachmentDescription prepassAttachment(
 		vkcv::AttachmentOperation::STORE,
@@ -288,14 +288,15 @@ int main(int argc, const char** argv) {
 		const vkcv::ImageHandle specularHandle = sceneImages.back().getHandle();
 
 		vkcv::DescriptorWrites setWrites;
-		setWrites.sampledImageWrites = {
-			vkcv::SampledImageDescriptorWrite(0, albedoHandle),
-			vkcv::SampledImageDescriptorWrite(2, normalHandle),
-			vkcv::SampledImageDescriptorWrite(3, specularHandle)
-		};
-		setWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, colorSampler),
-		};
+		setWrites.writeSampledImage(
+				0, albedoHandle
+		).writeSampledImage(
+				2, normalHandle
+		).writeSampledImage(
+				3, specularHandle
+		);
+		
+		setWrites.writeSampler(1, colorSampler);
 		core.writeDescriptorSet(materialDescriptorSets.back(), setWrites);
 	}
 
@@ -570,17 +571,28 @@ int main(int argc, const char** argv) {
 
 	// write forward pass descriptor set
 	vkcv::DescriptorWrites forwardDescriptorWrites;
-	forwardDescriptorWrites.uniformBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, shadowMapping.getLightInfoBuffer()),
-		vkcv::BufferDescriptorWrite(3, cameraPosBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(6, voxelization.getVoxelInfoBufferHandle()),
-		vkcv::BufferDescriptorWrite(7, volumetricSettingsBuffer.getHandle())};
-	forwardDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(1, shadowMapping.getShadowMap()),
-		vkcv::SampledImageDescriptorWrite(4, voxelization.getVoxelImageHandle()) };
-	forwardDescriptorWrites.samplerWrites = { 
-		vkcv::SamplerDescriptorWrite(2, shadowMapping.getShadowSampler()),
-		vkcv::SamplerDescriptorWrite(5, voxelSampler) };
+	forwardDescriptorWrites.writeUniformBuffer(
+			0, shadowMapping.getLightInfoBuffer()
+	).writeUniformBuffer(
+			3, cameraPosBuffer.getHandle()
+	).writeUniformBuffer(
+			6, voxelization.getVoxelInfoBufferHandle()
+	).writeUniformBuffer(
+			7, volumetricSettingsBuffer.getHandle()
+	);
+	
+	forwardDescriptorWrites.writeSampledImage(
+			1, shadowMapping.getShadowMap()
+	).writeSampledImage(
+			4, voxelization.getVoxelImageHandle()
+	);
+	
+	forwardDescriptorWrites.writeSampler(
+			2, shadowMapping.getShadowSampler()
+	).writeSampler(
+			5, voxelSampler
+	);
+	
 	core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites);
 
 	vkcv::upscaling::FSRUpscaling upscaling (core);
@@ -661,9 +673,7 @@ int main(int argc, const char** argv) {
 			
 			for (size_t i = 0; i < scene.materials.size(); i++) {
 				vkcv::DescriptorWrites setWrites;
-				setWrites.samplerWrites = {
-						vkcv::SamplerDescriptorWrite(1, colorSampler),
-				};
+				setWrites.writeSampler(1, colorSampler);
 				core.writeDescriptorSet(materialDescriptorSets[i], setWrites);
 			}
 			
@@ -709,25 +719,25 @@ int main(int argc, const char** argv) {
 
 		// update descriptor sets which use swapchain image
 		vkcv::DescriptorWrites tonemappingDescriptorWrites;
-		tonemappingDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, resolvedColorBuffer) };
-		tonemappingDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, colorSampler) };
-		tonemappingDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, swapBuffer) };
+		tonemappingDescriptorWrites.writeSampledImage(0, resolvedColorBuffer);
+		tonemappingDescriptorWrites.writeSampler(1, colorSampler);
+		tonemappingDescriptorWrites.writeStorageImage(2, swapBuffer);
 
 		core.writeDescriptorSet(tonemappingDescriptorSet, tonemappingDescriptorWrites);
 		
 		// update descriptor sets which use swapchain image
 		vkcv::DescriptorWrites postEffectsDescriptorWrites;
-		postEffectsDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, swapBuffer2) };
-		postEffectsDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, colorSampler) };
-		postEffectsDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, swapchainInput) };
+		postEffectsDescriptorWrites.writeSampledImage(0, swapBuffer2);
+		postEffectsDescriptorWrites.writeSampler(1, colorSampler);
+		postEffectsDescriptorWrites.writeStorageImage(2, swapchainInput);
 		
 		core.writeDescriptorSet(postEffectsDescriptorSet, postEffectsDescriptorWrites);
 
 		// update resolve descriptor, color images could be changed
 		vkcv::DescriptorWrites resolveDescriptorWrites;
-		resolveDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-		resolveDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, resolveSampler) };
-		resolveDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, resolvedColorBuffer) };
+		resolveDescriptorWrites.writeSampledImage(0, colorBuffer);
+		resolveDescriptorWrites.writeSampler(1, resolveSampler);
+		resolveDescriptorWrites.writeStorageImage(2, resolvedColorBuffer);
 		core.writeDescriptorSet(resolveDescriptorSet, resolveDescriptorWrites);
 
 		start = end;
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 96c367f2f8e22ac65bf6ccf6a5c09eb238b5604d..d554687b503fa4460f27aa4db5374cc0e4d0acb9 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -369,14 +369,14 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(initParticleWeightsSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
 		core.writeDescriptorSet(initParticleWeightsSets[1], writes);
 	}
 	
@@ -389,19 +389,19 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(transformParticlesToGridSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle()));
+		writes.writeUniformBuffer(0, simulation.getHandle());
 		core.writeDescriptorSet(transformParticlesToGridSets[1], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, grid.getHandle()));
+		writes.writeStorageImage(0, grid.getHandle());
 		core.writeDescriptorSet(transformParticlesToGridSets[2], writes);
 	}
 	
@@ -414,20 +414,20 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle()));
+		writes.writeUniformBuffer(0, simulation.getHandle());
 		core.writeDescriptorSet(updateParticleVelocitiesSets[1], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
 		core.writeDescriptorSet(updateParticleVelocitiesSets[2], writes);
 	}
 	
@@ -452,7 +452,7 @@ int main(int argc, const char **argv) {
 			{ vkcv::ShaderStage::FRAGMENT, "shaders/lines.frag" }
 	}, nullptr);
 	
-	vkcv::PassConfig passConfigGrid ({
+	vkcv::PassConfig passConfigGrid {{
 		vkcv::AttachmentDescription(
 				vkcv::AttachmentOperation::STORE,
 				vkcv::AttachmentOperation::CLEAR,
@@ -463,9 +463,9 @@ int main(int argc, const char **argv) {
 				vkcv::AttachmentOperation::CLEAR,
 				vk::Format::eD32Sfloat
 		)
-	});
+	}, vkcv::Multisampling::None };
 	
-	vkcv::PassConfig passConfigParticles ({
+	vkcv::PassConfig passConfigParticles {{
 		vkcv::AttachmentDescription(
 				vkcv::AttachmentOperation::STORE,
 				vkcv::AttachmentOperation::CLEAR,
@@ -476,9 +476,9 @@ int main(int argc, const char **argv) {
 				vkcv::AttachmentOperation::CLEAR,
 				vk::Format::eD32Sfloat
 		)
-	});
+	}, vkcv::Multisampling::None };
 	
-	vkcv::PassConfig passConfigLines ({
+	vkcv::PassConfig passConfigLines {{
 		vkcv::AttachmentDescription(
 				vkcv::AttachmentOperation::STORE,
 				vkcv::AttachmentOperation::LOAD,
@@ -489,7 +489,7 @@ int main(int argc, const char **argv) {
 				vkcv::AttachmentOperation::LOAD,
 				vk::Format::eD32Sfloat
 		)
-	});
+	}, vkcv::Multisampling::None };
 	
 	vkcv::DescriptorSetLayoutHandle gfxSetLayoutGrid = core.createDescriptorSetLayout(
 			gfxProgramGrid.getReflectedDescriptors().at(0)
@@ -499,9 +499,9 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(2, simulation.getHandle()));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
+		writes.writeUniformBuffer(2, simulation.getHandle());
 		core.writeDescriptorSet(gfxSetGrid, writes);
 	}
 	
@@ -513,7 +513,7 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(gfxSetParticles, writes);
 	}
 	
@@ -522,7 +522,7 @@ int main(int argc, const char **argv) {
 	vkcv::PassHandle gfxPassLines = core.createPass(passConfigLines);
 	
 	vkcv::VertexLayout vertexLayoutGrid ({
-		vkcv::VertexBinding(0, gfxProgramGrid.getVertexAttachments())
+		vkcv::createVertexBinding(0, gfxProgramGrid.getVertexAttachments())
 	});
 	
 	vkcv::GraphicsPipelineConfig gfxPipelineConfigGrid;
@@ -535,7 +535,7 @@ int main(int argc, const char **argv) {
 	gfxPipelineConfigGrid.m_UseDynamicViewport = true;
 	
 	vkcv::VertexLayout vertexLayoutParticles ({
-		vkcv::VertexBinding(0, gfxProgramParticles.getVertexAttachments())
+		vkcv::createVertexBinding(0, gfxProgramParticles.getVertexAttachments())
 	});
 	
 	vkcv::GraphicsPipelineConfig gfxPipelineConfigParticles;
@@ -548,7 +548,7 @@ int main(int argc, const char **argv) {
 	gfxPipelineConfigParticles.m_UseDynamicViewport = true;
 	
 	vkcv::VertexLayout vertexLayoutLines ({
-		vkcv::VertexBinding(0, gfxProgramLines.getVertexAttachments())
+		vkcv::createVertexBinding(0, gfxProgramLines.getVertexAttachments())
 	});
 	
 	vkcv::GraphicsPipelineConfig gfxPipelineConfigLines;
@@ -883,7 +883,7 @@ int main(int argc, const char **argv) {
 			);
 			
 			vkcv::DescriptorWrites writes;
-			writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+			writes.writeStorageBuffer(0, particlesHandle);
 			
 			core.writeDescriptorSet(initParticleWeightsSets[0], writes);
 			core.writeDescriptorSet(transformParticlesToGridSets[0], writes);
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index 52915ff04800ef3b6cb1e6caefdb3f25f6568aac..2d29719f4a34d305f90c1b76db6b56277eb3def5 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -111,6 +111,9 @@ namespace vkcv {
 		return BufferHandle(id, [&](uint64_t id) { destroyBufferById(id); });
 	}
 	
+	/**
+	 * @brief Structure to store details required for a staging process.
+	 */
 	struct StagingStepInfo {
 		const void* data;
 		size_t size;
diff --git a/src/vkcv/CommandResources.cpp b/src/vkcv/CommandResources.cpp
index a31e6967d85bd099fe5cbbc865b0e062212ca16e..d5c97946aa97ba897710dda412b6f71bd2ed54c8 100644
--- a/src/vkcv/CommandResources.cpp
+++ b/src/vkcv/CommandResources.cpp
@@ -40,7 +40,7 @@ namespace vkcv {
 		}
 	}
 
-	vk::CommandBuffer allocateCommandBuffer(const vk::Device& device, const vk::CommandPool cmdPool) {
+	vk::CommandBuffer allocateCommandBuffer(const vk::Device& device, const vk::CommandPool &cmdPool) {
 		const vk::CommandBufferAllocateInfo info(cmdPool, vk::CommandBufferLevel::ePrimary, 1);
 		return device.allocateCommandBuffers(info).front();
 	}
@@ -49,7 +49,7 @@ namespace vkcv {
 		return cmdResources.cmdPoolPerQueueFamily[queue.familyIndex];
 	}
 
-	Queue getQueueForSubmit(const QueueType type, const QueueManager& queueManager) {
+	Queue getQueueForSubmit(QueueType type, const QueueManager& queueManager) {
 		if (type == QueueType::Graphics) {
 			return queueManager.getGraphicsQueues().front();
 		}
@@ -68,17 +68,17 @@ namespace vkcv {
 		}
 	}
 
-	void beginCommandBuffer(const vk::CommandBuffer cmdBuffer, const vk::CommandBufferUsageFlags flags) {
+	void beginCommandBuffer(const vk::CommandBuffer &cmdBuffer, vk::CommandBufferUsageFlags flags) {
 		const vk::CommandBufferBeginInfo beginInfo(flags);
 		cmdBuffer.begin(beginInfo);
 	}
 
 	void submitCommandBufferToQueue(
-		const vk::Queue						queue,
-		const vk::CommandBuffer				cmdBuffer,
-		const vk::Fence						fence,
-		const std::vector<vk::Semaphore>&	waitSemaphores,
-		const std::vector<vk::Semaphore>&	signalSemaphores) {
+		vk::Queue							queue,
+		const vk::CommandBuffer				&cmdBuffer,
+		const vk::Fence						&fence,
+		const std::vector<vk::Semaphore>	&waitSemaphores,
+		const std::vector<vk::Semaphore>	&signalSemaphores) {
 
 		const std::vector<vk::PipelineStageFlags> waitDstStageMasks(waitSemaphores.size(), vk::PipelineStageFlagBits::eAllCommands);
 		const vk::SubmitInfo queueSubmitInfo(waitSemaphores, waitDstStageMasks, cmdBuffer, signalSemaphores);
diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp
index 52b73213dbc5837f6be4a2aa25c28615dccf5969..872e91c54b1b64616ad5867926e6f656f44ccded 100644
--- a/src/vkcv/CommandStreamManager.cpp
+++ b/src/vkcv/CommandStreamManager.cpp
@@ -1,4 +1,4 @@
-#include "vkcv/CommandStreamManager.hpp"
+#include "CommandStreamManager.hpp"
 #include "vkcv/Core.hpp"
 
 #include "vkcv/Logger.hpp"
@@ -22,7 +22,7 @@ namespace vkcv {
 	}
 
 	CommandStreamHandle CommandStreamManager::createCommandStream(
-		const vk::Queue queue, 
+		const vk::Queue &queue,
 		vk::CommandPool cmdPool) {
 
 		const vk::CommandBuffer cmdBuffer = allocateCommandBuffer(m_core->getContext().getDevice(), cmdPool);
@@ -53,8 +53,8 @@ namespace vkcv {
     }
 
 	void CommandStreamManager::recordCommandsToStream(
-		const CommandStreamHandle   handle, 
-		const RecordCommandFunction record) {
+		const CommandStreamHandle   &handle,
+		const RecordCommandFunction &record) {
 
 		const size_t id = handle.getId();
 		if (id >= m_commandStreams.size()) {
@@ -67,8 +67,8 @@ namespace vkcv {
 	}
 
 	void CommandStreamManager::addFinishCallbackToStream(
-		const CommandStreamHandle   handle, 
-		const FinishCommandFunction finish) {
+		const CommandStreamHandle   &handle,
+		const FinishCommandFunction &finish) {
 
 		const size_t id = handle.getId();
 		if (id >= m_commandStreams.size()) {
@@ -81,7 +81,7 @@ namespace vkcv {
 	}
 
 	void CommandStreamManager::submitCommandStreamSynchronous(
-		const CommandStreamHandle   handle,
+		const CommandStreamHandle   &handle,
 		std::vector<vk::Semaphore>  &waitSemaphores,
 		std::vector<vk::Semaphore>  &signalSemaphores) {
 
@@ -109,7 +109,7 @@ namespace vkcv {
 		}
 	}
 
-	vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle handle) {
+	vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle &handle) {
 		const size_t id = handle.getId();
 		if (id >= m_commandStreams.size()) {
 			vkcv_log(LogLevel::ERROR, "Requires valid handle");
diff --git a/src/vkcv/CommandStreamManager.hpp b/src/vkcv/CommandStreamManager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9a8eb3d02143c20532275d5a61ca3cc68aa03778
--- /dev/null
+++ b/src/vkcv/CommandStreamManager.hpp
@@ -0,0 +1,97 @@
+#pragma once
+#include <vulkan/vulkan.hpp>
+#include <vector>
+#include "vkcv/Event.hpp"
+#include "vkcv/Handles.hpp"
+#include "vkcv/CommandRecordingFunctionTypes.hpp"
+
+namespace vkcv {
+	
+	class Core;
+
+	/**
+	 * @brief Responsible for creation, deletion, callbacks and recording of command streams
+	*/
+	class CommandStreamManager
+	{
+		friend class Core;
+	private:
+		/**
+		 * @brief Represents one command stream, into which commands can be recorded into.
+		 * Consists of a command buffer, the command buffer's command pool and a queue, as well as some callbacks.
+		*/
+		struct CommandStream {
+			inline CommandStream(vk::CommandBuffer cmdBuffer, vk::Queue queue, vk::CommandPool cmdPool) 
+				: cmdBuffer(cmdBuffer), cmdPool(cmdPool), queue(queue) {};
+			vk::CommandBuffer                   cmdBuffer;
+			vk::CommandPool                     cmdPool;
+			vk::Queue                           queue;
+			std::vector<FinishCommandFunction>  callbacks;
+		};
+
+		Core* m_core;
+		std::vector<CommandStream> m_commandStreams;
+
+		CommandStreamManager() noexcept;
+
+		void init(Core* core);
+
+	public:
+		~CommandStreamManager() noexcept;
+
+		CommandStreamManager(CommandStreamManager&& other) = delete;
+		CommandStreamManager(const CommandStreamManager& other) = delete;
+
+		CommandStreamManager& operator=(CommandStreamManager&& other) = delete;
+		CommandStreamManager& operator=(const CommandStreamManager& other) = delete;
+
+		/**
+		 * @brief Creates a new command stream
+		 * 
+		 * @param queue Queue the command buffer will be submitted to
+		 * @param cmdPool Command pool the command buffer will be allocated from
+		 * @return Handle that represents the #CommandStream
+		*/
+		CommandStreamHandle createCommandStream(
+			const vk::Queue &queue,
+			vk::CommandPool cmdPool);
+
+		/**
+		 * @brief Record vulkan commands to a #CommandStream, using a record function
+		 * 
+		 * @param handle Command stream handle
+		 * @param record Function that records the vulkan commands
+		*/
+		void recordCommandsToStream(const CommandStreamHandle &handle, const RecordCommandFunction &record);
+
+		/**
+		 * @brief Add a callback to a #CommandStream that is called 
+		 * every time the command stream is submitted and finished
+		 * 
+		 * @param handle Command stream handle
+		 * @param finish Callback that is called when a command stream submission is finished
+		*/
+		void addFinishCallbackToStream(const CommandStreamHandle &handle, const FinishCommandFunction &finish);
+
+		/**
+		 * @brief Submits a #CommandStream to it's queue and returns after execution is finished
+		 * 
+		 * @param handle Command stream handle
+		 * @param waitSemaphores Semaphores that are waited upon before executing the recorded commands
+		 * @param signalSemaphores Semaphores that are signaled when execution of the recorded commands is finished
+		*/
+		void submitCommandStreamSynchronous(
+			const CommandStreamHandle   &handle,
+			std::vector<vk::Semaphore>  &waitSemaphores,
+			std::vector<vk::Semaphore>  &signalSemaphores);
+
+		/**
+		 * @brief Returns the underlying vulkan handle of a #CommandStream to be used for manual command recording
+		 * 
+		 * @param handle Command stream handle
+		 * @return Vulkan handle of the #CommandStream
+		*/
+		vk::CommandBuffer getStreamCommandBuffer(const CommandStreamHandle &handle);
+	};
+
+}
\ No newline at end of file
diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp
index a599001d3c60e126cfa0a52a1347abfe48b961a9..264389ca9b5ed118666911b07158ab589a4ca0ee 100644
--- a/src/vkcv/ComputePipelineManager.cpp
+++ b/src/vkcv/ComputePipelineManager.cpp
@@ -59,9 +59,9 @@ namespace vkcv
 
         vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts);
 
-        const size_t pushConstantSize = shaderProgram.getPushConstantSize();
-        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
-        if (pushConstantSize > 0) {
+        const size_t pushConstantsSize = shaderProgram.getPushConstantsSize();
+        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantsSize);
+        if (pushConstantsSize > 0) {
             pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
             pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
         }
@@ -112,8 +112,8 @@ namespace vkcv
 
     vk::Result ComputePipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage)
     {
-        std::vector<char> code = shaderProgram.getShader(stage).shaderCode;
-        vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
+        std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
+        vk::ShaderModuleCreateInfo moduleInfo({}, code.size() * sizeof(uint32_t), code.data());
         return m_Device.createShaderModule(&moduleInfo, nullptr, &module);
     }
 }
\ No newline at end of file
diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp
index acb50bbdef99d037374c140836d25bb161132b2b..4c186ac7508a0cb8ff98d691d25cd8c3b1726f47 100644
--- a/src/vkcv/ComputePipelineManager.hpp
+++ b/src/vkcv/ComputePipelineManager.hpp
@@ -16,6 +16,9 @@
 namespace vkcv
 {
 
+	/**
+	 * @brief Class to manage compute pipelines.
+	 */
     class ComputePipelineManager
     {
     public:
diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp
index 8988e479f0f57693c49ab3dbfc40f056a4cc4d8c..4a5b314f0bca5aa7af820c7bc876b954bf1ca0f3 100644
--- a/src/vkcv/Context.cpp
+++ b/src/vkcv/Context.cpp
@@ -185,6 +185,166 @@ namespace vkcv
 		
 		return extensions;
 	}
+	
+	/**
+	 * Given the @p physicalDevice and the @p queuePriorities, the @p queueCreateInfos are computed. First, the requested
+	 * queues are sorted by priority depending on the availability of queues in the queue families of the given
+	 * @p physicalDevice. Then check, if all requested queues are creatable. If so, the @p queueCreateInfos will be computed.
+	 * Furthermore, lists of index pairs (queueFamilyIndex, queueIndex) for later referencing of the separate queues will
+	 * be computed.
+	 * @param[in] physicalDevice The physical device
+	 * @param[in] queuePriorities The queue priorities used for the computation of @p queueCreateInfos
+	 * @param[in] queueFlags The queue flags requesting the queues
+	 * @param[in,out] queueCreateInfos The queue create info structures to be created
+	 * @param[in,out] queuePairsGraphics The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
+	 *      vk::QueueFlagBits::eGraphics
+	 * @param[in,out] queuePairsCompute The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
+	 *      vk::QueueFlagBits::eCompute
+	 * @param[in,out] queuePairsTransfer The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
+	 *      vk::QueueFlagBits::eTransfer
+	 * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due to insufficient availability.
+	 */
+	static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
+											 const std::vector<float> &queuePriorities,
+											 const std::vector<vk::QueueFlagBits> &queueFlags,
+											 std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
+											 std::vector<std::pair<int, int>> &queuePairsGraphics,
+											 std::vector<std::pair<int, int>> &queuePairsCompute,
+											 std::vector<std::pair<int, int>> &queuePairsTransfer)
+	{
+		queueCreateInfos = {};
+		queuePairsGraphics = {};
+		queuePairsCompute = {};
+		queuePairsTransfer = {};
+		std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
+		
+		//check priorities of flags -> the lower prioCount the higher the priority
+		std::vector<int> prios;
+		for(auto flag: queueFlags) {
+			int prioCount = 0;
+			for (size_t i = 0; i < qFamilyProperties.size(); i++) {
+				prioCount += (static_cast<uint32_t>(flag & qFamilyProperties[i].queueFlags) != 0) * qFamilyProperties[i].queueCount;
+			}
+			prios.push_back(prioCount);
+		}
+		//resort flags with heighest priority before allocating the queues
+		std::vector<vk::QueueFlagBits> newFlags;
+		for(size_t i = 0; i < prios.size(); i++) {
+			auto minElem = std::min_element(prios.begin(), prios.end());
+			int index = minElem - prios.begin();
+			newFlags.push_back(queueFlags[index]);
+			prios[index] = std::numeric_limits<int>::max();
+		}
+		
+		// create requested queues and check if more requested queues are supported
+		// herefore: create vector that updates available queues in each queue family
+		// structure: [qFamily_0, ..., qFamily_n] where
+		// - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n
+		std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
+		
+		for (auto qFamily : qFamilyProperties) {
+			auto graphicsCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0? qFamily.queueCount : 0;
+			auto computeCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0? qFamily.queueCount : 0;
+			auto transferCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0? qFamily.queueCount : 0;
+			queueFamilyStatus.push_back({
+												static_cast<int>(graphicsCount),
+												static_cast<int>(computeCount),
+												static_cast<int>(transferCount)
+										});
+		}
+		
+		initialQueueFamilyStatus = queueFamilyStatus;
+		// check if every queue with the specified queue flag can be created
+		// this automatically checks for queue flag support!
+		for (auto qFlag : newFlags) {
+			bool found;
+			switch (qFlag) {
+				case vk::QueueFlagBits::eGraphics:
+					found = false;
+					for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+						if (queueFamilyStatus[i][0] > 0) {
+							queuePairsGraphics.emplace_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]));
+							queueFamilyStatus[i][0]--;
+							queueFamilyStatus[i][1]--;
+							queueFamilyStatus[i][2]--;
+							found = true;
+						}
+					}
+					if (!found) {
+						for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+							if (initialQueueFamilyStatus[i][0] > 0) {
+								queuePairsGraphics.emplace_back(std::pair(i, 0));
+								found = true;
+							}
+						}
+						
+						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
+					}
+					break;
+				case vk::QueueFlagBits::eCompute:
+					found = false;
+					for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+						if (queueFamilyStatus[i][1] > 0) {
+							queuePairsCompute.emplace_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1]));
+							queueFamilyStatus[i][0]--;
+							queueFamilyStatus[i][1]--;
+							queueFamilyStatus[i][2]--;
+							found = true;
+						}
+					}
+					if (!found) {
+						for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+							if (initialQueueFamilyStatus[i][1] > 0) {
+								queuePairsCompute.emplace_back(std::pair(i, 0));
+								found = true;
+							}
+						}
+						
+						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
+					}
+					break;
+				case vk::QueueFlagBits::eTransfer:
+					found = false;
+					for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+						if (queueFamilyStatus[i][2] > 0) {
+							queuePairsTransfer.emplace_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2]));
+							queueFamilyStatus[i][0]--;
+							queueFamilyStatus[i][1]--;
+							queueFamilyStatus[i][2]--;
+							found = true;
+						}
+					}
+					if (!found) {
+						for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
+							if (initialQueueFamilyStatus[i][2] > 0) {
+								queuePairsTransfer.emplace_back(std::pair(i, 0));
+								found = true;
+							}
+						}
+						
+						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
+					}
+					break;
+				default:
+				vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", vk::to_string(qFlag).c_str());
+					break;
+			}
+		}
+		
+		// create all requested queues
+		for (size_t i = 0; i < qFamilyProperties.size(); i++) {
+			uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]);
+			if (create > 0) {
+				vk::DeviceQueueCreateInfo qCreateInfo(
+						vk::DeviceQueueCreateFlags(),
+						i,
+						create,
+						queuePriorities.data()
+				);
+				queueCreateInfos.push_back(qCreateInfo);
+			}
+		}
+	}
 
 	Context Context::create(const char *applicationName,
 							uint32_t applicationVersion,
@@ -306,7 +466,15 @@ namespace vkcv
 		qPriorities.resize(queueFlags.size(), 1.f);
 		std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
 		
-		QueueManager::queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
+		queueCreateInfosQueueHandles(
+				physicalDevice,
+				qPriorities,
+				queueFlags,
+				qCreateInfos,
+				queuePairsGraphics,
+				queuePairsCompute,
+				queuePairsTransfer
+		);
 		
 		vk::DeviceCreateInfo deviceCreateInfo(
 				vk::DeviceCreateFlags(),
@@ -327,10 +495,6 @@ namespace vkcv
 		deviceCreateInfo.setPNext(&(featureManager.getFeatures()));
 		
 		vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
-
-		if (featureManager.isExtensionActive(VK_NV_MESH_SHADER_EXTENSION_NAME)) {
-			InitMeshShaderDrawFunctions(device);
-		}
 		
 		QueueManager queueManager = QueueManager::create(
 				device,
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index a44ee97821e4fbf6241e74b9f010fcf46970e91f..df3170d1524b69d23a67c91d1ec94829bcc08c8c 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -16,7 +16,7 @@
 #include "DescriptorManager.hpp"
 #include "WindowManager.hpp"
 #include "ImageLayoutTransitions.hpp"
-#include "vkcv/CommandStreamManager.hpp"
+#include "CommandStreamManager.hpp"
 #include <cmath>
 #include "vkcv/Logger.hpp"
 
@@ -152,7 +152,7 @@ namespace vkcv
 		width = extent.width;
 		height = extent.height;
 		
-		if ((width < MIN_SWAPCHAIN_SIZE) || (height < MIN_SWAPCHAIN_SIZE)) {
+		if ((width < MIN_SURFACE_SIZE) || (height < MIN_SURFACE_SIZE)) {
 			return false;
 		}
 		
@@ -271,11 +271,15 @@ namespace vkcv
 	
 	vk::IndexType getIndexType(IndexBitCount indexByteCount){
 		switch (indexByteCount) {
-			case IndexBitCount::Bit16: return vk::IndexType::eUint16;
-			case IndexBitCount::Bit32: return vk::IndexType::eUint32;
-			default:
-			vkcv_log(LogLevel::ERROR, "unknown Enum");
+			case IndexBitCount::Bit8:
+				return vk::IndexType::eUint8EXT;
+			case IndexBitCount::Bit16:
 				return vk::IndexType::eUint16;
+			case IndexBitCount::Bit32:
+				return vk::IndexType::eUint32;
+			default:
+				vkcv_log(LogLevel::ERROR, "unknown Enum");
+				return vk::IndexType::eNoneKHR;
 		}
 	}
 	
@@ -893,9 +897,9 @@ namespace vkcv
 		return getSwapchain(swapchainHandle);
 	}
 
-	DescriptorSetLayoutHandle Core::createDescriptorSetLayout(const DescriptorBindings &bindingsMap)
+	DescriptorSetLayoutHandle Core::createDescriptorSetLayout(const DescriptorBindings &bindings)
 	{
-	    return m_DescriptorManager->createDescriptorSetLayout(bindingsMap);
+	    return m_DescriptorManager->createDescriptorSetLayout(bindings);
 	}
 
 	DescriptorSetLayout Core::getDescriptorSetLayout(const DescriptorSetLayoutHandle handle) const
@@ -1067,7 +1071,7 @@ namespace vkcv
 	
 	static void setDebugObjectLabel(const vk::Device& device, const vk::ObjectType& type,
 									uint64_t handle, const std::string& label) {
-#ifndef VULKAN_DEBUG_LABELS
+#ifdef VULKAN_DEBUG_LABELS
 		static PFN_vkSetDebugUtilsObjectNameEXT setDebugLabel = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(
 				device.getProcAddr("vkSetDebugUtilsObjectNameEXT")
 		);
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index 8343fde6650bd811d85fb44f867c8d832a9380d6..d12a5287e2317bdfc21fb15872681138b4f0d64f 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -35,6 +35,8 @@ namespace vkcv
         }
 		
 		for (uint64_t id = 0; id < m_DescriptorSetLayouts.size(); id++) {
+			// Resets the usage count to zero for destruction.
+			m_DescriptorSetLayouts[id].layoutUsageCount = 0;
 			destroyDescriptorSetLayoutById(id);
 		}
         
@@ -48,15 +50,16 @@ namespace vkcv
 		}
     }
 
-    DescriptorSetLayoutHandle DescriptorManager::createDescriptorSetLayout(const DescriptorBindings &setBindingsMap)
+    DescriptorSetLayoutHandle DescriptorManager::createDescriptorSetLayout(const DescriptorBindings &bindings)
     {
         for (size_t i = 0; i < m_DescriptorSetLayouts.size(); i++)
         {
-            if(m_DescriptorSetLayouts[i].descriptorBindings.size() != setBindingsMap.size())
+            if(m_DescriptorSetLayouts[i].descriptorBindings.size() != bindings.size())
                 continue;
 
-            if (m_DescriptorSetLayouts[i].descriptorBindings == setBindingsMap)
+            if (m_DescriptorSetLayouts[i].descriptorBindings == bindings)
             {
+				m_DescriptorSetLayouts[i].layoutUsageCount++;
                 return DescriptorSetLayoutHandle(i, [&](uint64_t id) { destroyDescriptorSetLayoutById(id); });
             }
         }
@@ -65,7 +68,7 @@ namespace vkcv
         std::vector<vk::DescriptorSetLayoutBinding> bindingsVector = {};
 		std::vector<vk::DescriptorBindingFlags> bindingsFlags = {};
 		
-        for (auto bindingElem : setBindingsMap)
+        for (auto bindingElem : bindings)
         {
             DescriptorBinding binding = bindingElem.second;
             uint32_t bindingID = bindingElem.first;
@@ -104,14 +107,14 @@ namespace vkcv
         };
 
         const uint64_t id = m_DescriptorSetLayouts.size();
-        m_DescriptorSetLayouts.push_back({vulkanHandle, setBindingsMap});
+        m_DescriptorSetLayouts.push_back({vulkanHandle, bindings, 1});
         return DescriptorSetLayoutHandle(id, [&](uint64_t id) { destroyDescriptorSetLayoutById(id); });
     }
 
-    DescriptorSetHandle DescriptorManager::createDescriptorSet(const DescriptorSetLayoutHandle &setLayoutHandle)
+    DescriptorSetHandle DescriptorManager::createDescriptorSet(const DescriptorSetLayoutHandle &layout)
     {
         //create and allocate the set based on the layout provided
-        DescriptorSetLayout setLayout = m_DescriptorSetLayouts[setLayoutHandle.getId()];
+        DescriptorSetLayout setLayout = m_DescriptorSetLayouts[layout.getId()];
         vk::DescriptorSet vulkanHandle;
         vk::DescriptorSetAllocateInfo allocInfo(m_Pools.back(), 1, &setLayout.vulkanHandle);
 
@@ -148,10 +151,13 @@ namespace vkcv
 	
 		size_t poolIndex = (m_Pools.size() - 1);
         const uint64_t id = m_DescriptorSets.size();
-        m_DescriptorSets.push_back({vulkanHandle, setLayoutHandle, poolIndex});
+        m_DescriptorSets.push_back({ vulkanHandle, layout, poolIndex });
         return DescriptorSetHandle(id, [&](uint64_t id) { destroyDescriptorSetById(id); });
     }
     
+	/**
+	 * @brief Structure to store details to write to a descriptor set.
+	 */
     struct WriteDescriptorSetInfo {
 		size_t imageInfoIndex;
 		size_t bufferInfoIndex;
@@ -173,7 +179,7 @@ namespace vkcv
 		
 		std::vector<WriteDescriptorSetInfo> writeInfos;
 
-		for (const auto& write : writes.sampledImageWrites)
+		for (const auto& write : writes.getSampledImageWrites())
 		{
 		    vk::ImageLayout layout = write.useGeneralLayout ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
 			const vk::DescriptorImageInfo imageInfo(
@@ -195,7 +201,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.storageImageWrites) {
+		for (const auto& write : writes.getStorageImageWrites()) {
 			const vk::DescriptorImageInfo imageInfo(
 				nullptr,
 				imageManager.getVulkanImageView(write.image, write.mipLevel),
@@ -215,7 +221,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.uniformBufferWrites) {
+		for (const auto& write : writes.getUniformBufferWrites()) {
 			const size_t size = bufferManager.getBufferSize(write.buffer);
 			const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size);
 			
@@ -242,7 +248,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.storageBufferWrites) {
+		for (const auto& write : writes.getStorageBufferWrites()) {
 			const size_t size = bufferManager.getBufferSize(write.buffer);
 			const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size);
 			
@@ -269,7 +275,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.samplerWrites) {
+		for (const auto& write : writes.getSamplerWrites()) {
 			const vk::Sampler& sampler = samplerManager.getVulkanSampler(write.sampler);
 			
 			const vk::DescriptorImageInfo imageInfo(
@@ -341,6 +347,13 @@ namespace vkcv
 	    }
 
 	    auto& layout = m_DescriptorSetLayouts[id];
+
+		if (layout.layoutUsageCount > 1) {
+			layout.layoutUsageCount--;
+			return;
+		} else {
+			layout.layoutUsageCount = 0;
+		}
 		
 	    if (layout.vulkanHandle){
 	        m_Device.destroy(layout.vulkanHandle);
diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp
index d60a6d5c6eb1a66db07487c888505e8b3731b046..c996e8c94f6dbb6f45f173f60f59f344a9a58623 100644
--- a/src/vkcv/DescriptorManager.hpp
+++ b/src/vkcv/DescriptorManager.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
 /**
- * @authors Artur Wasmut, Susanne D�tsch, Simeon Hermann
+ * @authors Artur Wasmut, Susanne D�tsch, Simeon Hermann, Tobias Frisch
  * @file src/vkcv/DescriptorManager.cpp
  * @brief Creation and handling of descriptor sets and the respective descriptor pools
  */
@@ -17,24 +17,60 @@
 
 namespace vkcv
 {
+	
+	/**
+	 * @brief Class to manage descriptor sets and descriptor set layouts.
+	 */
 	class DescriptorManager
 	{
 	public:
+		/**
+		 * @brief Constructor of the descriptor manager
+		 *
+		 * @param[in,out] device Vulkan device
+		 */
 	    explicit DescriptorManager(vk::Device device) noexcept;
+		
+		/**
+		 * @brief Destructor of the descriptor manager
+		 */
 	    ~DescriptorManager() noexcept;
 
-	    DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &setBindingsMap);
-        DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &setLayoutHandle);
+		/**
+		 * @brief Creates a descriptor set layout with given descriptor bindings
+		 * or returns a matching handle.
+		 *
+		 * @param[in] bindings Descriptor bindings
+		 * @return Handle of descriptor set layout
+		 */
+	    DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &bindings);
+		
+		/**
+		 * @brief Creates a descriptor set using a given descriptor set layout.
+		 *
+		 * @param[in] layout Handle of descriptor set layout
+		 * @return Handle of descriptor set
+		 */
+        DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layout);
 
-		void writeDescriptorSet(
-			const DescriptorSetHandle	&handle,
-			const DescriptorWrites  &writes,
-			const ImageManager      &imageManager,
-			const BufferManager     &bufferManager,
-			const SamplerManager    &samplerManager);
+		/**
+		 * @brief Writes to a descriptor set using writes and all required managers.
+		 *
+		 * @param[in] handle Handle of descriptor set
+		 * @param[in] writes Descriptor set writes
+		 * @param[in] imageManager Image manager
+		 * @param[in] bufferManager Buffer manager
+		 * @param[in] samplerManager Sampler manager
+		 */
+		void writeDescriptorSet(const DescriptorSetHandle &handle,
+								const DescriptorWrites &writes,
+								const ImageManager &imageManager,
+								const BufferManager &bufferManager,
+								const SamplerManager &samplerManager);
 
 		[[nodiscard]]
 		DescriptorSetLayout getDescriptorSetLayout(const DescriptorSetLayoutHandle handle) const;
+		
 		[[nodiscard]]
 		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
@@ -45,34 +81,40 @@ namespace vkcv
 		vk::DescriptorPoolCreateInfo m_PoolInfo;
 
 		/**
-        * Contains all the descriptor set layout descriptions
-        * that were requested by the user in calls of createDescriptorSetLayout.
-        */
+         * Contains all the descriptor set layout descriptions
+         * that were requested by the user in calls of createDescriptorSetLayout.
+         */
         std::vector<DescriptorSetLayout> m_DescriptorSetLayouts;
 
         /**
-		* Contains all the descriptor sets that were created by the user in calls of createDescriptorSet.
-		*/
+		 * Contains all the descriptor sets that were created by the user in calls of createDescriptorSet.
+		 */
         std::vector<DescriptorSet> m_DescriptorSets;
 
 		/**
-		* Destroys a specific descriptor set
-		* @param[in] the DescriptorSetHandle
-		*/
+		 * @brief Destroys a specific descriptor set.
+		 *
+		 * @param[in] the DescriptorSetHandle
+		 */
 		void destroyDescriptorSetById(uint64_t id);
 
 		/**
-        * Destroys a specific descriptor set LAYOUT (not the set)
-        * @param[in] the DescriptorSetLayoutHandle
-        */
+         * @brief Revokes the usage of a specific descriptor set layout and
+         * destroys it once the usage count is at zero.
+         *
+         * @param[in] the DescriptorSetLayoutHandle
+         */
 		void destroyDescriptorSetLayoutById(uint64_t id);
 
 		/**
-		* creates a descriptor pool based on the poolSizes and poolInfo defined in the constructor
-		* is called initially in the constructor and then every time the pool runs out memory
-		* @return a DescriptorPool object
-		*/
+		 * @brief Creates a descriptor pool based on the poolSizes and poolInfo defined in the
+		 * constructor is called initially in the constructor and then every time the pool runs
+		 * out memory.
+		 *
+		 * @return a DescriptorPool object
+		 */
 		vk::DescriptorPool allocateDescriptorPool();
 		
 	};
+	
 }
\ No newline at end of file
diff --git a/src/vkcv/DescriptorWrites.cpp b/src/vkcv/DescriptorWrites.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2dbf1b253d45c32ee1d7883aa0363c5640d023bb
--- /dev/null
+++ b/src/vkcv/DescriptorWrites.cpp
@@ -0,0 +1,75 @@
+
+#include "vkcv/DescriptorWrites.hpp"
+
+namespace vkcv {
+	
+	DescriptorWrites &DescriptorWrites::writeSampledImage(uint32_t binding,
+														  ImageHandle image,
+														  uint32_t mipLevel,
+														  bool useGeneralLayout,
+														  uint32_t arrayIndex) {
+		m_sampledImageWrites.emplace_back(binding, image, mipLevel, useGeneralLayout, arrayIndex);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeStorageImage(uint32_t binding,
+														  ImageHandle image,
+														  uint32_t mipLevel) {
+		m_storageImageWrites.emplace_back(binding, image, mipLevel);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeUniformBuffer(uint32_t binding,
+														   BufferHandle buffer,
+														   bool dynamic,
+														   uint32_t offset,
+														   uint32_t size) {
+		m_uniformBufferWrites.emplace_back(binding, buffer, dynamic, offset, size);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeStorageBuffer(uint32_t binding,
+														   BufferHandle buffer,
+														   bool dynamic,
+														   uint32_t offset,
+														   uint32_t size) {
+		m_storageBufferWrites.emplace_back(binding, buffer, dynamic, offset, size);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeSampler(uint32_t binding,
+													 SamplerHandle sampler) {
+		m_samplerWrites.emplace_back(binding, sampler);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeAcceleration(uint32_t binding) {
+		m_accelerationWrites.emplace_back(binding);
+		return *this;
+	}
+	
+	const std::vector<SampledImageDescriptorWrite> &DescriptorWrites::getSampledImageWrites() const {
+		return m_sampledImageWrites;
+	}
+	
+	const std::vector<StorageImageDescriptorWrite> &DescriptorWrites::getStorageImageWrites() const {
+		return m_storageImageWrites;
+	}
+	
+	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getUniformBufferWrites() const {
+		return m_uniformBufferWrites;
+	}
+	
+	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getStorageBufferWrites() const {
+		return m_storageBufferWrites;
+	}
+	
+	const std::vector<SamplerDescriptorWrite> &DescriptorWrites::getSamplerWrites() const {
+		return m_samplerWrites;
+	}
+	
+	const std::vector<AccelerationDescriptorWrite> &DescriptorWrites::getAccelerationWrites() const {
+		return m_accelerationWrites;
+	}
+	
+}
diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp
index e13b4d24148e9d76d8be4ad7fd3db0db87249c59..eef87ca65d5f461f1c37b678634cf3e6f8973397 100644
--- a/src/vkcv/DrawcallRecording.cpp
+++ b/src/vkcv/DrawcallRecording.cpp
@@ -5,28 +5,21 @@
 
 namespace vkcv {
 
-    struct MeshShaderFunctions
-    {
-        PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasks                           = nullptr;
-        PFN_vkCmdDrawMeshTasksIndirectNV cmdDrawMeshTasksIndirect           = nullptr;
-        PFN_vkCmdDrawMeshTasksIndirectCountNV cmdDrawMeshTasksIndirectCount = nullptr;
-    } MeshShaderFunctions;
-
-    void InitMeshShaderDrawFunctions(vk::Device device)
-    {
-        MeshShaderFunctions.cmdDrawMeshTasks = PFN_vkCmdDrawMeshTasksNV(device.getProcAddr("vkCmdDrawMeshTasksNV"));
-        MeshShaderFunctions.cmdDrawMeshTasksIndirect = PFN_vkCmdDrawMeshTasksIndirectNV(device.getProcAddr("vkCmdDrawMeshTasksIndirectNV"));
-        MeshShaderFunctions.cmdDrawMeshTasksIndirectCount = PFN_vkCmdDrawMeshTasksIndirectCountNV (device.getProcAddr( "vkCmdDrawMeshTasksIndirectCountNV"));
-    }
-
-    void recordMeshShaderDrawcall(
-		const Core&								core,
-        vk::CommandBuffer                       cmdBuffer,
-        vk::PipelineLayout                      pipelineLayout,
-        const PushConstants&                    pushConstantData,
-        const uint32_t                          pushConstantOffset,
-        const MeshShaderDrawcall&               drawcall,
-        const uint32_t                          firstTask) {
+    void recordMeshShaderDrawcall(const Core& core,
+                                  vk::CommandBuffer cmdBuffer,
+                                  vk::PipelineLayout pipelineLayout,
+                                  const PushConstants& pushConstantData,
+                                  uint32_t pushConstantOffset,
+                                  const MeshShaderDrawcall& drawcall,
+                                  uint32_t firstTask) {
+        static PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasks = reinterpret_cast<PFN_vkCmdDrawMeshTasksNV>(
+                core.getContext().getDevice().getProcAddr("vkCmdDrawMeshTasksNV")
+        );
+	
+		if (!cmdDrawMeshTasks) {
+			vkcv_log(LogLevel::ERROR, "Mesh shader drawcalls are not supported");
+			return;
+		}
 
         for (const auto& descriptorUsage : drawcall.descriptorSets) {
             cmdBuffer.bindDescriptorSets(
@@ -48,7 +41,7 @@ namespace vkcv {
                 pushConstantData.getSizePerDrawcall(),
                 drawcallPushConstantData);
         }
-
-        MeshShaderFunctions.cmdDrawMeshTasks(VkCommandBuffer(cmdBuffer), drawcall.taskCount, firstTask);
+    
+        cmdDrawMeshTasks(VkCommandBuffer(cmdBuffer), drawcall.taskCount, firstTask);
     }
 }
diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp
index f89eb0717b82e40b10f98673e6d42fc07e67a8fd..af4426252d840bdffd7d210d900be64d6b74f6f3 100644
--- a/src/vkcv/FeatureManager.cpp
+++ b/src/vkcv/FeatureManager.cpp
@@ -1,9 +1,12 @@
 
 #include "vkcv/FeatureManager.hpp"
 
-#include <stddef.h>
-#include <string.h>
+#include <cstddef>
+#include <cstring>
+
+#ifdef _MSVC_LANG
 #include <type_traits>
+#endif
 
 namespace vkcv {
 	
diff --git a/src/vkcv/File.cpp b/src/vkcv/File.cpp
index 6006b90f74e0a41f83483f2a1efbe5bda4c4e9f8..871dc06611903d5fb5cc8a9e3d53233510125826 100644
--- a/src/vkcv/File.cpp
+++ b/src/vkcv/File.cpp
@@ -1,7 +1,7 @@
 
 #include "vkcv/File.hpp"
 
-#include <stdlib.h>
+#include <cstdlib>
 
 #ifdef _WIN32
 #include <io.h>
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index ab0d9f26fdf482698f679b598d5b087e3674c638..2ebc84ad476bf911e42fc71bbc575db6b16db081 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -110,8 +110,8 @@ namespace vkcv
             vk::PipelineShaderStageCreateInfo*  outCreateInfo) {
 
         assert(outCreateInfo);
-        std::vector<char>           code = shaderProgram.getShader(stage).shaderCode;
-        vk::ShaderModuleCreateInfo  vertexModuleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
+        std::vector<uint32_t>       code = shaderProgram.getShaderBinary(stage);
+        vk::ShaderModuleCreateInfo  vertexModuleInfo({}, code.size() * sizeof(uint32_t), code.data());
         vk::ShaderModule            shaderModule;
         if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess)
             return false;
@@ -263,6 +263,9 @@ namespace vkcv
 			case CullMode::Back:
 				cullMode = vk::CullModeFlagBits::eBack;
 				break;
+			case CullMode::Both:
+				cullMode = vk::CullModeFlagBits::eFrontAndBack;
+				break;
 			default:
 			vkcv_log(LogLevel::ERROR, "Unknown CullMode");
 				cullMode = vk::CullModeFlagBits::eNone;
@@ -365,9 +368,9 @@ namespace vkcv
 																const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) {
 		static vk::PushConstantRange pushConstantRange;
 		
-		const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize();
+		const size_t pushConstantsSize = config.m_ShaderProgram.getPushConstantsSize();
 		pushConstantRange = vk::PushConstantRange(
-				vk::ShaderStageFlagBits::eAll, 0, pushConstantSize
+				vk::ShaderStageFlagBits::eAll, 0, pushConstantsSize
 		);
 		
 		vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo(
@@ -376,7 +379,7 @@ namespace vkcv
 				(pushConstantRange)
 		);
 		
-		if (pushConstantSize == 0) {
+		if (pushConstantsSize == 0) {
 			pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
 		}
 		
diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp
index 09900c37760f07d1967aa56a75cfc8b94aa289d5..511dcf47988028617712c191f79bdf1f292a200a 100644
--- a/src/vkcv/GraphicsPipelineManager.hpp
+++ b/src/vkcv/GraphicsPipelineManager.hpp
@@ -17,6 +17,10 @@
 
 namespace vkcv
 {
+	
+	/**
+	 * @brief Class to manage graphics pipelines.
+	 */
     class GraphicsPipelineManager
     {
     public:
@@ -82,4 +86,5 @@ namespace vkcv
         void destroyPipelineById(uint64_t id);
 
     };
+	
 }
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 124508d5e36711a13ad49ae289b9de98600e0d6e..aedf726031ef43ac723b93f3dbd1276d92f3f704 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -14,8 +14,19 @@
 
 namespace vkcv {
 	
+	/**
+	 * @brief Determine whether an image format is valid
+	 * for depth buffers.
+	 *
+	 * @param[in] format Image format
+	 * @return True, if the format is usable for depth buffers, otherwise false.
+	 */
 	bool isDepthImageFormat(vk::Format format);
 
+	/**
+	 * @brief Class to manage the creation, destruction, allocation
+	 * and filling of images.
+	 */
 	class ImageManager
 	{
 		friend class Core;
diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp
deleted file mode 100644
index b203fab4f02afcc8f51b468ab4504480a8e60e4e..0000000000000000000000000000000000000000
--- a/src/vkcv/PassConfig.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "vkcv/PassConfig.hpp"
-
-#include <utility>
-
-namespace vkcv
-{
-    AttachmentDescription::AttachmentDescription(
-		AttachmentOperation store_op,
-		AttachmentOperation load_op,
-		vk::Format format) noexcept :
-	store_operation{store_op},
-	load_operation{load_op},
-	format(format)
-    {}
-
-    PassConfig::PassConfig(std::vector<AttachmentDescription> attachments, Multisampling msaa) noexcept :
-    attachments{std::move(attachments) }, msaa(msaa)
-    {}
-}
\ No newline at end of file
diff --git a/src/vkcv/PassManager.hpp b/src/vkcv/PassManager.hpp
index 661a8b277ecb446c4bbaeeb63560ffde28c31d99..1ef976e0482ea39afad33346068f2a168eac70d8 100644
--- a/src/vkcv/PassManager.hpp
+++ b/src/vkcv/PassManager.hpp
@@ -7,6 +7,10 @@
 
 namespace vkcv
 {
+	
+	/**
+	 * @brief Class to manage the creation and destruction of passes.
+	 */
     class PassManager
     {
     private:
@@ -40,4 +44,5 @@ namespace vkcv
         const PassConfig& getPassConfig(const PassHandle &handle) const;
         
     };
+	
 }
diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp
index ff134041bdc6279d312df668cab448a50750f1c3..d2a4d593b6a3648e9d0f01404643999ed406c26d 100644
--- a/src/vkcv/QueueManager.cpp
+++ b/src/vkcv/QueueManager.cpp
@@ -9,166 +9,6 @@
 
 namespace vkcv {
 
-    /**
-     * Given the @p physicalDevice and the @p queuePriorities, the @p queueCreateInfos are computed. First, the requested
-     * queues are sorted by priority depending on the availability of queues in the queue families of the given
-     * @p physicalDevice. Then check, if all requested queues are creatable. If so, the @p queueCreateInfos will be computed.
-     * Furthermore, lists of index pairs (queueFamilyIndex, queueIndex) for later referencing of the separate queues will
-     * be computed.
-     * @param[in] physicalDevice The physical device
-     * @param[in] queuePriorities The queue priorities used for the computation of @p queueCreateInfos
-     * @param[in] queueFlags The queue flags requesting the queues
-     * @param[in,out] queueCreateInfos The queue create info structures to be created
-     * @param[in,out] queuePairsGraphics The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
-     *      vk::QueueFlagBits::eGraphics
-     * @param[in,out] queuePairsCompute The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
-     *      vk::QueueFlagBits::eCompute
-     * @param[in,out] queuePairsTransfer The list of index pairs (queueFamilyIndex, queueIndex) of queues of type
-     *      vk::QueueFlagBits::eTransfer
-     * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due to insufficient availability.
-     */
-    void QueueManager::queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
-                                      const std::vector<float> &queuePriorities,
-                                      const std::vector<vk::QueueFlagBits> &queueFlags,
-                                      std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
-                                      std::vector<std::pair<int, int>> &queuePairsGraphics,
-                                      std::vector<std::pair<int, int>> &queuePairsCompute,
-                                      std::vector<std::pair<int, int>> &queuePairsTransfer)
-    {
-        queueCreateInfos = {};
-        queuePairsGraphics = {};
-        queuePairsCompute = {};
-        queuePairsTransfer = {};
-        std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
-
-        //check priorities of flags -> the lower prioCount the higher the priority
-        std::vector<int> prios;
-        for(auto flag: queueFlags) {
-            int prioCount = 0;
-            for (size_t i = 0; i < qFamilyProperties.size(); i++) {
-                prioCount += (static_cast<uint32_t>(flag & qFamilyProperties[i].queueFlags) != 0) * qFamilyProperties[i].queueCount;
-            }
-            prios.push_back(prioCount);
-        }
-        //resort flags with heighest priority before allocating the queues
-        std::vector<vk::QueueFlagBits> newFlags;
-        for(size_t i = 0; i < prios.size(); i++) {
-            auto minElem = std::min_element(prios.begin(), prios.end());
-            int index = minElem - prios.begin();
-            newFlags.push_back(queueFlags[index]);
-            prios[index] = std::numeric_limits<int>::max();
-        }
-
-        // create requested queues and check if more requested queues are supported
-        // herefore: create vector that updates available queues in each queue family
-        // structure: [qFamily_0, ..., qFamily_n] where
-        // - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n
-        std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
-
-        for (auto qFamily : qFamilyProperties) {
-            auto graphicsCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0? qFamily.queueCount : 0;
-			auto computeCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0? qFamily.queueCount : 0;
-			auto transferCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0? qFamily.queueCount : 0;
-            queueFamilyStatus.push_back({
-				static_cast<int>(graphicsCount),
-				static_cast<int>(computeCount),
-				static_cast<int>(transferCount)
-			});
-        }
-
-        initialQueueFamilyStatus = queueFamilyStatus;
-        // check if every queue with the specified queue flag can be created
-        // this automatically checks for queue flag support!
-        for (auto qFlag : newFlags) {
-            bool found;
-            switch (qFlag) {
-                case vk::QueueFlagBits::eGraphics:
-                    found = false;
-                    for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                        if (queueFamilyStatus[i][0] > 0) {
-                            queuePairsGraphics.emplace_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]));
-                            queueFamilyStatus[i][0]--;
-                            queueFamilyStatus[i][1]--;
-                            queueFamilyStatus[i][2]--;
-                            found = true;
-                        }
-                    }
-                    if (!found) {
-                        for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                            if (initialQueueFamilyStatus[i][0] > 0) {
-                                queuePairsGraphics.emplace_back(std::pair(i, 0));
-                                found = true;
-                            }
-                        }
-	
-						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
-                    }
-                    break;
-                case vk::QueueFlagBits::eCompute:
-                    found = false;
-                    for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                        if (queueFamilyStatus[i][1] > 0) {
-                            queuePairsCompute.emplace_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1]));
-                            queueFamilyStatus[i][0]--;
-                            queueFamilyStatus[i][1]--;
-                            queueFamilyStatus[i][2]--;
-                            found = true;
-                        }
-                    }
-                    if (!found) {
-                        for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                            if (initialQueueFamilyStatus[i][1] > 0) {
-                                queuePairsCompute.emplace_back(std::pair(i, 0));
-                                found = true;
-                            }
-                        }
-                        
-						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
-                    }
-                    break;
-                case vk::QueueFlagBits::eTransfer:
-                    found = false;
-                    for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                        if (queueFamilyStatus[i][2] > 0) {
-                            queuePairsTransfer.emplace_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2]));
-                            queueFamilyStatus[i][0]--;
-                            queueFamilyStatus[i][1]--;
-                            queueFamilyStatus[i][2]--;
-                            found = true;
-                        }
-                    }
-                    if (!found) {
-                        for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) {
-                            if (initialQueueFamilyStatus[i][2] > 0) {
-                                queuePairsTransfer.emplace_back(std::pair(i, 0));
-                                found = true;
-                            }
-                        }
-	
-						vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
-                    }
-                    break;
-                default:
-					vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", vk::to_string(qFlag).c_str());
-					break;
-            }
-        }
-
-        // create all requested queues
-        for (size_t i = 0; i < qFamilyProperties.size(); i++) {
-            uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]);
-            if (create > 0) {
-                vk::DeviceQueueCreateInfo qCreateInfo(
-                        vk::DeviceQueueCreateFlags(),
-                        i,
-                        create,
-                        queuePriorities.data()
-                );
-                queueCreateInfos.push_back(qCreateInfo);
-            }
-        }
-    }
-
     /**
      * Computes the queue handles from @p queuePairs
      * @param device The device
@@ -190,9 +30,9 @@ namespace vkcv {
 
 
     QueueManager QueueManager::create(vk::Device device,
-                                      std::vector<std::pair<int, int>> &queuePairsGraphics,
-                                      std::vector<std::pair<int, int>> &queuePairsCompute,
-                                      std::vector<std::pair<int, int>> &queuePairsTransfer) {
+									  const std::vector<std::pair<int, int>> &queuePairsGraphics,
+									  const std::vector<std::pair<int, int>> &queuePairsCompute,
+									  const std::vector<std::pair<int, int>> &queuePairsTransfer) {
 
         std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics);
         std::vector<Queue> computeQueues  = getQueues(device, queuePairsCompute);
@@ -201,10 +41,8 @@ namespace vkcv {
     	return QueueManager( std::move(graphicsQueues), std::move(computeQueues), std::move(transferQueues), 0);
 	}
 
-	uint32_t QueueManager::checkSurfaceSupport(
-			const vk::PhysicalDevice &physicalDevice,
-			vk::SurfaceKHR &surface
-	) {
+	uint32_t QueueManager::checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice,
+											   const vk::SurfaceKHR &surface) {
 		std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
 
 		for(uint32_t i = 0; i < qFamilyProperties.size(); i++) {
diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp
index 128faa711993ac052cf774a1d31144d19362658f..24d89f0d6af151ff009a2f2bb64953d48a9e7213 100644
--- a/src/vkcv/SamplerManager.hpp
+++ b/src/vkcv/SamplerManager.hpp
@@ -10,6 +10,9 @@ namespace vkcv {
 	
 	class Core;
 	
+	/**
+	 * @brief Class to manage the creation and destruction of samplers.
+	 */
 	class SamplerManager {
 		friend class Core;
 	private:
diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp
index 504d8fcdbd84935db339370b15c31ccefe26e02b..97eea880cbc38fee1a71d52a1e154471344d7758 100644
--- a/src/vkcv/ShaderProgram.cpp
+++ b/src/vkcv/ShaderProgram.cpp
@@ -14,19 +14,25 @@ namespace vkcv {
      * @param[in] relative path to the shader code
      * @return vector of chars as a buffer for the code
      */
-	std::vector<char> readShaderCode(const std::filesystem::path &shaderPath) {
+	std::vector<uint32_t> readShaderCode(const std::filesystem::path &shaderPath) {
 		std::ifstream file (shaderPath.string(), std::ios::ate | std::ios::binary);
 		
 		if (!file.is_open()) {
-			vkcv_log(LogLevel::ERROR, "The file could not be opened");
-			return std::vector<char>{};
+			vkcv_log(LogLevel::ERROR, "The file could not be opened: %s", shaderPath.c_str());
+			return std::vector<uint32_t>();
 		}
 		
 		size_t fileSize = (size_t)file.tellg();
-		std::vector<char> buffer(fileSize);
+
+        if (fileSize % sizeof(uint32_t) != 0) {
+            vkcv_log(LogLevel::ERROR, "The file is not a valid shader: %s", shaderPath.c_str());
+            return std::vector<uint32_t>();
+        }
+
+		std::vector<uint32_t> buffer(fileSize / sizeof(uint32_t));
 		
 		file.seekg(0);
-		file.read(buffer.data(), fileSize);
+		file.read(reinterpret_cast<char*>(buffer.data()), fileSize);
 		file.close();
 		
         return buffer;
@@ -76,32 +82,31 @@ namespace vkcv {
     m_DescriptorSets{}
 	{}
 
-	bool ShaderProgram::addShader(ShaderStage shaderStage, const std::filesystem::path &shaderPath)
+	bool ShaderProgram::addShader(ShaderStage stage, const std::filesystem::path &path)
 	{
-	    if(m_Shaders.find(shaderStage) != m_Shaders.end()) {
+	    if(m_Shaders.find(stage) != m_Shaders.end()) {
 			vkcv_log(LogLevel::WARNING, "Overwriting existing shader stage");
 		}
 
-	    const std::vector<char> shaderCode = readShaderCode(shaderPath);
+	    const std::vector<uint32_t> shaderCode = readShaderCode(path);
 	    
 	    if (shaderCode.empty()) {
 			return false;
 		} else {
-            Shader shader{shaderCode, shaderStage};
-            m_Shaders.insert(std::make_pair(shaderStage, shader));
-            reflectShader(shaderStage);
+            m_Shaders.insert(std::make_pair(stage, shaderCode));
+            reflectShader(stage);
             return true;
         }
 	}
 
-    const Shader &ShaderProgram::getShader(ShaderStage shaderStage) const
+    const std::vector<uint32_t> &ShaderProgram::getShaderBinary(ShaderStage stage) const
     {
-	    return m_Shaders.at(shaderStage);
+	    return m_Shaders.at(stage);
 	}
 
-    bool ShaderProgram::existsShader(ShaderStage shaderStage) const
+    bool ShaderProgram::existsShader(ShaderStage stage) const
     {
-	    if(m_Shaders.find(shaderStage) == m_Shaders.end())
+	    if(m_Shaders.find(stage) == m_Shaders.end())
 	        return false;
 	    else
 	        return true;
@@ -109,13 +114,9 @@ namespace vkcv {
 
     void ShaderProgram::reflectShader(ShaderStage shaderStage)
     {
-        auto shaderCodeChar = m_Shaders.at(shaderStage).shaderCode;
-        std::vector<uint32_t> shaderCode;
-
-        for (uint32_t i = 0; i < shaderCodeChar.size()/4; i++)
-            shaderCode.push_back(((uint32_t*) shaderCodeChar.data())[i]);
+        auto shaderCode = m_Shaders.at(shaderStage);
 
-        spirv_cross::Compiler comp(move(shaderCode));
+        spirv_cross::Compiler comp(shaderCode);
         spirv_cross::ShaderResources resources = comp.get_shader_resources();
 
         //reflect vertex input
@@ -135,7 +136,12 @@ namespace vkcv {
 				// vertex input format (implies its size)
 				const VertexAttachmentFormat attachment_format = convertFormat(base_type.basetype, base_type.vecsize);
 
-                m_VertexAttachments.emplace_back(attachment_loc, attachment_name, attachment_format);
+                m_VertexAttachments.push_back({
+					attachment_loc,
+					attachment_name,
+					attachment_format,
+					0
+				});
             }
 		}
 
@@ -346,12 +352,12 @@ namespace vkcv {
 			for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id))
 			{
 				const size_t size = range.range + range.offset;
-				m_pushConstantSize = std::max(m_pushConstantSize, size);
+				m_pushConstantsSize = std::max(m_pushConstantsSize, size);
 			}
 		}
     }
 
-    const std::vector<VertexAttachment> &ShaderProgram::getVertexAttachments() const
+    const VertexAttachments &ShaderProgram::getVertexAttachments() const
     {
         return m_VertexAttachments;
 	}
@@ -361,8 +367,8 @@ namespace vkcv {
         return m_DescriptorSets;
     }
 
-	size_t ShaderProgram::getPushConstantSize() const
+	size_t ShaderProgram::getPushConstantsSize() const
 	{
-		return m_pushConstantSize;
+		return m_pushConstantsSize;
 	}
 }
diff --git a/src/vkcv/Surface.cpp b/src/vkcv/Surface.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3fa601b7bed751b1eb70538a0e2cf10c0b7b50f7
--- /dev/null
+++ b/src/vkcv/Surface.cpp
@@ -0,0 +1,258 @@
+
+#include <vkcv/Surface.hpp>
+#include <vkcv/Logger.hpp>
+
+#include <GLFW/glfw3.h>
+
+namespace vkcv {
+	
+	/**
+    * @brief Creates vulkan surface and checks availability.
+    *
+    * @param[in,out] window Current window for the surface
+    * @param[in,out] instance Vulkan-Instance
+    * @param[in,out] physicalDevice Vulkan-PhysicalDevice
+    * @param[out] surface Vulkan-Surface
+    * @return Created vulkan surface
+    */
+	bool createVulkanSurface(GLFWwindow* window,
+							 const vk::Instance& instance,
+							 const vk::PhysicalDevice& physicalDevice,
+							 vk::SurfaceKHR& surface) {
+		VkSurfaceKHR api_surface;
+		
+		if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &api_surface) != VK_SUCCESS) {
+			vkcv_log(LogLevel::ERROR, "Failed to create a window surface");
+			return false;
+		}
+		
+		vk::Bool32 surfaceSupport = false;
+		surface = vk::SurfaceKHR(api_surface);
+		
+		if ((physicalDevice.getSurfaceSupportKHR(0, surface, &surfaceSupport) != vk::Result::eSuccess) ||
+			(!surfaceSupport)) {
+			vkcv_log(LogLevel::ERROR, "Surface is not supported by the device");
+			instance.destroy(surface);
+			surface = nullptr;
+			return false;
+		}
+		
+		return true;
+	}
+	
+	/**
+     * @brief Chooses an Extent and clamps values to the available capabilities.
+     *
+     * @param physicalDevice Vulkan-PhysicalDevice
+     * @param surface Vulkan-Surface of the swapchain
+     * @param window Window of the current application
+     * @return Chosen Extent for the surface
+     */
+	vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) {
+		int fb_width, fb_height;
+		window.getFramebufferSize(fb_width, fb_height);
+		
+		VkExtent2D extent2D = {
+				static_cast<uint32_t>(fb_width),
+				static_cast<uint32_t>(fb_height)
+		};
+		
+		vk::SurfaceCapabilitiesKHR surfaceCapabilities;
+		if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) {
+			vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved");
+			
+			extent2D.width = std::max(MIN_SURFACE_SIZE, extent2D.width);
+			extent2D.height = std::max(MIN_SURFACE_SIZE, extent2D.height);
+		} else {
+			extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width));
+			extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height));
+		}
+		
+		return extent2D;
+	}
+	
+	/**
+     * @brief Chooses Surface Format for the current surface
+     *
+     * @param physicalDevice Vulkan-PhysicalDevice
+     * @param surface Vulkan-Surface of the swapchain
+     * @return Available Format
+     */
+	vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
+		std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface);
+		
+		for (const auto& availableFormat : availableFormats) {
+			if (availableFormat.format == vk::Format::eB8G8R8A8Unorm  && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
+				return availableFormat;
+			}
+		}
+		
+		return availableFormats[0];
+	}
+	
+	/**
+     * @brief Returns vk::PresentModeKHR::eMailbox if available or
+     * vk::PresentModeKHR::eFifo otherwise
+     *
+     * @param physicalDevice Vulkan-PhysicalDevice
+     * @param surface Vulkan-Surface of the swapchain
+     * @return Available PresentationMode
+     */
+	vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
+		std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface);
+		
+		for (const auto& availablePresentMode : availablePresentModes) {
+			if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
+				return availablePresentMode;
+			}
+		}
+		// The FIFO present mode is guaranteed by the spec to be supported
+		return vk::PresentModeKHR::eFifo;
+	}
+	
+	/**
+	* @brief Returns the minImageCount +1 for at least double buffering,
+	* if it's greater than maxImageCount return maxImageCount
+	*
+	* @param physicalDevice Vulkan-PhysicalDevice
+	* @param surface Vulkan-Surface of the swapchain
+	* @return Available image count
+	*/
+	uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
+		vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface);
+		
+		// minImageCount should always be at least 2; set to 3 for triple buffering
+		uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
+		
+		// check if requested image count is supported
+		if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
+			imageCount = surfaceCapabilities.maxImageCount;
+		}
+		
+		return imageCount;
+	}
+	
+	Surface::Surface(const Context &context,
+					 const vk::SurfaceKHR &handle,
+					 uint32_t presentQueueIndex,
+					 const vk::Extent2D &extent,
+					 vk::Format format,
+					 vk::ColorSpaceKHR colorSpace)
+					 : m_Context(&context),
+					   m_Handle(handle),
+					   m_PresentQueueIndex(presentQueueIndex),
+					   m_Extent(extent),
+					   m_Format(format),
+					   m_ColorSpace(colorSpace) {
+	}
+	
+	vk::SwapchainKHR Surface::createVulkanSwapchain(const Window &window,
+													const vk::SwapchainKHR &oldSwapchain) {
+		if ((!m_Context) || (!m_Handle))
+			return nullptr;
+		
+		const vk::PhysicalDevice& physicalDevice = m_Context->getPhysicalDevice();
+		const vk::Device& device = m_Context->getDevice();
+		
+		m_Extent = chooseExtent(physicalDevice, m_Handle, window);
+		
+		if ((m_Extent.width < MIN_SURFACE_SIZE) || (m_Extent.height < MIN_SURFACE_SIZE)) {
+			return nullptr;
+		}
+		
+		vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, m_Handle);
+		vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, m_Handle);
+		uint32_t chosenImageCount = chooseImageCount(physicalDevice, m_Handle);
+		
+		m_Format = chosenSurfaceFormat.format;
+		m_ColorSpace = chosenSurfaceFormat.colorSpace;
+		
+		vk::SwapchainCreateInfoKHR swapchainCreateInfo (
+				vk::SwapchainCreateFlagsKHR(),
+				m_Handle,
+				chosenImageCount,
+				m_Format,
+				m_ColorSpace,
+				m_Extent,
+				1,
+				vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage,
+				vk::SharingMode::eExclusive,
+				0,
+				nullptr,
+				vk::SurfaceTransformFlagBitsKHR::eIdentity,
+				vk::CompositeAlphaFlagBitsKHR::eOpaque,
+				chosenPresentMode,
+				true,
+				oldSwapchain
+		);
+		
+		return device.createSwapchainKHR(swapchainCreateInfo);
+	}
+	
+	Surface::Surface(Surface &&other) noexcept
+	: m_Context(other.m_Context),
+	  m_Handle(other.m_Handle),
+	  m_PresentQueueIndex(other.m_PresentQueueIndex),
+	  m_Extent(other.m_Extent),
+	  m_Format(other.m_Format),
+	  m_ColorSpace(other.m_ColorSpace) {
+		other.m_Context = nullptr;
+		other.m_Handle = nullptr;
+	}
+	
+	Surface &Surface::operator=(Surface &&other) noexcept {
+		m_Context = other.m_Context;
+		m_Handle = other.m_Handle;
+		m_PresentQueueIndex = other.m_PresentQueueIndex;
+		m_Extent = other.m_Extent;
+		m_Format = other.m_Format;
+		m_ColorSpace = other.m_ColorSpace;
+		
+		other.m_Context = nullptr;
+		other.m_Handle = nullptr;
+		return *this;
+	}
+	
+	Surface::~Surface() {
+		// needs to be destroyed by creator
+	}
+	
+	Surface Surface::create(const Window &window, const Context &context) {
+		const vk::Instance& instance = context.getInstance();
+		const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
+		
+		uint32_t presentQueueIndex = 0;
+		
+		vk::SurfaceKHR surfaceHandle;
+		if (!createVulkanSurface(window.getWindow(), instance, physicalDevice, surfaceHandle))
+			surfaceHandle = nullptr;
+		else
+			presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surfaceHandle);
+		
+		const vk::Extent2D extent = chooseExtent(physicalDevice, surfaceHandle, window);
+		const vk::SurfaceFormatKHR format = chooseSurfaceFormat(physicalDevice, surfaceHandle);
+		
+		return { context, surfaceHandle, presentQueueIndex, extent, format.format, format.colorSpace };
+	}
+	
+	vk::SurfaceKHR Surface::getSurface() const {
+		return m_Handle;
+	}
+	
+	uint32_t Surface::getPresentQueueIndex() const {
+		return m_PresentQueueIndex;
+	}
+	
+	const vk::Extent2D& Surface::getExtent() const {
+		return m_Extent;
+	}
+	
+	vk::Format Surface::getFormat() const {
+		return m_Format;
+	}
+	
+	vk::ColorSpaceKHR Surface::getColorSpace() const {
+		return m_ColorSpace;
+	}
+
+}
diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp
index 483732927bc2cc507f0868226b65bf4d49e27048..2ca69e7d58991ee67d8e72261e1cddf65de60ed0 100644
--- a/src/vkcv/Swapchain.cpp
+++ b/src/vkcv/Swapchain.cpp
@@ -5,203 +5,43 @@
 
 namespace vkcv
 {
-    /**
-    * creates surface and checks availability
-    * @param window current window for the surface
-    * @param instance Vulkan-Instance
-    * @param physicalDevice Vulkan-PhysicalDevice
-    * @return created surface
-    */
-    vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) {
-        //create surface
-        VkSurfaceKHR surface;
-        if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) {
-            throw std::runtime_error("failed to create a window surface!");
-        }
-        vk::Bool32 surfaceSupport = false;
-        if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) {
-            throw std::runtime_error("surface is not supported by the device!");
-        }
 
-        return vk::SurfaceKHR(surface);
-    }
-
-    Swapchain::Swapchain(const Surface &surface,
-                         vk::SwapchainKHR swapchain,
-                         vk::Format format,
-                         vk::ColorSpaceKHR colorSpace,
-                         vk::PresentModeKHR presentMode,
-                         uint32_t imageCount,
-						 vk::Extent2D extent) noexcept :
-			m_Surface(surface),
-			m_Swapchain(swapchain),
-			m_Format(format),
-			m_ColorSpace(colorSpace),
-			m_PresentMode(presentMode),
-			m_ImageCount(imageCount),
-			m_Extent(extent),
-			m_RecreationRequired(false)
-    {}
+    Swapchain::Swapchain(const Context &context,
+						 const Surface &surface,
+                         vk::SwapchainKHR swapchain) noexcept
+						 : m_Context(&context),
+						   m_Surface(surface),
+						   m_Swapchain(swapchain),
+						   m_RecreationRequired(false) {
+	}
     
     Swapchain::Swapchain(const Swapchain &other) :
-			m_Surface(other.m_Surface),
-			m_Swapchain(other.m_Swapchain),
-			m_Format(other.m_Format),
-			m_ColorSpace(other.m_ColorSpace),
-			m_PresentMode(other.m_PresentMode),
-			m_ImageCount(other.m_ImageCount),
-			m_Extent(other.m_Extent),
-			m_RecreationRequired(other.m_RecreationRequired.load())
-	{}
+	m_Context(other.m_Context),
+	m_Surface(other.m_Surface),
+	m_Swapchain(other.m_Swapchain),
+	m_RecreationRequired(other.m_RecreationRequired.load()) {
+	}
 
     const vk::SwapchainKHR& Swapchain::getSwapchain() const {
         return m_Swapchain;
     }
 
-    vk::SurfaceKHR Swapchain::getSurface() const {
-        return m_Surface.handle;
+    const Surface& Swapchain::getSurface() const {
+        return m_Surface;
     }
 
     vk::Format Swapchain::getFormat() const{
-        return m_Format;
+        return m_Surface.getFormat();
     }
 
-    /**
-     * chooses Extent and clapms values to the available
-     * @param physicalDevice Vulkan-PhysicalDevice
-     * @param surface of the swapchain
-     * @param window of the current application
-     * @return chosen Extent for the surface
-     */
-    vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) {
-        int fb_width, fb_height;
-        window.getFramebufferSize(fb_width, fb_height);
-        
-        VkExtent2D extent2D = {
-                static_cast<uint32_t>(fb_width),
-                static_cast<uint32_t>(fb_height)
-        };
-	
-		vk::SurfaceCapabilitiesKHR surfaceCapabilities;
-		if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) {
-			vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved");
-			
-			extent2D.width = std::max(MIN_SWAPCHAIN_SIZE, extent2D.width);
-			extent2D.height = std::max(MIN_SWAPCHAIN_SIZE, extent2D.height);
-		} else {
-			extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width));
-			extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height));
-		}
-
-        return extent2D;
-    }
-
-    /**
-     * chooses Surface Format for the current surface
-     * @param physicalDevice Vulkan-PhysicalDevice
-     * @param surface of the swapchain
-     * @return available Format
-     */
-    vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
-        std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface);
-
-        for (const auto& availableFormat : availableFormats) {
-            if (availableFormat.format == vk::Format::eB8G8R8A8Unorm  && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
-                return availableFormat;
-            }
-        }
-        
-        return availableFormats[0];
-    }
-
-    /**
-     * returns vk::PresentModeKHR::eMailbox if available or vk::PresentModeKHR::eFifo otherwise
-     * @param physicalDevice Vulkan-PhysicalDevice
-     * @param surface of the swapchain
-     * @return available PresentationMode
-     */
-    vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
-        std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface);
-
-        for (const auto& availablePresentMode : availablePresentModes) {
-            if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
-                return availablePresentMode;
-            }
-        }
-        // The FIFO present mode is guaranteed by the spec to be supported
-        return vk::PresentModeKHR::eFifo;
-    }
-
-    /**
-     * returns the minImageCount +1 for at least doublebuffering, if it's greater than maxImageCount return maxImageCount
-     * @param physicalDevice Vulkan-PhysicalDevice
-     * @param surface of the swapchain
-     * @return available ImageCount
-     */
-    uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
-        vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface);
-	
-		// minImageCount should always be at least 2; set to 3 for triple buffering
-        uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
-        
-        // check if requested image count is supported
-        if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
-            imageCount = surfaceCapabilities.maxImageCount;
-        }
-
-        return imageCount;
-    }
-    /**
-     * creates and returns a swapchain with default specs
-     * @param window of the current application
-     * @param context that keeps instance, physicalDevice and a device.
-     * @return swapchain
-     */
     Swapchain Swapchain::create(const Window &window, const Context &context) {
-        const vk::Instance& instance = context.getInstance();
-        const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
-        const vk::Device& device = context.getDevice();
-
-        Surface surface;
-        surface.handle            = createSurface(window.getWindow(), instance, physicalDevice);
-        surface.formats           = physicalDevice.getSurfaceFormatsKHR(surface.handle);
-        surface.capabilities      = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle);
-        surface.presentModes      = physicalDevice.getSurfacePresentModesKHR(surface.handle);
-		surface.presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surface.handle);
+        Surface surface = Surface::create(window, context);
 
-        vk::Extent2D chosenExtent = chooseExtent(physicalDevice, surface.handle, window);
-        vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, surface.handle);
-        vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, surface.handle);
-        uint32_t chosenImageCount = chooseImageCount(physicalDevice, surface.handle);
+        vk::SwapchainKHR swapchain = surface.createVulkanSwapchain(
+				window, nullptr
+		);
 
-        vk::SwapchainCreateInfoKHR swapchainCreateInfo(
-                vk::SwapchainCreateFlagsKHR(),  //flags
-                surface.handle,    // surface
-                chosenImageCount,  // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -> 3 for Triple Buffering, else 2 for Double Buffering (should be the standard)
-                chosenSurfaceFormat.format,   // imageFormat
-                chosenSurfaceFormat.colorSpace,   // imageColorSpace
-                chosenExtent,   // imageExtent
-                1,  // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers"
-                vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage,  // imageUsage TODO: what attachments? only color? depth?
-                vk::SharingMode::eExclusive,    // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues"
-                0,  // queueFamilyIndexCount, the number of queue families having access to the image(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT
-                nullptr,    // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT
-                vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display
-                vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque
-                chosenPresentMode,    // presentMode
-                true,   // clipped
-                nullptr // oldSwapchain
-        );
-
-        vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo);
-
-        return Swapchain(surface,
-                         swapchain,
-                         chosenSurfaceFormat.format,
-                         chosenSurfaceFormat.colorSpace,
-                         chosenPresentMode,
-                         chosenImageCount,
-						 chosenExtent);
+        return { context, surface, swapchain };
     }
     
     bool Swapchain::shouldUpdateSwapchain() const {
@@ -214,40 +54,18 @@ namespace vkcv
 		}
     	
 		vk::SwapchainKHR oldSwapchain = m_Swapchain;
-		vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window);
 	
-		if ((extent2D.width >= MIN_SWAPCHAIN_SIZE) && (extent2D.height >= MIN_SWAPCHAIN_SIZE)) {
-			vk::SwapchainCreateInfoKHR swapchainCreateInfo(
-					vk::SwapchainCreateFlagsKHR(),
-					m_Surface.handle,
-					m_ImageCount,
-					m_Format,
-					m_ColorSpace,
-					extent2D,
-					1,
-					vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage,
-					vk::SharingMode::eExclusive,
-					0,
-					nullptr,
-					vk::SurfaceTransformFlagBitsKHR::eIdentity,
-					vk::CompositeAlphaFlagBitsKHR::eOpaque,
-					m_PresentMode,
-					true,
-					oldSwapchain
-			);
-			
-			m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo);
-		} else {
-			m_Swapchain = nullptr;
-			
+		m_Swapchain = m_Surface.createVulkanSwapchain(
+				window, oldSwapchain
+		);
+		
+		if (!m_Swapchain) {
 			signalSwapchainRecreation();
 		}
 		
 		if (oldSwapchain) {
 			context.getDevice().destroySwapchainKHR(oldSwapchain);
 		}
-		
-		m_Extent = extent2D;
     }
 
     void Swapchain::signalSwapchainRecreation() {
@@ -255,7 +73,7 @@ namespace vkcv
     }
     
     const vk::Extent2D& Swapchain::getExtent() const {
-    	return m_Extent;
+    	return m_Surface.getExtent();
     }
 
     Swapchain::~Swapchain() {
@@ -263,10 +81,16 @@ namespace vkcv
     }
 
 	uint32_t Swapchain::getImageCount() const {
-		return m_ImageCount;
+		uint32_t imageCount = 0;
+		
+		if (vk::Result::eSuccess != m_Context->getDevice().getSwapchainImagesKHR(m_Swapchain, &imageCount, nullptr))
+			return 0;
+		else
+			return imageCount;
 	}
 
-	const uint32_t &Swapchain::getPresentQueueIndex() const {
-		return m_Surface.presentQueueIndex;
+	uint32_t Swapchain::getPresentQueueIndex() const {
+		return m_Surface.getPresentQueueIndex();
 	}
+	
 }
diff --git a/src/vkcv/SwapchainManager.cpp b/src/vkcv/SwapchainManager.cpp
index 0caea9fd0fe47b4f51a53adac9134fb7f81a205a..369e077aabc7a5a80bc4dd668d9c6eea1277e66f 100644
--- a/src/vkcv/SwapchainManager.cpp
+++ b/src/vkcv/SwapchainManager.cpp
@@ -40,9 +40,9 @@ namespace vkcv {
 			swapchain.m_Swapchain = nullptr;
 		}
 		
-		if (swapchain.m_Surface.handle) {
-			m_context->getInstance().destroySurfaceKHR(swapchain.m_Surface.handle);
-			swapchain.m_Surface.handle = nullptr;
+		if (swapchain.m_Surface.m_Handle) {
+			m_context->getInstance().destroySurfaceKHR(swapchain.m_Surface.m_Handle);
+			swapchain.m_Surface.m_Handle = nullptr;
 		}
 	}
 
diff --git a/src/vkcv/SwapchainManager.hpp b/src/vkcv/SwapchainManager.hpp
index 58478ef09af1734bef7df217550d43af74fd8424..285641db25f98d1e3dd8d8ed1375fa27e7db5708 100644
--- a/src/vkcv/SwapchainManager.hpp
+++ b/src/vkcv/SwapchainManager.hpp
@@ -8,8 +8,13 @@
 #include "vkcv/Handles.hpp"
 
 namespace vkcv {
+	
 	class Core;
-
+	
+	/**
+	 * @brief Class to manage the creation, destruction and
+	 * allocation of swapchains.
+	 */
 	class SwapchainManager {
 		friend class Core;
 
@@ -20,11 +25,18 @@ namespace vkcv {
 
 		Context *m_context;
 
+		/**
+		 * destroys a specific swapchain by a given id
+		 * @param id of the swapchain to be destroyed
+		 */
 		void destroySwapchainById(uint64_t id);
 
 	public:
 		SwapchainManager() noexcept;
 
+		/**
+		 * destroys every swapchain
+		 */
 		~SwapchainManager() noexcept;
 
 		SwapchainManager(SwapchainManager &&other) = delete;
@@ -69,4 +81,5 @@ namespace vkcv {
 		 */
 		std::vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle& handle);
 	};
+	
 }
\ No newline at end of file
diff --git a/src/vkcv/SyncResources.cpp b/src/vkcv/SyncResources.cpp
index 9c27fe32452e0ae648565020d92891764ececb3f..8bd53c85e8cdede55d5b1db71d44bf483e24acb1 100644
--- a/src/vkcv/SyncResources.cpp
+++ b/src/vkcv/SyncResources.cpp
@@ -26,7 +26,7 @@ namespace vkcv {
 		return device.createFence(fenceInfo, nullptr, {});
 	}
 
-	void waitForFence(const vk::Device& device, const vk::Fence fence) {
+	void waitForFence(const vk::Device& device, const vk::Fence& fence) {
 		const auto result = device.waitForFences(fence, true, UINT64_MAX);
 		assert(result == vk::Result::eSuccess);
 	}
diff --git a/src/vkcv/VertexLayout.cpp b/src/vkcv/VertexLayout.cpp
index 0edced571502bbaf0e89ff6d45d338ca38b229ca..73e3885bf8f97854712d5b202123c7f7202042d1 100644
--- a/src/vkcv/VertexLayout.cpp
+++ b/src/vkcv/VertexLayout.cpp
@@ -6,6 +6,7 @@
 #include "vkcv/Logger.hpp"
 
 namespace vkcv {
+	
     uint32_t getFormatSize(VertexAttachmentFormat format) {
         switch (format) {
             case VertexAttachmentFormat::FLOAT:
@@ -29,34 +30,18 @@ namespace vkcv {
                 return 0;
         }
     }
+	
+	VertexBinding createVertexBinding(uint32_t bindingLocation, const VertexAttachments &attachments) {
+		VertexBinding binding { bindingLocation, 0, attachments };
+		uint32_t offset = 0;
+		
+		for (auto& attachment : binding.vertexAttachments) {
+			attachment.offset = offset;
+			offset += getFormatSize(attachment.format);
+		}
+		
+		binding.stride = offset;
+		return binding;
+	}
 
-    VertexAttachment::VertexAttachment(uint32_t inputLocation, const std::string &name, VertexAttachmentFormat format) noexcept:
-            inputLocation{inputLocation},
-            name{name},
-            format{format},
-            offset{0}
-    {}
-
-
-    VertexBinding::VertexBinding(uint32_t bindingLocation, const std::vector<VertexAttachment> &attachments) noexcept :
-    bindingLocation{bindingLocation},
-    stride{0},
-    vertexAttachments{attachments}
-    {
-        uint32_t offset = 0;
-        for (auto &attachment : vertexAttachments)
-        {
-            attachment.offset = offset;
-            offset += getFormatSize(attachment.format);
-        }
-        stride = offset;
-    }
-
-    VertexLayout::VertexLayout() noexcept :
-    vertexBindings{}
-    {}
-
-    VertexLayout::VertexLayout(const std::vector<VertexBinding> &bindings) noexcept :
-    vertexBindings{bindings}
-    {}
 }
\ No newline at end of file
diff --git a/src/vkcv/WindowManager.hpp b/src/vkcv/WindowManager.hpp
index 66186c494c38a5af46ffe34cc31b2e86bbbc95db..81658c241174c62359457c04e143accf07253edb 100644
--- a/src/vkcv/WindowManager.hpp
+++ b/src/vkcv/WindowManager.hpp
@@ -9,21 +9,35 @@
 #include "SwapchainManager.hpp"
 
 namespace vkcv {
+	
 	class Context;
 
 	class SwapchainManager;
 
+	/**
+	 * @brief Class to manage the windows of applications.
+	 */
 	class WindowManager {
 		friend class Core;
 
 	private:
+		/**
+		 * vector of all managed windows
+		 */
 		std::vector<Window*> m_windows;
 
+		/**
+		 * destroys a specific window by a given id
+		 * @param id of the window to be destroyed
+		 */
 		void destroyWindowById(uint64_t id);
 
 	public:
 		WindowManager() noexcept;
 
+		/**
+		 * destroys every window
+		 */
 		~WindowManager() noexcept;
 
 		WindowManager(WindowManager &&other) = delete;
@@ -55,4 +69,5 @@ namespace vkcv {
 		Window &getWindow(const WindowHandle handle) const;
 
 	};
+	
 }
\ No newline at end of file