Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision f00ee54ef3913ec9cd14069ea55103ceaf8220cc)
+++ vulkan-game.cpp	(revision 721e8be09e0b371d92e1759c73e15282b11ebcdb)
@@ -78,4 +78,12 @@
 };
 
+struct DescriptorInfo {
+   VkDescriptorType type;
+   VkShaderStageFlags stageFlags;
+
+   vector<VkDescriptorBufferInfo>* bufferDataList;
+   VkDescriptorImageInfo* imageData;
+};
+
 struct GraphicsPipelineInfo {
    VkPipelineLayout pipelineLayout;
@@ -84,4 +92,6 @@
    VkVertexInputBindingDescription bindingDescription;
    vector<VkVertexInputAttributeDescription> attributeDescriptions;
+
+   vector<DescriptorInfo> descriptorInfoList;
 
    VkDescriptorPool descriptorPool;
@@ -195,4 +205,9 @@
       vector<VkBuffer> uniformBuffers;
       vector<VkDeviceMemory> uniformBuffersMemory;
+
+      VkDescriptorImageInfo sceneImageInfo;
+      VkDescriptorImageInfo overlayImageInfo;
+
+      vector<VkDescriptorBufferInfo> uniformBufferInfoList;
 
       GraphicsPipelineInfo scenePipeline;
@@ -308,4 +323,14 @@
          createTextureSampler();
 
+         sceneImageInfo = {};
+         sceneImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+         sceneImageInfo.imageView = textureImageView;
+         sceneImageInfo.sampler = textureSampler;
+
+         overlayImageInfo = {};
+         overlayImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+         overlayImageInfo.imageView = sdlOverlayImageView;
+         overlayImageInfo.sampler = textureSampler;
+
          vector<Vertex> sceneVertices = {
             {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
@@ -332,5 +357,8 @@
          addAttributeDescription(scenePipeline, VK_FORMAT_R32G32_SFLOAT, offset_of(&Vertex::texCoord));
 
-         createSceneDescriptorSetLayout(scenePipeline);
+         addDescriptorInfo(scenePipeline, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList, nullptr);
+         addDescriptorInfo(scenePipeline, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr, &sceneImageInfo);
+
+         createDescriptorSetLayout(scenePipeline);
 
 
@@ -352,5 +380,7 @@
          addAttributeDescription(overlayPipeline, VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
 
-         createOverlayDescriptorSetLayout(overlayPipeline);
+         addDescriptorInfo(overlayPipeline, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr, &overlayImageInfo);
+
+         createDescriptorSetLayout(overlayPipeline);
 
          createBufferResources();
@@ -761,49 +791,4 @@
       }
 
-      void createSceneDescriptorSetLayout(GraphicsPipelineInfo& info) {
-         VkDescriptorSetLayoutBinding uboLayoutBinding = {};
-         uboLayoutBinding.binding = 0;
-         uboLayoutBinding.descriptorCount = 1;
-         uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-         uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
-         uboLayoutBinding.pImmutableSamplers = nullptr;
-
-         VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
-         samplerLayoutBinding.binding = 1;
-         samplerLayoutBinding.descriptorCount = 1;
-         samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-         samplerLayoutBinding.pImmutableSamplers = nullptr;
-         samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
-
-         array<VkDescriptorSetLayoutBinding, 2> bindings = { uboLayoutBinding, samplerLayoutBinding };
-         VkDescriptorSetLayoutCreateInfo layoutInfo = {};
-         layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
-         layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
-         layoutInfo.pBindings = bindings.data();
-
-         if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &info.descriptorSetLayout) != VK_SUCCESS) {
-            throw runtime_error("failed to create descriptor set layout!");
-         }
-      }
-
-      void createOverlayDescriptorSetLayout(GraphicsPipelineInfo& info) {
-         VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
-         samplerLayoutBinding.binding = 0;
-         samplerLayoutBinding.descriptorCount = 1;
-         samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-         samplerLayoutBinding.pImmutableSamplers = nullptr;
-         samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
-
-         array<VkDescriptorSetLayoutBinding, 1> bindings = { samplerLayoutBinding };
-         VkDescriptorSetLayoutCreateInfo layoutInfo = {};
-         layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
-         layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
-         layoutInfo.pBindings = bindings.data();
-
-         if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &info.descriptorSetLayout) != VK_SUCCESS) {
-            throw runtime_error("failed to create descriptor set layout!");
-         }
-      }
-
       void initGraphicsPipelineInfo(GraphicsPipelineInfo& info,
             const void* vertexData, int vertexSize, size_t numVertices,
@@ -833,4 +818,29 @@
 
          info.attributeDescriptions.push_back(attributeDesc);
+      }
+
+      void addDescriptorInfo(GraphicsPipelineInfo& info, VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData, VkDescriptorImageInfo* imageData) {
+         info.descriptorInfoList.push_back({ type, stageFlags, bufferData, imageData });
+      }
+
+      void createDescriptorSetLayout(GraphicsPipelineInfo& info) {
+         vector<VkDescriptorSetLayoutBinding> bindings(info.descriptorInfoList.size());
+
+         for (size_t i = 0; i < bindings.size(); i++) {
+            bindings[i].binding = i;
+            bindings[i].descriptorCount = 1;
+            bindings[i].descriptorType = info.descriptorInfoList[i].type;
+            bindings[i].stageFlags = info.descriptorInfoList[i].stageFlags;
+            bindings[i].pImmutableSamplers = nullptr;
+         }
+
+         VkDescriptorSetLayoutCreateInfo layoutInfo = {};
+         layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+         layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
+         layoutInfo.pBindings = bindings.data();
+
+         if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &info.descriptorSetLayout) != VK_SUCCESS) {
+            throw runtime_error("failed to create descriptor set layout!");
+         }
       }
 
