diff --git a/config/Sources.cmake b/config/Sources.cmake
index 1865bd81606ca70794b4bfb98868b9af47904279..d74c407b876be65af141559d96351429fad5c6d4 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -42,6 +42,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
diff --git a/include/vkcv/Surface.hpp b/include/vkcv/Surface.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..18f5a8b909ed505a8d59294c12ae9b5ad1b2b9d9
--- /dev/null
+++ b/include/vkcv/Surface.hpp
@@ -0,0 +1,82 @@
+#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;
+
+	class Surface {
+	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 window Window
+		 * @param 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;
+		
+		[[nodiscard]]
+		uint32_t getPresentQueueIndex() const;
+		
+		[[nodiscard]]
+		const vk::Extent2D& getExtent() const;
+		
+		[[nodiscard]]
+		vk::Format getFormat() const;
+		
+		[[nodiscard]]
+		vk::ColorSpaceKHR getColorSpace() const;
+		
+	};
+
+}
diff --git a/include/vkcv/Swapchain.hpp b/include/vkcv/Swapchain.hpp
index dc23bb9bf93c4c1733cb67944575b9fa669cb5c0..811da063c2fa3e58335769709aa806d86ad4ae97 100644
--- a/include/vkcv/Swapchain.hpp
+++ b/include/vkcv/Swapchain.hpp
@@ -9,59 +9,35 @@
 #include <vulkan/vulkan.hpp>
 
 #include "Context.hpp"
+#include "Surface.hpp"
 #include "Window.hpp"
 
 namespace vkcv
 {
 	
-	const uint32_t MIN_SWAPCHAIN_SIZE = 2;
-	
     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 context Current context
 		 * @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
 		 */
-        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
@@ -96,7 +72,7 @@ namespace vkcv
          * @return current surface
          */
         [[nodiscard]]
-        vk::SurfaceKHR getSurface() const;
+        const Surface& getSurface() const;
 
         /**
          * gets the chosen swapchain format
@@ -133,7 +109,7 @@ namespace vkcv
 		 * @return the familyQueueIndex for the surface
 		 */
 		[[nodiscard]]
-		const uint32_t& getPresentQueueIndex() const;
+		uint32_t getPresentQueueIndex() const;
 
 	};
     
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 158411a1b63e63f4bb363fae84c561864deeca8a..cd24d9e0991b1401aa2443166ba638c017c6a6f9 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -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;
 		}
 		
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 79289110307712a1d6a27ecd1b1eb7df71492522..2ca69e7d58991ee67d8e72261e1cddf65de60ed0 100644
--- a/src/vkcv/Swapchain.cpp
+++ b/src/vkcv/Swapchain.cpp
@@ -5,198 +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;
-    }
-
-    /**
-     * 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 double buffering, 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;
+        return m_Surface.getFormat();
     }
 
     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(),
-                surface.handle,
-                chosenImageCount,
-                chosenSurfaceFormat.format,
-                chosenSurfaceFormat.colorSpace,
-                chosenExtent,
-                1,
-                vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage,
-                vk::SharingMode::eExclusive,
-                0,
-                nullptr,
-                vk::SurfaceTransformFlagBitsKHR::eIdentity,
-                vk::CompositeAlphaFlagBitsKHR::eOpaque,
-                chosenPresentMode,
-                true,
-                nullptr
-        );
-
-        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 {
@@ -209,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() {
@@ -250,7 +73,7 @@ namespace vkcv
     }
     
     const vk::Extent2D& Swapchain::getExtent() const {
-    	return m_Extent;
+    	return m_Surface.getExtent();
     }
 
     Swapchain::~Swapchain() {
@@ -258,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;
 		}
 	}