Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision b8b32bd447f32afb9589680b778624e62dee25df)
+++ vulkan-game.cpp	(revision 28c13dafd9634445841ee3e30280ec2cab479545)
@@ -112,5 +112,10 @@
 
 struct GraphicsPipelineInfo {
+   VkPipelineLayout pipelineLayout;
    VkPipeline pipeline;
+
+   VkDescriptorPool descriptorPool;
+   VkDescriptorSetLayout descriptorSetLayout;
+   vector<VkDescriptorSet> descriptorSets;
 
    VkBuffer vertexBuffer;
@@ -187,9 +192,4 @@
 
       VkRenderPass renderPass;
-      VkDescriptorSetLayout descriptorSetLayout;
-      VkPipelineLayout pipelineLayout;
-      VkDescriptorPool descriptorPool;
-      vector<VkDescriptorSet> descriptorSets;
-
       VkCommandPool commandPool;
 
@@ -313,7 +313,11 @@
          createImageViews();
          createRenderPass();
-         createDescriptorSetLayout();
-         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", &scenePipeline.pipeline);
-         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", &overlayPipeline.pipeline);
+
+         createDescriptorSetLayout(scenePipeline);
+         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", scenePipeline);
+
+         createDescriptorSetLayout(overlayPipeline);
+         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", overlayPipeline);
+
          createCommandPool();
          createDepthResources();
@@ -358,6 +362,11 @@
 
          createUniformBuffers();
-         createDescriptorPool();
-         createDescriptorSets();
+
+         createDescriptorPool(scenePipeline);
+         createDescriptorSets(scenePipeline);
+
+         createDescriptorPool(overlayPipeline);
+         createDescriptorSets(overlayPipeline);
+
          createCommandBuffers();
          createSyncObjects();
@@ -766,5 +775,5 @@
       }
 
-      void createDescriptorSetLayout() {
+      void createDescriptorSetLayout(GraphicsPipelineInfo& info) {
          VkDescriptorSetLayoutBinding uboLayoutBinding = {};
          uboLayoutBinding.binding = 0;
@@ -794,10 +803,10 @@
          layoutInfo.pBindings = bindings.data();
 
-         if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
+         if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &info.descriptorSetLayout) != VK_SUCCESS) {
             throw runtime_error("failed to create descriptor set layout!");
          }
       }
 
-      void createGraphicsPipeline(string vertShaderFile, string fragShaderFile, VkPipeline* pipeline) {
+      void createGraphicsPipeline(string vertShaderFile, string fragShaderFile, GraphicsPipelineInfo& info) {
          auto vertShaderCode = readFile(vertShaderFile);
          auto fragShaderCode = readFile(fragShaderFile);
@@ -906,8 +915,8 @@
          pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
          pipelineLayoutInfo.setLayoutCount = 1;
-         pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
+         pipelineLayoutInfo.pSetLayouts = &info.descriptorSetLayout;
          pipelineLayoutInfo.pushConstantRangeCount = 0;
 
-         if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
+         if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &info.pipelineLayout) != VK_SUCCESS) {
             throw runtime_error("failed to create pipeline layout!");
          }
@@ -925,5 +934,5 @@
          pipelineInfo.pColorBlendState = &colorBlending;
          pipelineInfo.pDynamicState = nullptr;
-         pipelineInfo.layout = pipelineLayout;
+         pipelineInfo.layout = info.pipelineLayout;
          pipelineInfo.renderPass = renderPass;
          pipelineInfo.subpass = 0;
@@ -931,5 +940,5 @@
          pipelineInfo.basePipelineIndex = -1;
 
-         if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, pipeline) != VK_SUCCESS) {
+         if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &info.pipeline) != VK_SUCCESS) {
             throw runtime_error("failed to create graphics pipeline!");
          }
@@ -1487,5 +1496,5 @@
       }
 
-      void createDescriptorPool() {
+      void createDescriptorPool(GraphicsPipelineInfo& info) {
          array<VkDescriptorPoolSize, 3> poolSizes = {};
          poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -1502,20 +1511,20 @@
          poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
 
-         if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
+         if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &info.descriptorPool) != VK_SUCCESS) {
             throw runtime_error("failed to create descriptor pool!");
          }
       }
 
-      void createDescriptorSets() {
-         vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout);
+      void createDescriptorSets(GraphicsPipelineInfo& info) {
+         vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), info.descriptorSetLayout);
 
          VkDescriptorSetAllocateInfo allocInfo = {};
          allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-         allocInfo.descriptorPool = descriptorPool;
+         allocInfo.descriptorPool = info.descriptorPool;
          allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
          allocInfo.pSetLayouts = layouts.data();
 
-         descriptorSets.resize(swapChainImages.size());
-         if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
+         info.descriptorSets.resize(swapChainImages.size());
+         if (vkAllocateDescriptorSets(device, &allocInfo, info.descriptorSets.data()) != VK_SUCCESS) {
             throw runtime_error("failed to allocate descriptor sets!");
          }
@@ -1540,5 +1549,5 @@
 
             descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[0].dstSet = descriptorSets[i];
+            descriptorWrites[0].dstSet = info.descriptorSets[i];
             descriptorWrites[0].dstBinding = 0;
             descriptorWrites[0].dstArrayElement = 0;
@@ -1550,5 +1559,5 @@
 
             descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[1].dstSet = descriptorSets[i];
+            descriptorWrites[1].dstSet = info.descriptorSets[i];
             descriptorWrites[1].dstBinding = 1;
             descriptorWrites[1].dstArrayElement = 0;