@@ -1413,4 +1423,5 @@
          uniformBuffers.resize(swapChainImages.size());
          uniformBuffersMemory.resize(swapChainImages.size());
+         uniformBufferInfoList.resize(swapChainImages.size());
 
          for (size_t i = 0; i < swapChainImages.size(); i++) {
@@ -1418,4 +1429,8 @@
                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
                uniformBuffers[i], uniformBuffersMemory[i]);
+
+            uniformBufferInfoList[i].buffer = uniformBuffers[i];
+            uniformBufferInfoList[i].offset = 0;
+            uniformBufferInfoList[i].range = sizeof(UniformBufferObject);
          }
       }
@@ -1503,10 +1518,11 @@
       }
 
-      void createSceneDescriptorPool(GraphicsPipelineInfo& info) {
-         array<VkDescriptorPoolSize, 2> poolSizes = {};
-         poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-         poolSizes[0].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
-         poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-         poolSizes[1].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
+      void createDescriptorPool(GraphicsPipelineInfo& info) {
+         vector<VkDescriptorPoolSize> poolSizes(info.descriptorInfoList.size());
+
+         for (size_t i = 0; i < poolSizes.size(); i++) {
+            poolSizes[i].type = info.descriptorInfoList[i].type;
+            poolSizes[i].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
+         }
 
          VkDescriptorPoolCreateInfo poolInfo = {};
@@ -1521,5 +1537,5 @@
       }
 
-      void createSceneDescriptorSets(GraphicsPipelineInfo& info) {
+      void createDescriptorSets(GraphicsPipelineInfo& info) {
          vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), info.descriptorSetLayout);
 
@@ -1536,87 +1552,28 @@
 
          for (size_t i = 0; i < swapChainImages.size(); i++) {
-            VkDescriptorBufferInfo bufferInfo = {};
-            bufferInfo.buffer = uniformBuffers[i];
-            bufferInfo.offset = 0;
-            bufferInfo.range = sizeof(UniformBufferObject);
-
-            VkDescriptorImageInfo imageInfo = {};
-            imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-            imageInfo.imageView = textureImageView;
-            imageInfo.sampler = textureSampler;
-
-            array<VkWriteDescriptorSet, 2> descriptorWrites = {};
-
-            descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[0].dstSet = info.descriptorSets[i];
-            descriptorWrites[0].dstBinding = 0;
-            descriptorWrites[0].dstArrayElement = 0;
-            descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-            descriptorWrites[0].descriptorCount = 1;
-            descriptorWrites[0].pBufferInfo = &bufferInfo;
-            descriptorWrites[0].pImageInfo = nullptr;
-            descriptorWrites[0].pTexelBufferView = nullptr;
-
-            descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[1].dstSet = info.descriptorSets[i];
-            descriptorWrites[1].dstBinding = 1;
-            descriptorWrites[1].dstArrayElement = 0;
-            descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-            descriptorWrites[1].descriptorCount = 1;
-            descriptorWrites[1].pBufferInfo = nullptr;
-            descriptorWrites[1].pImageInfo = &imageInfo;
-            descriptorWrites[1].pTexelBufferView = nullptr;
-
-            vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
-         }
-      }
-
-      void createOverlayDescriptorPool(GraphicsPipelineInfo& info) {
-         array<VkDescriptorPoolSize, 1> poolSizes = {};
-         poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-         poolSizes[0].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
-
-         VkDescriptorPoolCreateInfo poolInfo = {};
-         poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
-         poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
-         poolInfo.pPoolSizes = poolSizes.data();
-         poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
-
-         if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &info.descriptorPool) != VK_SUCCESS) {
-            throw runtime_error("failed to create descriptor pool!");
-         }
-      }
-
-      void createOverlayDescriptorSets(GraphicsPipelineInfo& info) {
-         vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), info.descriptorSetLayout);
-
-         VkDescriptorSetAllocateInfo allocInfo = {};
-         allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-         allocInfo.descriptorPool = info.descriptorPool;
-         allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
-         allocInfo.pSetLayouts = layouts.data();
-
-         info.descriptorSets.resize(swapChainImages.size());
-         if (vkAllocateDescriptorSets(device, &allocInfo, info.descriptorSets.data()) != VK_SUCCESS) {
-            throw runtime_error("failed to allocate descriptor sets!");
-         }
-
-         for (size_t i = 0; i < swapChainImages.size(); i++) {
-            VkDescriptorImageInfo imageInfo = {};
-            imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-            imageInfo.imageView = sdlOverlayImageView;
-            imageInfo.sampler = textureSampler;
-
-            array<VkWriteDescriptorSet, 1> descriptorWrites = {};
-
-            descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptorWrites[0].dstSet = info.descriptorSets[i];
-            descriptorWrites[0].dstBinding = 0;
-            descriptorWrites[0].dstArrayElement = 0;
-            descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-            descriptorWrites[0].descriptorCount = 1;
-            descriptorWrites[0].pBufferInfo = nullptr;
-            descriptorWrites[0].pImageInfo = &imageInfo;
-            descriptorWrites[0].pTexelBufferView = nullptr;
+            vector<VkWriteDescriptorSet> descriptorWrites(info.descriptorInfoList.size());
+
+            for (size_t j = 0; j < descriptorWrites.size(); j++) {
+               descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+               descriptorWrites[j].dstSet = info.descriptorSets[i];
+               descriptorWrites[j].dstBinding = j;
+               descriptorWrites[j].dstArrayElement = 0;
+               descriptorWrites[j].descriptorType = info.descriptorInfoList[j].type;
+               descriptorWrites[j].descriptorCount = 1;
+               descriptorWrites[j].pBufferInfo = nullptr;
+               descriptorWrites[j].pImageInfo = nullptr;
+               descriptorWrites[j].pTexelBufferView = nullptr;
+
+               switch (descriptorWrites[j].descriptorType) {
+                  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                     descriptorWrites[j].pBufferInfo = &(*info.descriptorInfoList[j].bufferDataList)[i];
+                     break;
+                  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                     descriptorWrites[j].pImageInfo = info.descriptorInfoList[j].imageData;
+                     break;
+                  default:
+                     cout << "Unknown descriptor type: " << descriptorWrites[j].descriptorType << endl;
+               }
+            }
 
             vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
@@ -1880,10 +1837,10 @@
 
          createGraphicsPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv", scenePipeline);
-         createSceneDescriptorPool(scenePipeline);
-         createSceneDescriptorSets(scenePipeline);
+         createDescriptorPool(scenePipeline);
+         createDescriptorSets(scenePipeline);
 
          createGraphicsPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv", overlayPipeline);
-         createOverlayDescriptorPool(overlayPipeline);
-         createOverlayDescriptorSets(overlayPipeline);
+         createDescriptorPool(overlayPipeline);
+         createDescriptorSets(overlayPipeline);
 
          createCommandBuffers();
