Index: sdl-game.cpp
===================================================================
--- sdl-game.cpp	(revision 5ea0a37095f83aa1eb8ad853b90c9675730b6782)
+++ sdl-game.cpp	(revision 90880fb20c607160a5a48bacee6fd39c33e88e18)
@@ -70,4 +70,5 @@
                      , gui(nullptr)
                      , window(nullptr)
+                     , vp_mats_modelPipeline()
                      , objects_modelPipeline()
                      , score(0)
@@ -91,4 +92,7 @@
    VkPhysicalDeviceProperties deviceProperties;
    vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+
+   vp_mats_modelPipeline = VulkanBuffer<UBO_VP_mats>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                     deviceProperties.limits.minUniformBufferOffsetAlignment);
 
    objects_modelPipeline = VulkanBuffer<SSBO_ModelObject>(10, deviceProperties.limits.maxStorageBufferRange,
@@ -110,10 +114,10 @@
    modelPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_modelPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
                    uniformBuffers_modelPipeline);
 
-   createBufferSet(objects_modelPipeline.capacity * sizeof(SSBO_ModelObject),
+   createBufferSet(objects_modelPipeline.memorySize(),
                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
@@ -289,7 +293,4 @@
    projMat = perspective(radians(FOV_ANGLE), (float)swapChainExtent.width / (float)swapChainExtent.height, NEAR_CLIP, FAR_CLIP);
    projMat[1][1] *= -1; // flip the y-axis so that +y is up
-
-   object_VP_mats.view = viewMat;
-   object_VP_mats.proj = projMat;
 }
 
@@ -444,5 +445,11 @@
 
 void VulkanGame::updateScene() {
-   // TODO: Probably move the resizing to the VulkanBuffer class
+   vp_mats_modelPipeline.data()->view = viewMat;
+   vp_mats_modelPipeline.data()->proj = projMat;
+
+   // TODO: Probably move the resizing to the VulkanBuffer class's add() method
+   // Remember that we want to avoid resizing the actuall ssbo or ubo more than once per frame
+   // TODO: Figure out a way to make updateDescriptorInfo easier to use, maybe store the binding index in the buffer set
+
    if (objects_modelPipeline.resized) {
       resizeBufferSet(storageBuffers_modelPipeline, objects_modelPipeline.memorySize(), resourceCommandPool,
@@ -467,9 +474,9 @@
    }
 
+   VulkanUtils::copyDataToMemory(device, vp_mats_modelPipeline.data(), uniformBuffers_modelPipeline.memory[imageIndex],
+                                 0, vp_mats_modelPipeline.memorySize(), false);
+
    VulkanUtils::copyDataToMemory(device, objects_modelPipeline.data(), storageBuffers_modelPipeline.memory[imageIndex],
                                  0, objects_modelPipeline.memorySize(), false);
-
-   VulkanUtils::copyDataToMemory(device, &object_VP_mats, uniformBuffers_modelPipeline.memory[imageIndex], 0,
-                                 sizeof(object_VP_mats), false);
 }
 
@@ -1275,5 +1282,5 @@
    createSyncObjects();
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_modelPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
Index: sdl-game.hpp
===================================================================
--- sdl-game.hpp	(revision 5ea0a37095f83aa1eb8ad853b90c9675730b6782)
+++ sdl-game.hpp	(revision 90880fb20c607160a5a48bacee6fd39c33e88e18)
@@ -225,7 +225,9 @@
       GraphicsPipeline_Vulkan<ModelVertex> modelPipeline;
 
+      BufferSet uniformBuffers_modelPipeline;
       BufferSet storageBuffers_modelPipeline;
+
+      VulkanBuffer<UBO_VP_mats> vp_mats_modelPipeline;
       VulkanBuffer<SSBO_ModelObject> objects_modelPipeline;
-      BufferSet uniformBuffers_modelPipeline;
 
       // TODO: Maybe make the ubo objects part of the pipeline class since there's only one ubo
@@ -238,6 +240,4 @@
 
       vector<SceneObject<ModelVertex>> modelObjects;
-
-      UBO_VP_mats object_VP_mats;
 
       /*** High-level vars ***/
Index: vulkan-buffer.hpp
===================================================================
--- vulkan-buffer.hpp	(revision 5ea0a37095f83aa1eb8ad853b90c9675730b6782)
+++ vulkan-buffer.hpp	(revision 90880fb20c607160a5a48bacee6fd39c33e88e18)
@@ -37,4 +37,9 @@
       T& get(uint32_t index);
       void add(T obj);
+
+      void* mapped(size_t idx);
+
+      void map(vector<VkDeviceMemory>& deviceMemory, VkDevice device);
+      void unmap(vector<VkDeviceMemory>& deviceMemory, VkDevice device);
 
       void resize();
@@ -182,4 +187,29 @@
 
 template<class T>
+void* VulkanBuffer<T>::mapped(size_t idx) {
+   return mappedData[idx];
+}
+
+template<class T>
+void VulkanBuffer<T>::map(vector<VkDeviceMemory>& deviceMemory, VkDevice device) {
+   // TODO: Make sure that mappedData initally has size 0. If not, it means the memory is already mapped
+   // and I should return some kind of error or warning
+   mappedData.resize(deviceMemory.size());
+
+   for (size_t i = 0; i < deviceMemory.size(); i++) {
+      vkMapMemory(device, deviceMemory[i], 0, memorySize(), 0, &mappedData[i]);
+   }
+}
+
+template<class T>
+void VulkanBuffer<T>::unmap(vector<VkDeviceMemory>& deviceMemory, VkDevice device) {
+   for (size_t i = 0; i < deviceMemory.size(); i++) {
+      vkUnmapMemory(device, deviceMemory[i]);
+   }
+
+   mappedData.clear();
+}
+
+template<class T>
 void VulkanBuffer<T>::resize() {
    resized = false;
Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision 5ea0a37095f83aa1eb8ad853b90c9675730b6782)
+++ vulkan-game.cpp	(revision 90880fb20c607160a5a48bacee6fd39c33e88e18)
@@ -77,16 +77,16 @@
                      , gui(nullptr)
                      , window(nullptr)
+                     , vp_mats_modelPipeline()
                      , objects_modelPipeline()
+                     , vp_mats_shipPipeline()
                      , objects_shipPipeline()
+                     , vp_mats_asteroidPipeline()
                      , objects_asteroidPipeline()
+                     , vp_mats_laserPipeline()
                      , objects_laserPipeline()
+                     , uniforms_explosionPipeline()
                      , objects_explosionPipeline()
                      , score(0)
                      , fps(0.0f) {
-   object_VP_mats = {};
-   ship_VP_mats = {};
-   asteroid_VP_mats = {};
-   laser_VP_mats = {};
-   explosion_UBO = {};
 }
 
@@ -110,12 +110,31 @@
    vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
 
+   vp_mats_modelPipeline = VulkanBuffer<UBO_VP_mats>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                     deviceProperties.limits.minUniformBufferOffsetAlignment);
+
    objects_modelPipeline = VulkanBuffer<SSBO_ModelObject>(10, deviceProperties.limits.maxStorageBufferRange,
                                                           deviceProperties.limits.minStorageBufferOffsetAlignment);
+
+   vp_mats_shipPipeline = VulkanBuffer<UBO_VP_mats>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                    deviceProperties.limits.minUniformBufferOffsetAlignment);
+
    objects_shipPipeline = VulkanBuffer<SSBO_ModelObject>(10, deviceProperties.limits.maxStorageBufferRange,
                                                          deviceProperties.limits.minStorageBufferOffsetAlignment);
