diff --git a/src/main.cpp b/src/main.cpp
index e592d98..88b5efb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,6 +6,8 @@
 #include <vector>
 #include <array>
 #include <set>
+#include <limits>
+#include <algorithm>
 #include <memory>
 #include <optional>
 #include <stdexcept>
@@ -28,6 +30,9 @@ private:
     inline static const std::vector<const char*> validationLayers {
         "VK_LAYER_KHRONOS_validation"
     };
+    inline static const std::vector<const char*> deviceExtensions {
+        VK_KHR_SWAPCHAIN_EXTENSION_NAME
+    };
 
     #ifdef NDEBUG
         static constexpr bool enableValidationLayers = false;
@@ -47,6 +52,10 @@ private:
     vk::raii::Device m_device{ nullptr };
     vk::raii::Queue m_graphicsQueue{ nullptr };
     vk::raii::Queue m_presentQueue{ nullptr };
+    vk::raii::SwapchainKHR m_swapChain{ nullptr };
+    std::vector<vk::Image> m_swapChainImages;
+    vk::Format m_swapChainImageFormat;
+    vk::Extent2D m_swapChainExtent;
     /////////////////////////////////////////////////////////////////
 
     /////////////////////////////////////////////////////////////////
@@ -66,6 +75,7 @@ private:
         createSurface();
         pickPhysicalDevice();
         createLogicalDevice();
+        createSwapChain();
     }
 
     void mainLoop() {
@@ -188,10 +198,27 @@ private:
             return graphicsFamily.has_value() && presentFamily.has_value();
         }
     };
+    bool checkDeviceExtensionSupport(const vk::raii::PhysicalDevice& physicalDevice) {
+        // std::vector<vk::ExtensionProperties>
+        auto availableExtensions = physicalDevice.enumerateDeviceExtensionProperties();
+        std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
+        for (const auto& extension : availableExtensions) {
+            requiredExtensions.erase(extension.extensionName);
+        }
+        return requiredExtensions.empty();
+    }
     bool isDeviceSuitable(const vk::raii::PhysicalDevice& physicalDevice) {
         QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
 
-        return indices.isComplete();
+        bool extensionsSupported = checkDeviceExtensionSupport(physicalDevice);
+
+        bool swapChainAdequate = false;
+        if (extensionsSupported) {
+            SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
+            swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
+        }
+
+        return indices.isComplete() && extensionsSupported && swapChainAdequate;
     }
     void pickPhysicalDevice() {
         // std::vector<vk::raii::PhysicalDevice>
@@ -256,6 +283,8 @@ private:
         createInfo.setQueueCreateInfos( queueCreateInfos );
         createInfo.pEnabledFeatures = &deviceFeatures;
 
+        createInfo.setPEnabledExtensionNames( deviceExtensions );
+
         if (enableValidationLayers) {
             createInfo.setPEnabledLayerNames( validationLayers );
         }
@@ -277,6 +306,103 @@ private:
         m_surface = vk::raii::SurfaceKHR( m_instance, cSurface );
     }
     /////////////////////////////////////////////////////////////////
+
+    /////////////////////////////////////////////////////////////////
+    /// swapchain
+    struct SwapChainSupportDetails {
+        vk::SurfaceCapabilitiesKHR capabilities;
+        std::vector<vk::SurfaceFormatKHR>  formats;
+        std::vector<vk::PresentModeKHR> presentModes;
+    };
+    vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats) {
+        for (const auto& availableFormat : availableFormats) {
+            if (availableFormat.format == vk::Format::eB8G8R8A8Srgb && 
+                availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
+                return availableFormat;
+            }
+        }
+        return availableFormats.at(0);
+    }
+    vk::PresentModeKHR chooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& availablePresentModes) {
+        for (const auto& availablePresentMode : availablePresentModes) {
+            if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
+                return availablePresentMode;
+            }
+        }
+        return vk::PresentModeKHR::eFifo;
+    }
+    vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities) {
+        if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
+            return capabilities.currentExtent;
+        } else {
+            int width, height;
+            glfwGetFramebufferSize( m_window, &width, &height );
+
+            vk::Extent2D actualExtent (
+                static_cast<uint32_t>(width),
+                static_cast<uint32_t>(height)
+            );
+
+            actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
+            actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
+
+            return actualExtent;
+        }
+    }
+    SwapChainSupportDetails querySwapChainSupport(const vk::raii::PhysicalDevice& physicalDevice) {
+        SwapChainSupportDetails details;
+
+        details.capabilities = physicalDevice.getSurfaceCapabilitiesKHR( m_surface );
+        details.formats = physicalDevice.getSurfaceFormatsKHR( m_surface );
+        details.presentModes = physicalDevice.getSurfacePresentModesKHR( m_surface );
+
+        return details;
+    }
+    void createSwapChain() {
+        SwapChainSupportDetails swapChainSupport = querySwapChainSupport( m_physicalDevice );
+
+        vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat( swapChainSupport.formats );
+        vk::PresentModeKHR presentMode = chooseSwapPresentMode( swapChainSupport.presentModes );
+        vk::Extent2D extent = chooseSwapExtent( swapChainSupport.capabilities );
+
+        uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
+        if (swapChainSupport.capabilities.maxImageCount > 0 && 
+            imageCount > swapChainSupport.capabilities.maxImageCount) {
+            imageCount = swapChainSupport.capabilities.maxImageCount;
+        }
+
+        vk::SwapchainCreateInfoKHR createInfo;
+        createInfo.surface = m_surface;
+        createInfo.minImageCount = imageCount;
+        createInfo.imageFormat = surfaceFormat.format;
+        createInfo.imageColorSpace = surfaceFormat.colorSpace;
+        createInfo.imageExtent = extent;
+        createInfo.imageArrayLayers = 1;
+        createInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
+
+        QueueFamilyIndices indices = findQueueFamilies( m_physicalDevice );
+        std::vector<uint32_t> queueFamilyIndices { indices.graphicsFamily.value(), indices.presentFamily.value() };
+
+        if (indices.graphicsFamily != indices.presentFamily) {
+            createInfo.imageSharingMode = vk::SharingMode::eConcurrent;
+            createInfo.setQueueFamilyIndices( queueFamilyIndices );
+        } else {
+            createInfo.imageSharingMode = vk::SharingMode::eExclusive;
+        }
+
+        createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
+        createInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
+        createInfo.presentMode = presentMode;
+        createInfo.clipped = true;
+        createInfo.oldSwapchain = nullptr;
+
+        m_swapChain = m_device.createSwapchainKHR( createInfo );
+        m_swapChainImages = m_swapChain.getImages();
+        m_swapChainImageFormat = surfaceFormat.format;
+        m_swapChainExtent = extent;
+    }
+    /////////////////////////////////////////////////////////////////
+
 };
 
 int main() {