@@ -1560,5 +1569,5 @@
 
             descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[2].dstSet = descriptorSets[i];
+            descriptorWrites[2].dstSet = info.descriptorSets[i];
             descriptorWrites[2].dstBinding = 2;
             descriptorWrites[2].dstArrayElement = 0;
@@ -1612,24 +1621,6 @@
             vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 
-            vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, scenePipeline.pipeline);
-
-            vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);
-
-            VkBuffer vertexBuffers[] = { scenePipeline.vertexBuffer };
-            VkDeviceSize offsets[] = { 0 };
-            vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
-
-            vkCmdBindIndexBuffer(commandBuffers[i], scenePipeline.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
-
-            vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(scenePipeline.numIndices), 1, 0, 0, 0);
-
-            vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, overlayPipeline.pipeline);
-
-            VkBuffer vertexBuffersOverlay[] = { overlayPipeline.vertexBuffer };
-            vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffersOverlay, offsets);
-
-            vkCmdBindIndexBuffer(commandBuffers[i], overlayPipeline.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
-
-            vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(overlayPipeline.numIndices), 1, 0, 0, 0);
+            createGraphicsPipelineCommands(scenePipeline, i);
+            createGraphicsPipelineCommands(overlayPipeline, i);
 
             vkCmdEndRenderPass(commandBuffers[i]);
@@ -1639,4 +1630,18 @@
             }
          }
+      }
+
+      void createGraphicsPipelineCommands(GraphicsPipelineInfo& info, size_t imageIdx) {
+         vkCmdBindPipeline(commandBuffers[imageIdx], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
+         vkCmdBindDescriptorSets(commandBuffers[imageIdx], VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipelineLayout, 0, 1,
+            &info.descriptorSets[imageIdx], 0, nullptr);
+
+         VkBuffer vertexBuffers[] = { info.vertexBuffer };
+         VkDeviceSize offsets[] = { 0 };
+         vkCmdBindVertexBuffers(commandBuffers[imageIdx], 0, 1, vertexBuffers, offsets);
+
+         vkCmdBindIndexBuffer(commandBuffers[imageIdx], info.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
+
+         vkCmdDrawIndexed(commandBuffers[imageIdx], static_cast<uint32_t>(info.numIndices), 1, 0, 0, 0);
       }
 
@@ -1824,11 +1829,18 @@
          createImageViews();
          createRenderPass();
-         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", &scenePipeline.pipeline);
-         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", &overlayPipeline.pipeline);
+
+         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", scenePipeline);
+         createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", overlayPipeline);
+
          createDepthResources();
          createFramebuffers();
          createUniformBuffers();
-         createDescriptorPool();
-         createDescriptorSets();
+
+         createDescriptorPool(scenePipeline);
+         createDescriptorSets(scenePipeline);
+
+         createDescriptorPool(overlayPipeline);
+         createDescriptorSets(overlayPipeline);
+
          createCommandBuffers();
       }
@@ -1851,15 +1863,6 @@
          vkFreeMemory(device, sdlOverlayImageMemory, nullptr);
 
-         vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
-
-         vkDestroyBuffer(device, scenePipeline.vertexBuffer, nullptr);
-         vkFreeMemory(device, scenePipeline.vertexBufferMemory, nullptr);
-         vkDestroyBuffer(device, scenePipeline.indexBuffer, nullptr);
-         vkFreeMemory(device, scenePipeline.indexBufferMemory, nullptr);
-
-         vkDestroyBuffer(device, overlayPipeline.vertexBuffer, nullptr);
-         vkFreeMemory(device, overlayPipeline.vertexBufferMemory, nullptr);
-         vkDestroyBuffer(device, overlayPipeline.indexBuffer, nullptr);
-         vkFreeMemory(device, overlayPipeline.indexBufferMemory, nullptr);
+         cleanupPipelineBuffers(scenePipeline);
+         cleanupPipelineBuffers(overlayPipeline);
 
          for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
@@ -1920,8 +1923,7 @@
          vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
 
-         vkDestroyPipeline(device, scenePipeline.pipeline, nullptr);
-         vkDestroyPipeline(device, overlayPipeline.pipeline, nullptr);
-
-         vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
+         cleanupPipeline(scenePipeline);
+         cleanupPipeline(overlayPipeline);
+
          vkDestroyRenderPass(device, renderPass, nullptr);
 
@@ -1936,6 +1938,19 @@
             vkFreeMemory(device, uniformBuffersMemory[i], nullptr);
          }
-
-         vkDestroyDescriptorPool(device, descriptorPool, nullptr);
+      }
+
+      void cleanupPipeline(GraphicsPipelineInfo& pipeline) {
+         vkDestroyPipeline(device, pipeline.pipeline, nullptr);
+         vkDestroyDescriptorPool(device, pipeline.descriptorPool, nullptr);
+         vkDestroyPipelineLayout(device, pipeline.pipelineLayout, nullptr);
+      }
+
+      void cleanupPipelineBuffers(GraphicsPipelineInfo& pipeline) {
+         vkDestroyDescriptorSetLayout(device, pipeline.descriptorSetLayout, nullptr);
+
+         vkDestroyBuffer(device, pipeline.vertexBuffer, nullptr);
+         vkFreeMemory(device, pipeline.vertexBufferMemory, nullptr);
+         vkDestroyBuffer(device, pipeline.indexBuffer, nullptr);
+         vkFreeMemory(device, pipeline.indexBufferMemory, nullptr);
       }
 