+
+   vp_mats_asteroidPipeline = VulkanBuffer<UBO_VP_mats>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                        deviceProperties.limits.minUniformBufferOffsetAlignment);
+
    objects_asteroidPipeline = VulkanBuffer<SSBO_Asteroid>(10, deviceProperties.limits.maxStorageBufferRange,
                                                           deviceProperties.limits.minStorageBufferOffsetAlignment);
+
+   vp_mats_laserPipeline = VulkanBuffer<UBO_VP_mats>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                     deviceProperties.limits.minUniformBufferOffsetAlignment);
+
    objects_laserPipeline = VulkanBuffer<SSBO_Laser>(2, deviceProperties.limits.maxStorageBufferRange,
                                                     deviceProperties.limits.minStorageBufferOffsetAlignment);
+
+   uniforms_explosionPipeline = VulkanBuffer<UBO_Explosion>(1, deviceProperties.limits.maxUniformBufferRange,
+                                                            deviceProperties.limits.minUniformBufferOffsetAlignment);
+
    objects_explosionPipeline = VulkanBuffer<SSBO_Explosion>(2, deviceProperties.limits.maxStorageBufferRange,
                                                             deviceProperties.limits.minStorageBufferOffsetAlignment);
@@ -138,5 +157,5 @@
    modelPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_modelPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -208,5 +227,5 @@
    shipPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_shipPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -475,5 +494,5 @@
    asteroidPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_asteroidPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -500,5 +519,5 @@
    laserPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&LaserVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_laserPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -527,5 +546,5 @@
    explosionPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ExplosionVertex::objIndex));
 
