Index: graphics-pipeline_vulkan.cpp
===================================================================
--- graphics-pipeline_vulkan.cpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ graphics-pipeline_vulkan.cpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -326,14 +326,11 @@
       &descriptorSets[currentImage], 0, nullptr);
 
-   // TODO: Implement once I add vertex and index buffers to the pipeline
-   /*
-   VkBuffer vertexBuffers[] = { info.vertexBuffer };
+   VkBuffer vertexBuffers[] = { vertexBuffer };
    VkDeviceSize offsets[] = { 0 };
-   vkCmdBindVertexBuffers(commandBuffers[currentImage], 0, 1, vertexBuffers, offsets);
-
-   vkCmdBindIndexBuffer(commandBuffers[currentImage], info.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
-
-   vkCmdDrawIndexed(commandBuffers[currentImage], static_cast<uint32_t>(info.numIndices), 1, 0, 0, 0);
-   */
+   vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
+
+   vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
+
+   vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(numIndices), 1, 0, 0, 0);
 }
 
Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ vulkan-game.cpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -215,6 +215,4 @@
    UIEvent e;
    bool quit = false;
-
-   SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
 
    while (!quit) {
@@ -266,6 +264,20 @@
 
 void VulkanGame::renderUI() {
+   // TODO: Since I currently don't use any other render targets,
+   // I may as well set this once before the render loop
+   SDL_SetRenderTarget(renderer, uiOverlay);
+
+   SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
    SDL_RenderClear(renderer);
-   SDL_RenderPresent(renderer);
+
+   SDL_Rect rect = {280, 220, 100, 100};
+   SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
+   SDL_RenderFillRect(renderer, &rect);
+
+   SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xFF, 0xFF);
+   SDL_RenderDrawLine(renderer, 50, 5, 150, 500);
+
+   VulkanUtils::populateVulkanImageFromSDLTexture(device, physicalDevice, commandPool, uiOverlay, renderer,
+      sdlOverlayImage, graphicsQueue);
 }
 
@@ -274,4 +286,57 @@
 
    uint32_t imageIndex;
+
+   VkResult result = vkAcquireNextImageKHR(device, swapChain, numeric_limits<uint64_t>::max(),
+      imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
+
+   if (result == VK_ERROR_OUT_OF_DATE_KHR) {
+      recreateSwapChain();
+      return;
+   } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
+      throw runtime_error("failed to acquire swap chain image!");
+   }
+
+   VkSubmitInfo submitInfo = {};
+   submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+
+   VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
+   VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
+
+   submitInfo.waitSemaphoreCount = 1;
+   submitInfo.pWaitSemaphores = waitSemaphores;
+   submitInfo.pWaitDstStageMask = waitStages;
+   submitInfo.commandBufferCount = 1;
+   submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
+
+   VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
+
+   submitInfo.signalSemaphoreCount = 1;
+   submitInfo.pSignalSemaphores = signalSemaphores;
+
+   vkResetFences(device, 1, &inFlightFences[currentFrame]);
+
+   if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
+      throw runtime_error("failed to submit draw command buffer!");
+   }
+
+   VkPresentInfoKHR presentInfo = {};
+   presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+   presentInfo.waitSemaphoreCount = 1;
+   presentInfo.pWaitSemaphores = signalSemaphores;
+
+   VkSwapchainKHR swapChains[] = { swapChain };
+   presentInfo.swapchainCount = 1;
+   presentInfo.pSwapchains = swapChains;
+   presentInfo.pImageIndices = &imageIndex;
+   presentInfo.pResults = nullptr;
+
+   result = vkQueuePresentKHR(presentQueue, &presentInfo);
+
+   if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
+      framebufferResized = false;
+      recreateSwapChain();
+   } else if (result != VK_SUCCESS) {
+      throw runtime_error("failed to present swap chain image!");
+   }
 
    currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
@@ -774,6 +839,4 @@
       vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 
-      // reateGraphicsPipelineCommands(scenePipeline, i);
-      // createGraphicsPipelineCommands(overlayPipeline, i);
       for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
          pipeline.createRenderCommands(commandBuffers[i], i);
