Index: sdl-game.cpp
===================================================================
--- sdl-game.cpp	(revision 7865c5b0ff6fd16268522aa00c64569b2fd54092)
+++ sdl-game.cpp	(revision e469aed2b040a0363dcf04deeac96931497c6068)
@@ -60,5 +60,5 @@
                      , shouldRecreateSwapChain(false)
                      , frameCount(0)
-                     , currentFrame()
+                     , currentFrame(0)
                      , imageIndex(0)
                      , fpsStartTime(0.0f)
@@ -66,5 +66,5 @@
                      , done(false)
                      , currentRenderScreenFn(nullptr)
-                     , descriptorPool(VK_NULL_HANDLE)
+                     , imguiDescriptorPool(VK_NULL_HANDLE)
                      , gui(nullptr)
                      , window(nullptr)
@@ -77,11 +77,8 @@
 
 void VulkanGame::run(int width, int height, unsigned char guiFlags) {
-   // TODO: Maybe call the init code in the constructor instead of in run()
-   // Research this
    cout << "DEBUGGING IS " << (ENABLE_VALIDATION_LAYERS ? "ON" : "OFF") << endl;
 
    cout << "Vulkan Game" << endl;
 
-   // TODO: Move IMGUI initialization in here
    if (initUI(width, height, guiFlags) == RTWO_ERROR) {
       return;
@@ -90,87 +87,9 @@
    initVulkan();
 
-   // Create Descriptor Pool
-   {
-      VkDescriptorPoolSize pool_sizes[] =
-      {
-          { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
-          { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
-          { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
-          { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
-          { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
-          { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
-          { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
-          { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
-          { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
-          { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
-          { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
-      };
-      VkDescriptorPoolCreateInfo pool_info = {};
-      pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
-      pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
-      pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
-      pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
-      pool_info.pPoolSizes = pool_sizes;
-
-      VKUTIL_CHECK_RESULT(vkCreateDescriptorPool(device, &pool_info, nullptr, &descriptorPool),
-         "failed to create descriptor pool");
-   }
-
-   // TODO: Do this in one place and save it instead of redoing it every time I need a queue family index
-   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
-
-   // Setup Dear ImGui context
-   IMGUI_CHECKVERSION();
-   ImGui::CreateContext();
+   initImGuiOverlay();
+
+   currentRenderScreenFn = &VulkanGame::renderMainScreen;
+
    ImGuiIO& io = ImGui::GetIO();
-   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
-   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
-
-   // Setup Dear ImGui style
-   ImGui::StyleColorsDark();
-   //ImGui::StyleColorsClassic();
-
-   // Setup Platform/Renderer bindings
-   ImGui_ImplSDL2_InitForVulkan(window);
-   ImGui_ImplVulkan_InitInfo init_info = {};
-   init_info.Instance = instance;
-   init_info.PhysicalDevice = physicalDevice;
-   init_info.Device = device;
-   init_info.QueueFamily = indices.graphicsFamily.value();
-   init_info.Queue = graphicsQueue;
-   init_info.DescriptorPool = descriptorPool;
-   init_info.Allocator = nullptr;
-   init_info.MinImageCount = swapChainMinImageCount;
-   init_info.ImageCount = swapChainImageCount;
-   init_info.CheckVkResultFn = check_imgui_vk_result;
-   ImGui_ImplVulkan_Init(&init_info, renderPass);
-
-   // Load Fonts
-   // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
-   // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
-   // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
-   // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
-   // - Read 'docs/FONTS.md' for more instructions and details.
-   // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
-   //io.Fonts->AddFontDefault();
-   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
-   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
-   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
-   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
-   //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
-   //assert(font != NULL);
-
-   // Upload Fonts
-   {
-      VkCommandBuffer commandBuffer = VulkanUtils::beginSingleTimeCommands(device, resourceCommandPool);
-
-      ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
-
-      VulkanUtils::endSingleTimeCommands(device, resourceCommandPool, commandBuffer, graphicsQueue);
-
-      ImGui_ImplVulkan_DestroyFontUploadObjects();
-   }
-
-   currentRenderScreenFn = &VulkanGame::renderMainScreen;
 
    initGuiValueLists(valueLists);
@@ -221,4 +140,5 @@
       cout << "UI library could not be initialized!" << endl;
       cout << gui->getError() << endl;
+      // TODO: Rename RTWO_ERROR to something else
       return RTWO_ERROR;
    }
@@ -253,18 +173,12 @@
    createSwapChain();
    createImageViews();
+
+   createResourceCommandPool();
+   createImageResources();
+
    createRenderPass();
-
-   createResourceCommandPool();
    createCommandPools();
-
-   VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent,
-      depthImage, graphicsQueue);
-
    createFramebuffers();
-
-   // TODO: Initialize pipelines here
-
    createCommandBuffers();
-
    createSyncObjects();
 }
@@ -354,5 +268,5 @@
       }
 
-      // Start the Dear ImGui frame
+      // TODO: Move this into a renderImGuiOverlay() function
       ImGui_ImplVulkan_NewFrame();
       ImGui_ImplSDL2_NewFrame(window);
@@ -378,12 +292,7 @@
    VKUTIL_CHECK_RESULT(vkDeviceWaitIdle(device), "failed to wait for device!");
 
-   ImGui_ImplVulkan_Shutdown();
-   ImGui_ImplSDL2_Shutdown();
-   ImGui::DestroyContext();
+   cleanupImGuiOverlay();
 
    cleanupSwapChain();
-
-   // this would actually be destroyed in the pipeline class
-   vkDestroyDescriptorPool(device, descriptorPool, nullptr);
 
    vkDestroyCommandPool(device, resourceCommandPool, nullptr);
@@ -702,4 +611,31 @@
          VK_IMAGE_ASPECT_COLOR_BIT);
    }
+}
+
+void VulkanGame::createResourceCommandPool() {
+   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
+
+   VkCommandPoolCreateInfo poolInfo = {};
+   poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+   poolInfo.queueFamilyIndex = indices.graphicsFamily.value();
+   poolInfo.flags = 0;
+
+   if (vkCreateCommandPool(device, &poolInfo, nullptr, &resourceCommandPool) != VK_SUCCESS) {
+      throw runtime_error("failed to create resource command pool!");
+   }
+}
+
+void VulkanGame::createImageResources() {
+   VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent,
+      depthImage, graphicsQueue);
+}
+
+VkFormat VulkanGame::findDepthFormat() {
+   return VulkanUtils::findSupportedFormat(
+      physicalDevice,
+      { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
+      VK_IMAGE_TILING_OPTIMAL,
+      VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
+   );
 }
 
@@ -766,26 +702,4 @@
 }
 
-VkFormat VulkanGame::findDepthFormat() {
-   return VulkanUtils::findSupportedFormat(
-      physicalDevice,
-      { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
-      VK_IMAGE_TILING_OPTIMAL,
-      VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
-   );
-}
-
-void VulkanGame::createResourceCommandPool() {
-   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
-
-   VkCommandPoolCreateInfo poolInfo = {};
-   poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-   poolInfo.queueFamilyIndex = indices.graphicsFamily.value();
-   poolInfo.flags = 0;
-
-   if (vkCreateCommandPool(device, &poolInfo, nullptr, &resourceCommandPool) != VK_SUCCESS) {
-      throw runtime_error("failed to create resource command pool!");
-   }
-}
-
 void VulkanGame::createCommandPools() {
    commandPools.resize(swapChainImageCount);
@@ -859,16 +773,101 @@
 
    for (size_t i = 0; i < swapChainImageCount; i++) {
-      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAcquiredSemaphores[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create image acquired sempahore for a frame!");
-      }
-
-      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderCompleteSemaphores[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create render complete sempahore for a frame!");
-      }
-
-      if (vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create fence for a frame!");
-      }
-   }
+      VKUTIL_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAcquiredSemaphores[i]),
+         "failed to create image acquired sempahore for a frame!");
+
+      VKUTIL_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderCompleteSemaphores[i]),
+         "failed to create render complete sempahore for a frame!");
+
+      VKUTIL_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]),
+         "failed to create fence for a frame!");
+   }
+}
+
+void VulkanGame::initImGuiOverlay() {
+   vector<VkDescriptorPoolSize> pool_sizes {
+       { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
+       { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
+       { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
+       { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
+       { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
+       { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
+       { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
+       { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
+       { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
+       { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
+       { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
+   };
+
+   VkDescriptorPoolCreateInfo pool_info = {};
+   pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+   pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+   pool_info.maxSets = 1000 * pool_sizes.size();
+   pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size());
+   pool_info.pPoolSizes = pool_sizes.data();
+
+   VKUTIL_CHECK_RESULT(vkCreateDescriptorPool(device, &pool_info, nullptr, &imguiDescriptorPool),
+      "failed to create IMGUI descriptor pool!");
+
+   // TODO: Do this in one place and save it instead of redoing it every time I need a queue family index
+   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
+
+   // Setup Dear ImGui context
+   IMGUI_CHECKVERSION();
+   ImGui::CreateContext();
+   ImGuiIO& io = ImGui::GetIO();
+   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
+   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
+
+   // Setup Dear ImGui style
+   ImGui::StyleColorsDark();
+   //ImGui::StyleColorsClassic();
+
+   // Setup Platform/Renderer bindings
+   ImGui_ImplSDL2_InitForVulkan(window);
+   ImGui_ImplVulkan_InitInfo init_info = {};
+   init_info.Instance = instance;
+   init_info.PhysicalDevice = physicalDevice;
+   init_info.Device = device;
+   init_info.QueueFamily = indices.graphicsFamily.value();
+   init_info.Queue = graphicsQueue;
+   init_info.DescriptorPool = imguiDescriptorPool;
+   init_info.Allocator = nullptr;
+   init_info.MinImageCount = swapChainMinImageCount;
+   init_info.ImageCount = swapChainImageCount;
+   init_info.CheckVkResultFn = check_imgui_vk_result;
+   ImGui_ImplVulkan_Init(&init_info, renderPass);
+
+   // Load Fonts
+   // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+   // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+   // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+   // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+   // - Read 'docs/FONTS.md' for more instructions and details.
+   // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+   //io.Fonts->AddFontDefault();
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+   //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+   //assert(font != NULL);
+
+   // Upload Fonts
+
+   VkCommandBuffer commandBuffer = VulkanUtils::beginSingleTimeCommands(device, resourceCommandPool);
+
+   ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
+
+   VulkanUtils::endSingleTimeCommands(device, resourceCommandPool, commandBuffer, graphicsQueue);
+
+   ImGui_ImplVulkan_DestroyFontUploadObjects();
+}
+
+void VulkanGame::cleanupImGuiOverlay() {
+   ImGui_ImplVulkan_Shutdown();
+   ImGui_ImplSDL2_Shutdown();
+   ImGui::DestroyContext();
+
+   vkDestroyDescriptorPool(device, imguiDescriptorPool, nullptr);
 }
 
@@ -898,5 +897,5 @@
    VkCommandBufferBeginInfo beginInfo = {};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
-   beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+   beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 
    VKUTIL_CHECK_RESULT(vkBeginCommandBuffer(commandBuffers[imageIndex], &beginInfo),
@@ -907,8 +906,9 @@
    renderPassInfo.renderPass = renderPass;
    renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
+   renderPassInfo.renderArea.offset = { 0, 0 };
    renderPassInfo.renderArea.extent = swapChainExtent;
 
    array<VkClearValue, 2> clearValues = {};
-   clearValues[0].color = { { 0.45f, 0.55f, 0.60f, 1.00f } };
+   clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
    clearValues[1].depthStencil = { 1.0f, 0 };
 
@@ -978,7 +978,4 @@
    createSwapChain();
    createImageViews();
-   createRenderPass();
-
-   createCommandPools();
 
    // The depth buffer does need to be recreated with the swap chain since its dimensions depend on the window size
@@ -987,11 +984,11 @@
       depthImage, graphicsQueue);
 
+   createRenderPass();
+   createCommandPools();
    createFramebuffers();
+   createCommandBuffers();
+   createSyncObjects();
 
    // TODO: Update pipelines here
-
-   createCommandBuffers();
-
-   createSyncObjects();
 
    imageIndex = 0;
