diff --git a/src/main.cpp b/src/main.cpp
index fa38a92..3f75304 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -77,6 +77,9 @@ private:
     vk::raii::Pipeline m_graphicsPipeline{ nullptr };
     vk::raii::CommandPool m_commandPool{ nullptr };
     std::vector<vk::raii::CommandBuffer> m_commandBuffers;
+    vk::raii::Semaphore m_imageAvailableSemaphore{ nullptr };
+    vk::raii::Semaphore m_renderFinishedSemaphore{ nullptr };
+    vk::raii::Fence m_inFlightFence{ nullptr };
     /////////////////////////////////////////////////////////////
 
     /////////////////////////////////////////////////////////////
@@ -103,12 +106,15 @@ private:
         createGraphicsPipeline();
         createCommandPool();
         createCommandBuffer();
+        createSyncObjects();
     }
 
     void mainLoop() {
         while (!glfwWindowShouldClose( m_window )) {
             glfwPollEvents();
+            drawFrame();
         }
+        m_device.waitIdle();
     }
 
     void cleanup() {
@@ -412,9 +418,18 @@ private:
         subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
         subpass.setColorAttachments( colorAttachmentRef );
 
+        vk::SubpassDependency dependency;
+        dependency.srcSubpass = vk::SubpassExternal;
+        dependency.dstSubpass = 0;
+        dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
+        dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
+        dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
+        dependency.srcAccessMask = {};
+
         vk::RenderPassCreateInfo renderPassInfo;
         renderPassInfo.setAttachments( colorAttachment );
         renderPassInfo.setSubpasses( subpass );
+        renderPassInfo.setDependencies( dependency );
 
         m_renderPass = m_device.createRenderPass(renderPassInfo);
     }
@@ -578,6 +593,49 @@ private:
         commandBuffer.end();
     }
     /////////////////////////////////////////////////////////////
+
+    /////////////////////////////////////////////////////////////
+    /// draw frame
+    void createSyncObjects() {
+        constexpr vk::SemaphoreCreateInfo semaphoreInfo;
+        constexpr vk::FenceCreateInfo fenceInfo(
+            vk::FenceCreateFlagBits::eSignaled  // flags
+        );
+        m_imageAvailableSemaphore = m_device.createSemaphore( semaphoreInfo );
+        m_renderFinishedSemaphore = m_device.createSemaphore( semaphoreInfo );
+        m_inFlightFence = m_device.createFence( fenceInfo );
+    }
+    void drawFrame() {
+        if(const auto res = m_device.waitForFences( *m_inFlightFence, true, std::numeric_limits<uint64_t>::max() );
+            res != vk::Result::eSuccess
+        ) throw std::runtime_error{ "waitForFences in drawFrame was failed" };
+
+        m_device.resetFences( *m_inFlightFence );
+
+        auto [nxtRes, imageIndex] = m_swapChain.acquireNextImage(std::numeric_limits<uint64_t>::max(), m_imageAvailableSemaphore);
+
+        m_commandBuffers[0].reset();
+        recordCommandBuffer(m_commandBuffers[0], imageIndex);
+
+        vk::SubmitInfo submitInfo;
+        submitInfo.setWaitSemaphores( *m_imageAvailableSemaphore );
+        std::array<vk::PipelineStageFlags,1> waitStages = { vk::PipelineStageFlagBits::eColorAttachmentOutput };
+        submitInfo.setWaitDstStageMask( waitStages );
+        submitInfo.setCommandBuffers( *m_commandBuffers[0] );
+
+        submitInfo.setSignalSemaphores( *m_renderFinishedSemaphore );
+        m_graphicsQueue.submit(submitInfo, m_inFlightFence);
+
+        vk::PresentInfoKHR presentInfo;
+        presentInfo.setWaitSemaphores( *m_renderFinishedSemaphore );
+        presentInfo.setSwapchains( *m_swapChain );
+        presentInfo.pImageIndices = &imageIndex;
+        if (const auto res = m_presentQueue.presentKHR( presentInfo );
+            res != vk::Result::eSuccess
+        ) throw std::runtime_error{ "presentKHR in drawFrame was failed" };
+
+    }
+    /////////////////////////////////////////////////////////////
 };
 
 int main() {