@@ -809,4 +872,19 @@
 }
 
+void VulkanGame::recreateSwapChain() {
+   cout << "Recreating swap chain" << endl;
+   gui->refreshWindowSize();
+
+   while (gui->getWindowWidth() == 0 || gui->getWindowHeight() == 0 ||
+      (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0) {
+      SDL_WaitEvent(nullptr);
+      gui->refreshWindowSize();
+   }
+
+   vkDeviceWaitIdle(device);
+
+   //cleanupSwapChain();
+}
+
 void VulkanGame::cleanupSwapChain() {
    VulkanUtils::destroyVulkanImage(device, depthImage);
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ vulkan-game.hpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -124,4 +124,6 @@
       void createSyncObjects();
 
+      void recreateSwapChain();
+
       void cleanupSwapChain();
 
Index: vulkan-ref.cpp
===================================================================
--- vulkan-ref.cpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ vulkan-ref.cpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -823,5 +823,4 @@
       }
 
-/*** START OF REFACTORED CODE ***/
       void addDescriptorInfo(GraphicsPipelineInfo& info, VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData, VkDescriptorImageInfo* imageData) {
          info.descriptorInfoList.push_back({ type, stageFlags, bufferData, imageData });
@@ -1160,5 +1159,4 @@
          view = createImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
       }
-/*** END OF REFACTORED CODE ***/
 
       void populateImageFromSDLTexture(SDL_Texture* texture, VkImage& image) {
@@ -1205,5 +1203,4 @@
       }
 
-/*** START OF REFACTORED CODE ***/
       void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage,
             VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
@@ -1653,8 +1650,6 @@
             vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 
-/*** END OF REFACTORED CODE ***/
             createGraphicsPipelineCommands(scenePipeline, i);
             createGraphicsPipelineCommands(overlayPipeline, i);
-/*** START OF REFACTORED CODE ***/
 
             vkCmdEndRenderPass(commandBuffers[i]);
@@ -1670,5 +1665,4 @@
          vkCmdBindDescriptorSets(commandBuffers[currentImage], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipelineLayout, 0, 1,
             &info.descriptorSets[currentImage], 0, nullptr);
-/*** END OF REFACTORED CODE ***/
 
          VkBuffer vertexBuffers[] = { info.vertexBuffer };
@@ -1679,5 +1673,4 @@
 
          vkCmdDrawIndexed(commandBuffers[currentImage], static_cast<uint32_t>(info.numIndices), 1, 0, 0, 0);
-/*** START OF REFACTORED CODE ***/
       }
 
@@ -1791,5 +1784,4 @@
 
          uint32_t imageIndex;
-/*** END OF REFACTORED CODE ***/
 
          VkResult result = vkAcquireNextImageKHR(device, swapChain, numeric_limits<uint64_t>::max(),
@@ -1802,7 +1794,9 @@
             throw runtime_error("failed to acquire swap chain image!");
          }
+/*** END OF REFACTORED CODE ***/
 
          updateUniformBuffer(imageIndex);
 
+/*** START OF REFACTORED CODE ***/
          VkSubmitInfo submitInfo = {};
          submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@@ -1848,5 +1842,4 @@
          }
 
-/*** START OF REFACTORED CODE ***/
          currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
          currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
@@ -1854,5 +1847,4 @@
 
       void drawUI() {
-/*** END OF REFACTORED CODE ***/
          // TODO: Since I currently don't use any other render targets,
          // I may as well set this once before the render loop
@@ -1861,4 +1853,5 @@
          SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0x00);
          SDL_RenderClear(gRenderer);
+/*** END OF REFACTORED CODE ***/
 
          SDL_Rect rect;
@@ -1877,9 +1870,9 @@
          SDL_RenderCopy(gRenderer, uiImage, nullptr, &rect);
 
+/*** START OF REFACTORED CODE ***/
          SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0xFF, 0xFF);
          SDL_RenderDrawLine(gRenderer, 50, 5, 150, 500);
 
          populateImageFromSDLTexture(uiOverlay, sdlOverlayImage);
-/*** START OF REFACTORED CODE ***/
       }
 /*** END OF REFACTORED CODE ***/
