Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision c1ec4f63156230af7a921799acc46120ccc4b110)
+++ vulkan-game.cpp	(revision 6486ba8f42f8ee2b61912e3a96ac6921ee30292b)
@@ -139,6 +139,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_modelPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_modelPipeline);
+
+   createBufferSet(objects_modelPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_modelPipeline);
 
    modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -149,5 +156,5 @@
       VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
 
-   SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr;
+   SceneObject<ModelVertex>* texturedSquare = nullptr;
 
    texturedSquare = &addObject(modelObjects, modelPipeline,
@@ -202,6 +209,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_shipPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_shipPipeline);
+
+   createBufferSet(objects_shipPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_shipPipeline);
 
    shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -212,5 +226,5 @@
    // TODO: With the normals, indexing basically becomes pointless since no vertices will have exactly
    // the same data. Add an option to make some pipelines not use indexing
-   SceneObject<ModelVertex, SSBO_ModelObject>& ship = addObject(shipObjects, shipPipeline,
+   SceneObject<ModelVertex>& ship = addObject(shipObjects, shipPipeline,
       addObjectIndex<ModelVertex>(shipObjects.size(),
          addVertexNormals<ModelVertex>({
@@ -462,6 +476,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_asteroidPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_asteroidPipeline);
+
+   createBufferSet(objects_asteroidPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_asteroidPipeline);
 
    asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -480,6 +501,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_laserPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_laserPipeline);
+
+   createBufferSet(objects_laserPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_laserPipeline);
 
    laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -500,6 +528,13 @@
 
    createBufferSet(sizeof(UBO_Explosion),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_explosionPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_explosionPipeline);
+
+   createBufferSet(objects_explosionPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_explosionPipeline);
 
    explosionPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -615,39 +650,15 @@
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 24, 24);
 
-   createBufferSet(objects_modelPipeline.capacity * sizeof(SSBO_ModelObject),
-                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
-                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-                   storageBuffers_modelPipeline);
-
    shipPipeline = GraphicsPipeline_Vulkan<ModelVertex>(
       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 138, 138);
 
-   createBufferSet(objects_shipPipeline.capacity * sizeof(SSBO_ModelObject),
-                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
-                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-                   storageBuffers_shipPipeline);
-
    asteroidPipeline = GraphicsPipeline_Vulkan<ModelVertex>(
       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 24, 36);
 
-   createBufferSet(objects_asteroidPipeline.capacity * sizeof(SSBO_Asteroid),
-                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
-                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-                   storageBuffers_asteroidPipeline);
-
    laserPipeline = GraphicsPipeline_Vulkan<LaserVertex>(
       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 8, 18);
-
-   createBufferSet(objects_laserPipeline.capacity * sizeof(SSBO_Laser),
-                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
-                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-                   storageBuffers_laserPipeline);
 
    explosionPipeline = GraphicsPipeline_Vulkan<ExplosionVertex>(
@@ -655,10 +666,4 @@
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height },
       EXPLOSION_PARTICLE_COUNT, EXPLOSION_PARTICLE_COUNT);
-
-   createBufferSet(objects_explosionPipeline.capacity * sizeof(SSBO_Explosion),
-                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
-                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-                   storageBuffers_explosionPipeline);
 }
 
@@ -767,20 +772,19 @@
                   float zOffset = -2.0f + (0.5f * modelObjects.size());
 