-   createBufferSet(sizeof(UBO_Explosion),
+   createBufferSet(uniforms_explosionPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -684,19 +703,4 @@
    projMat = perspective(radians(FOV_ANGLE), (float)swapChainExtent.width / (float)swapChainExtent.height, NEAR_CLIP, FAR_CLIP);
    projMat[1][1] *= -1; // flip the y-axis so that +y is up
-
-   object_VP_mats.view = viewMat;
-   object_VP_mats.proj = projMat;
-
-   ship_VP_mats.view = viewMat;
-   ship_VP_mats.proj = projMat;
-
-   asteroid_VP_mats.view = viewMat;
-   asteroid_VP_mats.proj = projMat;
-
-   laser_VP_mats.view = viewMat;
-   laser_VP_mats.proj = projMat;
-
-   explosion_UBO.view = viewMat;
-   explosion_UBO.proj = projMat;
 }
 
@@ -940,4 +944,34 @@
 // where it will run just once per frame
 void VulkanGame::updateScene() {
+
+   vp_mats_modelPipeline.data()->view = viewMat;
+   vp_mats_modelPipeline.data()->proj = projMat;
+
+   vp_mats_shipPipeline.data()->view = viewMat;
+   vp_mats_shipPipeline.data()->proj = projMat;
+
+   vp_mats_asteroidPipeline.data()->view = viewMat;
+   vp_mats_asteroidPipeline.data()->proj = projMat;
+
+   vp_mats_laserPipeline.data()->view = viewMat;
+   vp_mats_laserPipeline.data()->proj = projMat;
+
+   uniforms_explosionPipeline.data()->view = viewMat;
+   uniforms_explosionPipeline.data()->proj = projMat;
+   uniforms_explosionPipeline.data()->cur_time = curTime;
+
+   for (vector<BaseEffectOverTime*>::iterator it = effects.begin(); it != effects.end(); ) {
+      if ((*it)->deleted) {
+         delete *it;
+         it = effects.erase(it);
+      } else {
+         BaseEffectOverTime* eot = *it;
+
+         eot->applyEffect(curTime);
+
+         it++;
+      }
+   }
+
    if (curTime - lastSpawn_asteroid > spawnRate_asteroid) {
       lastSpawn_asteroid = curTime;
@@ -1046,4 +1080,7 @@
    }
 
+   VulkanUtils::copyDataToMemory(device, vp_mats_modelPipeline.data(), uniformBuffers_modelPipeline.memory[imageIndex],
+                                 0, vp_mats_modelPipeline.memorySize(), false);
+
    VulkanUtils::copyDataToMemory(device, objects_modelPipeline.data(), storageBuffers_modelPipeline.memory[imageIndex],
                                  0, objects_modelPipeline.memorySize(), false);
@@ -1066,4 +1103,7 @@
       obj.center = vec3(objData.model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
    }
+
+   VulkanUtils::copyDataToMemory(device, vp_mats_shipPipeline.data(), uniformBuffers_shipPipeline.memory[imageIndex],
+                                 0, vp_mats_shipPipeline.memorySize(), false);
 
    VulkanUtils::copyDataToMemory(device, objects_shipPipeline.data(), storageBuffers_shipPipeline.memory[imageIndex],
@@ -1111,4 +1151,7 @@
    }
 
+   VulkanUtils::copyDataToMemory(device, vp_mats_asteroidPipeline.data(), uniformBuffers_asteroidPipeline.memory[imageIndex],
+                                 0, vp_mats_asteroidPipeline.memorySize(), false);
+
    VulkanUtils::copyDataToMemory(device, objects_asteroidPipeline.data(), storageBuffers_asteroidPipeline.memory[imageIndex],
                                  0, objects_asteroidPipeline.memorySize(), false);
@@ -1137,4 +1180,7 @@
       obj.center = vec3(objData.model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
    }
+
+   VulkanUtils::copyDataToMemory(device, vp_mats_laserPipeline.data(), uniformBuffers_laserPipeline.memory[imageIndex],
+                                 0, vp_mats_laserPipeline.memorySize(), false);
 
    VulkanUtils::copyDataToMemory(device, objects_laserPipeline.data(), storageBuffers_laserPipeline.memory[imageIndex],
@@ -1164,36 +1210,9 @@
    }
 
+   VulkanUtils::copyDataToMemory(device, uniforms_explosionPipeline.data(), uniformBuffers_explosionPipeline.memory[imageIndex],
+                                 0, uniforms_explosionPipeline.memorySize(), false);
+
    VulkanUtils::copyDataToMemory(device, objects_explosionPipeline.data(), storageBuffers_explosionPipeline.memory[imageIndex],
                                  0, objects_explosionPipeline.memorySize(), false);
-
-   explosion_UBO.cur_time = curTime;
-
-   for (vector<BaseEffectOverTime*>::iterator it = effects.begin(); it != effects.end(); ) {
-      if ((*it)->deleted) {
-         delete *it;
-         it = effects.erase(it);
-      } else {
-         BaseEffectOverTime* eot = *it;
-
-         eot->applyEffect(curTime);
-
-         it++;
-      }
-   }
-
-   VulkanUtils::copyDataToMemory(device, &object_VP_mats, uniformBuffers_modelPipeline.memory[imageIndex], 0,
-                                 sizeof(object_VP_mats), false);
-
-   VulkanUtils::copyDataToMemory(device, &ship_VP_mats, uniformBuffers_shipPipeline.memory[imageIndex], 0,
-                                 sizeof(ship_VP_mats), false);
-
-   VulkanUtils::copyDataToMemory(device, &asteroid_VP_mats, uniformBuffers_asteroidPipeline.memory[imageIndex], 0,
-                                 sizeof(asteroid_VP_mats), false);
-
-   VulkanUtils::copyDataToMemory(device, &laser_VP_mats, uniformBuffers_laserPipeline.memory[imageIndex], 0,
-                                 sizeof(laser_VP_mats), false);
-
-   VulkanUtils::copyDataToMemory(device, &explosion_UBO, uniformBuffers_explosionPipeline.memory[imageIndex], 0,
-                                 sizeof(explosion_UBO), false);
 }
 
@@ -2234,5 +2253,5 @@
    createSyncObjects();
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_modelPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -2250,5 +2269,5 @@
    modelPipeline.createDescriptorSets(swapChainImages.size());
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_shipPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -2266,5 +2285,5 @@
    shipPipeline.createDescriptorSets(swapChainImages.size());
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_asteroidPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -2282,5 +2301,5 @@
    asteroidPipeline.createDescriptorSets(swapChainImages.size());
 
-   createBufferSet(sizeof(UBO_VP_mats),
+   createBufferSet(vp_mats_laserPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
@@ -2298,5 +2317,5 @@
    laserPipeline.createDescriptorSets(swapChainImages.size());
 
-   createBufferSet(sizeof(UBO_Explosion),
+   createBufferSet(uniforms_explosionPipeline.memorySize(),
                    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision 5ea0a37095f83aa1eb8ad853b90c9675730b6782)
+++ vulkan-game.hpp	(revision 90880fb20c607160a5a48bacee6fd39c33e88e18)
@@ -311,23 +311,33 @@
       GraphicsPipeline_Vulkan<ExplosionVertex> explosionPipeline;
 
+      BufferSet uniformBuffers_modelPipeline;
       BufferSet storageBuffers_modelPipeline;
+
+      VulkanBuffer<UBO_VP_mats> vp_mats_modelPipeline;
       VulkanBuffer<SSBO_ModelObject> objects_modelPipeline;
-      BufferSet uniformBuffers_modelPipeline;
-
+
+      BufferSet uniformBuffers_shipPipeline;
       BufferSet storageBuffers_shipPipeline;
+
+      VulkanBuffer<UBO_VP_mats> vp_mats_shipPipeline;
       VulkanBuffer<SSBO_ModelObject> objects_shipPipeline;
-      BufferSet uniformBuffers_shipPipeline;
-
+
+      BufferSet uniformBuffers_asteroidPipeline;
       BufferSet storageBuffers_asteroidPipeline;
+
+      VulkanBuffer<UBO_VP_mats> vp_mats_asteroidPipeline;
       VulkanBuffer<SSBO_Asteroid> objects_asteroidPipeline;
-      BufferSet uniformBuffers_asteroidPipeline;
-
+
+      BufferSet uniformBuffers_laserPipeline;
       BufferSet storageBuffers_laserPipeline;
+
+      VulkanBuffer<UBO_VP_mats> vp_mats_laserPipeline;
       VulkanBuffer<SSBO_Laser> objects_laserPipeline;
-      BufferSet uniformBuffers_laserPipeline;
-
+
+      BufferSet uniformBuffers_explosionPipeline;
       BufferSet storageBuffers_explosionPipeline;
+
+      VulkanBuffer<UBO_Explosion> uniforms_explosionPipeline;
       VulkanBuffer<SSBO_Explosion> objects_explosionPipeline;
-      BufferSet uniformBuffers_explosionPipeline;
 
       // TODO: Maybe make the ubo objects part of the pipeline class since there's only one ubo
@@ -340,22 +350,10 @@
 
       vector<SceneObject<ModelVertex>> modelObjects;
-
-      UBO_VP_mats object_VP_mats;
-
       vector<SceneObject<ModelVertex>> shipObjects;
-
-      UBO_VP_mats ship_VP_mats;
-
       vector<SceneObject<ModelVertex>> asteroidObjects;
-
-      UBO_VP_mats asteroid_VP_mats;
-
       vector<SceneObject<LaserVertex>> laserObjects;
-
-      UBO_VP_mats laser_VP_mats;
-
       vector<SceneObject<ExplosionVertex>> explosionObjects;
 
-      UBO_Explosion explosion_UBO;
+      //UBO_Explosion explosion_UBO;
 
       vector<BaseEffectOverTime*> effects;
