Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision e1308e874d193cdc00723f7df1f19245df234d38)
+++ vulkan-game.cpp	(revision 055750aa780089e54a6a30e8455284e2e1f4883c)
@@ -26,6 +26,6 @@
    framebufferResized = false;
 
-   modelMvpMats = {};
-   shipMvpMats = {};
+   object_VP_mats = {};
+   ship_VP_mats = {};
 }
 
@@ -196,8 +196,14 @@
    modelPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&ModelVertex::texCoord));
 
-   createUniformBuffers<UBO_MvpMat>(uniformBuffers, uniformBuffersMemory, uniformBufferInfoList);
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_scenePipeline, uniformBuffersMemory_scenePipeline, uniformBufferInfoList_scenePipeline);
+   createBufferSet(10 * sizeof(SBO_SceneObject), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_scenePipeline, storageBuffersMemory_scenePipeline, storageBufferInfoList_scenePipeline);
 
    modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList);
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_scenePipeline);
+   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &storageBufferInfoList_scenePipeline);
+
    modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
       VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
@@ -250,8 +256,13 @@
    shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::normal));
 
-   createUniformBuffers<UBO_MvpMat>(uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
+   createBufferSet(10 * sizeof(SBO_SceneObject), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_shipPipeline, storageBuffersMemory_shipPipeline, storageBufferInfoList_shipPipeline);
 
    shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
       VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_shipPipeline);
+   shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &storageBufferInfoList_shipPipeline);
 
    // TODO: With the normals, indexing basically becomes pointless since no vertices will have exactly
@@ -525,14 +536,9 @@
    proj[1][1] *= -1; // flip the y-axis so that +y is up
 
-   modelMvpMats.model = mat4(1.0f);
-   modelMvpMats.view = view;
-   modelMvpMats.proj = proj;
-
-   mat4 T_model = translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f));
-   mat4 R_model(1.0f);
-
-   shipMvpMats.model = T_model * R_model * scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
-   shipMvpMats.view = view;
-   shipMvpMats.proj = proj;
+   object_VP_mats.view = view;
+   object_VP_mats.proj = proj;
+
+   ship_VP_mats.view = view;
+   ship_VP_mats.proj = proj;
 }
 
@@ -607,4 +613,6 @@
 }
 
+// TODO: The view and projection mats only need to be updated once.
+// Create a separate function that can do this once per Vulkan image at the beginning
 void VulkanGame::updateScene(uint32_t currentImage) {
    static auto startTime = chrono::high_resolution_clock::now();
@@ -613,11 +621,19 @@
    float time = chrono::duration<float, chrono::seconds::period>(currentTime - startTime).count();
 
-   modelMvpMats.model =
+   so_Object.model =
       translate(mat4(1.0f), vec3(0.0f, -2.0f, -0.0f)) *
       rotate(mat4(1.0f), time * radians(90.0f), vec3(0.0f, 0.0f, 1.0f));
 
-   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory[currentImage], modelMvpMats);
-
-   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_shipPipeline[currentImage], shipMvpMats);
+   so_Ship.model =
+      translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f)) *
+      scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
+
+   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_scenePipeline[currentImage], object_VP_mats);
+
+   VulkanUtils::copyDataToMemory(device, storageBuffersMemory_scenePipeline[currentImage], so_Object);
+
+   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_shipPipeline[currentImage], ship_VP_mats);
+
+   VulkanUtils::copyDataToMemory(device, storageBuffersMemory_shipPipeline[currentImage], so_Ship);
 }
 
@@ -901,6 +917,5 @@
 
 void VulkanGame::createLogicalDevice(
-      const vector<const char*> validationLayers,
-      const vector<const char*>& deviceExtensions) {
+      const vector<const char*> validationLayers, const vector<const char*>& deviceExtensions) {
    QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface);
 
@@ -1237,4 +1252,21 @@
 }
 
+void VulkanGame::createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags,
+      vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory, vector<VkDescriptorBufferInfo>& bufferInfoList) {
+   buffers.resize(swapChainImages.size());
+   buffersMemory.resize(swapChainImages.size());
+   bufferInfoList.resize(swapChainImages.size());
+
+   for (size_t i = 0; i < swapChainImages.size(); i++) {
+      VulkanUtils::createBuffer(device, physicalDevice, bufferSize, flags,
+         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+         buffers[i], buffersMemory[i]);
+
+      bufferInfoList[i].buffer = buffers[i];
+      bufferInfoList[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now
+      bufferInfoList[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE
+   }
+}
+
 // TODO: Fix the crash that happens when alt-tabbing
 void VulkanGame::recreateSwapChain() {
@@ -1260,5 +1292,8 @@
    createFramebuffers();
 
-   createUniformBuffers<UBO_MvpMat>(uniformBuffers, uniformBuffersMemory, uniformBufferInfoList);
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_scenePipeline, uniformBuffersMemory_scenePipeline, uniformBufferInfoList_scenePipeline);
+   createBufferSet(10 * sizeof(SBO_SceneObject), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_scenePipeline, storageBuffersMemory_scenePipeline, storageBufferInfoList_scenePipeline);
 
    modelPipeline.updateRenderPass(renderPass);
@@ -1272,5 +1307,8 @@
    overlayPipeline.createDescriptorSets(swapChainImages);
 
-   createUniformBuffers<UBO_MvpMat>(uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
+   createBufferSet(10 * sizeof(SBO_SceneObject), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_shipPipeline, storageBuffersMemory_shipPipeline, storageBufferInfoList_shipPipeline);
 
    shipPipeline.updateRenderPass(renderPass);
@@ -1303,7 +1341,12 @@
    vkDestroySwapchainKHR(device, swapChain, nullptr);
 
-   for (size_t i = 0; i < uniformBuffers.size(); i++) {
-      vkDestroyBuffer(device, uniformBuffers[i], nullptr);
-      vkFreeMemory(device, uniformBuffersMemory[i], nullptr);
+   for (size_t i = 0; i < uniformBuffers_scenePipeline.size(); i++) {
+      vkDestroyBuffer(device, uniformBuffers_scenePipeline[i], nullptr);
+      vkFreeMemory(device, uniformBuffersMemory_scenePipeline[i], nullptr);
+   }
+
+   for (size_t i = 0; i < storageBuffers_scenePipeline.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_scenePipeline[i], nullptr);
+      vkFreeMemory(device, storageBuffersMemory_scenePipeline[i], nullptr);
    }
 
@@ -1312,3 +1355,8 @@
       vkFreeMemory(device, uniformBuffersMemory_shipPipeline[i], nullptr);
    }
-}
+
+   for (size_t i = 0; i < storageBuffers_shipPipeline.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_shipPipeline[i], nullptr);
+      vkFreeMemory(device, storageBuffersMemory_shipPipeline[i], nullptr);
+   }
+}