-                  SceneObject<ModelVertex, SSBO_ModelObject>& texturedSquare =
-                     addObject(modelObjects, modelPipeline,
-                        addObjectIndex<ModelVertex>(modelObjects.size(),
-                           addVertexNormals<ModelVertex>({
-                              {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
-                              {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
-                              {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
-                              {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
-                              {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
-                              {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
-                           })),
-                        {
-                           0, 1, 2, 3, 4, 5
-                        }, objects_modelPipeline, {
-                           mat4(1.0f)
-                        });
+                  SceneObject<ModelVertex>& texturedSquare = addObject(modelObjects, modelPipeline,
+                     addObjectIndex<ModelVertex>(modelObjects.size(),
+                        addVertexNormals<ModelVertex>({
+                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
+                           {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
+                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
+                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
+                           {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
+                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
+                        })),
+                     {
+                        0, 1, 2, 3, 4, 5
+                     }, objects_modelPipeline, {
+                        mat4(1.0f)
+                     });
 
                   texturedSquare.model_base =
@@ -817,5 +821,5 @@
                // START UNREVIEWED SECTION
                if (e.key.keycode == SDL_SCANCODE_Z && leftLaserIdx != -1) {
-                  laserObjects[leftLaserIdx].ssbo.deleted = true;
+                  objects_laserPipeline.get(leftLaserIdx).deleted = true;
                   leftLaserIdx = -1;
 
@@ -825,5 +829,5 @@
                   }
                } else if (e.key.keycode == SDL_SCANCODE_X && rightLaserIdx != -1) {
-                  laserObjects[rightLaserIdx].ssbo.deleted = true;
+                  objects_laserPipeline.get(rightLaserIdx).deleted = true;
                   rightLaserIdx = -1;
 
@@ -857,5 +861,5 @@
       // Check which keys are held down
 
-      SceneObject<ModelVertex, SSBO_ModelObject>& ship = shipObjects[0];
+      SceneObject<ModelVertex>& ship = shipObjects[0];
 
       if (gui->keyPressed(SDL_SCANCODE_LEFT)) {
@@ -936,72 +940,71 @@
 // where it will run just once per frame
 void VulkanGame::updateScene() {
-   if (curTime - this->lastSpawn_asteroid > this->spawnRate_asteroid) {
-      this->lastSpawn_asteroid = curTime;
-
-      SceneObject<ModelVertex, SSBO_Asteroid>& asteroid =
-         addObject(asteroidObjects, asteroidPipeline,
-            addObjectIndex<ModelVertex>(asteroidObjects.size(),
-               addVertexNormals<ModelVertex>({
-
-                  // front
-                  {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-
-                  // top
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-
-                  // bottom
-                  {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f, -1.0}, {0.4f, 0.4f, 0.4f}},
-
-                  // back
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-
-                  // right
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-
-                  // left
-                  {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
-                  {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
-               })),
-            {
-                0,  1,  2,  3,  4,  5,
-                6,  7,  8,  9, 10, 11,
-               12, 13, 14, 15, 16, 17,
-               18, 19, 20, 21, 22, 23,
-               24, 25, 26, 27, 28, 29,
-               30, 31, 32, 33, 34, 35,
-            }, objects_asteroidPipeline, {
-               mat4(1.0f),
-               10.0f,
-               false
-            });
+   if (curTime - lastSpawn_asteroid > spawnRate_asteroid) {
+      lastSpawn_asteroid = curTime;
+
+      SceneObject<ModelVertex>& asteroid = addObject(asteroidObjects, asteroidPipeline,
+         addObjectIndex<ModelVertex>(asteroidObjects.size(),
+            addVertexNormals<ModelVertex>({
+
+               // front
+               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+
+               // top
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+
+               // bottom
+               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f, -1.0}, {0.4f, 0.4f, 0.4f}},
+
+               // back
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+
+               // right
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+
+               // left
+               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+            })),
+         {
+             0,  1,  2,  3,  4,  5,
+             6,  7,  8,  9, 10, 11,
+            12, 13, 14, 15, 16, 17,
+            18, 19, 20, 21, 22, 23,
+            24, 25, 26, 27, 28, 29,
+            30, 31, 32, 33, 34, 35,
+         }, objects_asteroidPipeline, {
+            mat4(1.0f),
+            10.0f,
+            false
+         });
 
       // This accounts for the scaling in model_base.
@@ -1033,6 +1036,6 @@
 
    for (size_t i = 0; i < modelObjects.size(); i++) {
-      SceneObject<ModelVertex, SSBO_ModelObject>& obj = modelObjects[i];
-      SSBO_ModelObject& objData = obj.ssbo;
+      SceneObject<ModelVertex>& obj = modelObjects[i];
+      SSBO_ModelObject& objData = objects_modelPipeline.get(i);
 
       // Rotate the textured squares
@@ -1058,6 +1061,6 @@
    // TODO: Move ship position updates from the ui event handling code into this function
    for (size_t i = 0; i < shipObjects.size(); i++) {
-      SceneObject<ModelVertex, SSBO_ModelObject>& obj = shipObjects[i];
-      SSBO_ModelObject& objData = obj.ssbo;
+      SceneObject<ModelVertex>& obj = shipObjects[i];
+      SSBO_ModelObject& objData = objects_shipPipeline.get(i);
 
       objData.model = obj.model_transform * obj.model_base;
@@ -1077,6 +1080,6 @@
 
    for (size_t i = 0; i < asteroidObjects.size(); i++) {
-      SceneObject<ModelVertex, SSBO_Asteroid>& obj = asteroidObjects[i];
-      SSBO_Asteroid& objData = obj.ssbo;
+      SceneObject<ModelVertex>& obj = asteroidObjects[i];
+      SSBO_Asteroid& objData = objects_asteroidPipeline.get(i);
 
       if (!objData.deleted) {
@@ -1127,6 +1130,6 @@
 
    for (size_t i = 0; i < laserObjects.size(); i++) {
-      SceneObject<LaserVertex, SSBO_Laser>& obj = laserObjects[i];
-      SSBO_Laser& objData = obj.ssbo;
+      SceneObject<LaserVertex>& obj = laserObjects[i];
+      SSBO_Laser& objData = objects_laserPipeline.get(i);
 
       objData.model = obj.model_transform * obj.model_base;
@@ -1146,6 +1149,6 @@
 
    for (size_t i = 0; i < explosionObjects.size(); i++) {
-      SceneObject<ExplosionVertex, SSBO_Explosion>& obj = explosionObjects[i];
-      SSBO_Explosion& objData = obj.ssbo;
+      SceneObject<ExplosionVertex>& obj = explosionObjects[i];
+      SSBO_Explosion& objData = objects_explosionPipeline.get(i);
 
       if (!objData.deleted) {
@@ -1212,29 +1215,4 @@
    laserPipeline.cleanupBuffers();
    explosionPipeline.cleanupBuffers();
-
-   for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
-      vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
-      vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
-   }
-
-   for (size_t i = 0; i < storageBuffers_shipPipeline.buffers.size(); i++) {
-      vkDestroyBuffer(device, storageBuffers_shipPipeline.buffers[i], nullptr);
-      vkFreeMemory(device, storageBuffers_shipPipeline.memory[i], nullptr);
-   }
-
-   for (size_t i = 0; i < storageBuffers_asteroidPipeline.buffers.size(); i++) {
-      vkDestroyBuffer(device, storageBuffers_asteroidPipeline.buffers[i], nullptr);
-      vkFreeMemory(device, storageBuffers_asteroidPipeline.memory[i], nullptr);
-   }
-
-   for (size_t i = 0; i < storageBuffers_laserPipeline.buffers.size(); i++) {
-      vkDestroyBuffer(device, storageBuffers_laserPipeline.buffers[i], nullptr);
-      vkFreeMemory(device, storageBuffers_laserPipeline.memory[i], nullptr);
-   }
-
-   for (size_t i = 0; i < storageBuffers_explosionPipeline.buffers.size(); i++) {
-      vkDestroyBuffer(device, storageBuffers_explosionPipeline.buffers[i], nullptr);
-      vkFreeMemory(device, storageBuffers_explosionPipeline.memory[i], nullptr);
-   }
 
    // END UNREVIEWED SECTION
@@ -2004,6 +1982,5 @@
    float length = glm::length(ray);
 
-   SceneObject<LaserVertex, SSBO_Laser>& laser = addObject(
-      laserObjects, laserPipeline,
+   SceneObject<LaserVertex>& laser = addObject(laserObjects, laserPipeline,
       addObjectIndex<LaserVertex>(laserObjects.size(), {
          {{ width / 2, 0.0f, -width / 2         }, {1.0f, 0.5f }},
@@ -2051,5 +2028,5 @@
 
 void VulkanGame::translateLaser(size_t index, const vec3& translation) {
-   SceneObject<LaserVertex, SSBO_Laser>& laser = this->laserObjects[index];
+   SceneObject<LaserVertex>& laser = laserObjects[index];
 
    // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
@@ -2081,5 +2058,5 @@
 
 void VulkanGame::updateLaserTarget(size_t index) {
-   SceneObject<LaserVertex, SSBO_Laser>& laser = this->laserObjects[index];
+   SceneObject<LaserVertex>& laser = laserObjects[index];
 
    // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
@@ -2090,10 +2067,10 @@
 
    vec3 intersection(0.0f), closestIntersection(0.0f);
-   SceneObject<ModelVertex, SSBO_Asteroid>* closestAsteroid = nullptr;
+   SceneObject<ModelVertex>* closestAsteroid = nullptr;
    unsigned int closestAsteroidIndex = -1;
 
-   for (int i = 0; i < this->asteroidObjects.size(); i++) {
-      if (!this->asteroidObjects[i].ssbo.deleted &&
-            this->getLaserAndAsteroidIntersection(this->asteroidObjects[i], start, end, intersection)) {
+   for (int i = 0; i < asteroidObjects.size(); i++) {
+      if (!objects_asteroidPipeline.get(i).deleted &&
+          getLaserAndAsteroidIntersection(asteroidObjects[i], start, end, intersection)) {
          // TODO: Implement a more generic algorithm for testing the closest object by getting the distance between the points
          // TODO: Also check which intersection is close to the start of the laser. This would make the algorithm work
@@ -2119,10 +2096,10 @@
       }
 
-      EffectOverTime<ModelVertex, SSBO_Asteroid>* eot = nullptr;
+      EffectOverTime<SSBO_Asteroid>* eot = nullptr;
 
       if (closestAsteroid != nullptr) {
-         // TODO: Use some sort of smart pointer instead
-         eot = new EffectOverTime<ModelVertex, SSBO_Asteroid>(asteroidPipeline, asteroidObjects, closestAsteroidIndex,
-            offset_of(&SSBO_Asteroid::hp), curTime, -20.0f);
+         // TODO: Figure out if I should use a smart pointer instead
+         eot = new EffectOverTime(objects_asteroidPipeline, closestAsteroidIndex, offset_of(&SSBO_Asteroid::hp),
+                                  curTime, -20.0f);
          effects.push_back(eot);
       }
@@ -2146,11 +2123,11 @@
 
    // TODO: Consider if I want to set a flag and do this update in updateScene() instead
-   updateObjectVertices(this->laserPipeline, laser, index);
+   updateObjectVertices(laserPipeline, laser, index);
 }
 
 // TODO: Determine if I should pass start and end by reference or value since they don't get changed
 // Probably use const reference
-bool VulkanGame::getLaserAndAsteroidIntersection(SceneObject<ModelVertex, SSBO_Asteroid>& asteroid,
-      vec3& start, vec3& end, vec3& intersection) {
+bool VulkanGame::getLaserAndAsteroidIntersection(SceneObject<ModelVertex>& asteroid, vec3& start, vec3& end,
+                                                 vec3& intersection) {
    /*
    ### LINE EQUATIONS ###
@@ -2221,5 +2198,5 @@
    iota(indices.begin(), indices.end(), 0);
 
-   SceneObject<ExplosionVertex, SSBO_Explosion>& explosion = addObject(explosionObjects, explosionPipeline,
+   SceneObject<ExplosionVertex>& explosion = addObject(explosionObjects, explosionPipeline,
       addObjectIndex(explosionObjects.size(), vertices), indices, objects_explosionPipeline, {
          mat4(1.0f),
@@ -2254,11 +2231,14 @@
    createSyncObjects();
 
-   // TODO: Move UBO creation/management into GraphicsPipeline_Vulkan, like I did with SSBOs
-   // TODO: Check if the shader stages and maybe some other properties of the pipeline can be re-used
-   // instead of recreated every time
-
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_modelPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_modelPipeline);
+
+   createBufferSet(objects_modelPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_modelPipeline);
 
    modelPipeline.updateRenderPass(renderPass);
@@ -2268,6 +2248,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_shipPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_shipPipeline);
+
+   createBufferSet(objects_shipPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_shipPipeline);
 
    shipPipeline.updateRenderPass(renderPass);
@@ -2277,6 +2264,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_asteroidPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_asteroidPipeline);
+
+   createBufferSet(objects_asteroidPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_asteroidPipeline);
 
    asteroidPipeline.updateRenderPass(renderPass);
@@ -2286,6 +2280,13 @@
 
    createBufferSet(sizeof(UBO_VP_mats),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_laserPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_laserPipeline);
+
+   createBufferSet(objects_laserPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_laserPipeline);
 
    laserPipeline.updateRenderPass(renderPass);
@@ -2295,6 +2296,13 @@
 
    createBufferSet(sizeof(UBO_Explosion),
-      VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-      uniformBuffers_explosionPipeline);
+                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   uniformBuffers_explosionPipeline);
+
+   createBufferSet(objects_explosionPipeline.memorySize(),
+                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                   storageBuffers_explosionPipeline);
 
    explosionPipeline.updateRenderPass(renderPass);
@@ -2329,4 +2337,9 @@
    }
 
+   for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
+      vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
+   }
+
    for (size_t i = 0; i < uniformBuffers_shipPipeline.buffers.size(); i++) {
       vkDestroyBuffer(device, uniformBuffers_shipPipeline.buffers[i], nullptr);
@@ -2334,4 +2347,9 @@
    }
 
+   for (size_t i = 0; i < storageBuffers_shipPipeline.buffers.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_shipPipeline.buffers[i], nullptr);
+      vkFreeMemory(device, storageBuffers_shipPipeline.memory[i], nullptr);
+   }
+
    for (size_t i = 0; i < uniformBuffers_asteroidPipeline.buffers.size(); i++) {
       vkDestroyBuffer(device, uniformBuffers_asteroidPipeline.buffers[i], nullptr);
@@ -2339,4 +2357,9 @@
    }
 
+   for (size_t i = 0; i < storageBuffers_asteroidPipeline.buffers.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_asteroidPipeline.buffers[i], nullptr);
+      vkFreeMemory(device, storageBuffers_asteroidPipeline.memory[i], nullptr);
+   }
+
    for (size_t i = 0; i < uniformBuffers_laserPipeline.buffers.size(); i++) {
       vkDestroyBuffer(device, uniformBuffers_laserPipeline.buffers[i], nullptr);
@@ -2344,7 +2367,17 @@
    }
 
+   for (size_t i = 0; i < storageBuffers_laserPipeline.buffers.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_laserPipeline.buffers[i], nullptr);
+      vkFreeMemory(device, storageBuffers_laserPipeline.memory[i], nullptr);
+   }
+
    for (size_t i = 0; i < uniformBuffers_explosionPipeline.buffers.size(); i++) {
       vkDestroyBuffer(device, uniformBuffers_explosionPipeline.buffers[i], nullptr);
       vkFreeMemory(device, uniformBuffers_explosionPipeline.memory[i], nullptr);
+   }
+
+   for (size_t i = 0; i < storageBuffers_explosionPipeline.buffers.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_explosionPipeline.buffers[i], nullptr);
+      vkFreeMemory(device, storageBuffers_explosionPipeline.memory[i], nullptr);
    }
 