@@ -1903,4 +1896,5 @@
       }
 
+/*** START OF REFACTORED CODE ***/
       void recreateSwapChain() {
          gui->refreshWindowSize();
@@ -1913,4 +1907,5 @@
 
          vkDeviceWaitIdle(device);
+/*** END OF REFACTORED CODE ***/
 
          cleanupSwapChain();
@@ -1921,7 +1916,7 @@
 
          createBufferResources();
-      }
-
 /*** START OF REFACTORED CODE ***/
+      }
+
       void createBufferResources() {
          createDepthResources();
@@ -2045,5 +2040,4 @@
          vkFreeMemory(device, pipeline.indexBufferMemory, nullptr);
       }
-/*** END OF REFACTORED CODE ***/
 
       static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
@@ -2076,5 +2070,4 @@
 };
 
-/*** START OF REFACTORED CODE ***/
 int main(int argc, char* argv[]) {
 
Index: vulkan-utils.cpp
===================================================================
--- vulkan-utils.cpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ vulkan-utils.cpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -269,5 +269,6 @@
    VkDeviceMemory stagingBufferMemory;
 
-   createBuffer(device, physicalDevice, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+   createBuffer(device, physicalDevice, imageSize,
+      VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
       stagingBuffer, stagingBufferMemory);
@@ -308,4 +309,52 @@
 
    image.imageView = createImageView(device, image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
+}
+
+void VulkanUtils::populateVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice,
+      VkCommandPool commandPool, SDL_Texture* texture, SDL_Renderer* renderer, VulkanImage& image,
+      VkQueue graphicsQueue) {
+   int a, w, h;
+
+   SDL_QueryTexture(texture, nullptr, &a, &w, &h);
+
+   VkDeviceSize imageSize = w * h * 4;
+   unsigned char* pixels = new unsigned char[imageSize];
+
+   SDL_RenderReadPixels(renderer, nullptr, SDL_PIXELFORMAT_ABGR8888, pixels, w * 4);
+
+   VkBuffer stagingBuffer;
+   VkDeviceMemory stagingBufferMemory;
+
+   createBuffer(device, physicalDevice, imageSize,
+      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+      stagingBuffer, stagingBufferMemory);
+
+   void* data;
+
+   vkMapMemory(device, stagingBufferMemory, 0, VK_WHOLE_SIZE, 0, &data);
+   memcpy(data, pixels, static_cast<size_t>(imageSize));
+
+   VkMappedMemoryRange mappedMemoryRange = {};
+   mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+   mappedMemoryRange.memory = stagingBufferMemory;
+   mappedMemoryRange.offset = 0;
+   mappedMemoryRange.size = VK_WHOLE_SIZE;
+
+   // TODO: Should probably check that the function succeeded
+   vkFlushMappedMemoryRanges(device, 1, &mappedMemoryRange);
+   vkUnmapMemory(device, stagingBufferMemory);
+
+   delete[] pixels;
+
+   transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM,
+      VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, graphicsQueue);
+   copyBufferToImage(device, commandPool, stagingBuffer, image.image,
+      static_cast<uint32_t>(w), static_cast<uint32_t>(h), graphicsQueue);
+   transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM,
+      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, graphicsQueue);
+
+   vkDestroyBuffer(device, stagingBuffer, nullptr);
+   vkFreeMemory(device, stagingBufferMemory, nullptr);
 }
 
Index: vulkan-utils.hpp
===================================================================
--- vulkan-utils.hpp	(revision 87c8f1abdf1a94f87d0f0051fbc134d1ec1fa9ee)
+++ vulkan-utils.hpp	(revision d2d9286a6d366401699becfa31a552c8c937ef7b)
@@ -70,4 +70,7 @@
       static void createVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice,
             SDL_Texture* texture, VulkanImage& image);
+      static void populateVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice,
+            VkCommandPool commandPool, SDL_Texture* texture, SDL_Renderer* renderer, VulkanImage& image,
+            VkQueue graphicsQueue);
       static void createDepthImage(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool,
             VkFormat depthFormat, VkExtent2D extent, VulkanImage& image, VkQueue graphicsQueue);
