Changeset 6486ba8 in opengl-game


Ignore:
Timestamp:
Jun 11, 2021, 8:12:29 PM (3 years ago)
Author:
Dmitry Portnoy <dportnoy@…>
Branches:
feature/imgui-sdl
Children:
5ea0a37
Parents:
c1ec4f6
Message:

Rewrite some parts of SDLGame and VulkanGame to store per-object buffer object
data contiguously and copied to the GPU in one call

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • sdl-game.cpp

    rc1ec4f6 r6486ba8  
    111111
    112112   createBufferSet(sizeof(UBO_VP_mats),
    113       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    114       uniformBuffers_modelPipeline);
     113                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     114                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     115                   uniformBuffers_modelPipeline);
     116
     117   createBufferSet(objects_modelPipeline.capacity * sizeof(SSBO_ModelObject),
     118                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     119                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     120                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     121                   storageBuffers_modelPipeline);
    115122
    116123   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    121128      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
    122129
    123    SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr;
     130   SceneObject<ModelVertex>* texturedSquare = nullptr;
    124131
    125132   texturedSquare = &addObject(modelObjects, modelPipeline,
    126133      addObjectIndex<ModelVertex>(modelObjects.size(),
    127134         addVertexNormals<ModelVertex>({
    128             {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0},
    129             {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0},
    130             {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    131             {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    132             {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    133             {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}
     135            {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
     136            {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     137            {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     138            {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     139            {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
     140            {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
    134141         })),
    135142      {
     
    264271      VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
    265272      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 16, 24);
    266 
    267    createBufferSet(objects_modelPipeline.capacity * sizeof(SSBO_ModelObject),
    268                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    269                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    270                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    271                    storageBuffers_modelPipeline);
    272273}
    273274
     
    362363                  float zOffset = -2.0f + (0.5f * modelObjects.size());
    363364
    364                   SceneObject<ModelVertex, SSBO_ModelObject>& texturedSquare =
    365                      addObject(modelObjects, modelPipeline,
    366                         addObjectIndex<ModelVertex>(modelObjects.size(),
    367                            addVertexNormals<ModelVertex>({
    368                               {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0},
    369                               {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0},
    370                               {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    371                               {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    372                               {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0},
    373                               {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}
    374                            })),
    375                         {
    376                            0, 1, 2, 3, 4, 5
    377                         }, objects_modelPipeline, {
    378                            mat4(1.0f)
    379                         });
     365                  SceneObject<ModelVertex>& texturedSquare = addObject(modelObjects, modelPipeline,
     366                     addObjectIndex<ModelVertex>(modelObjects.size(),
     367                        addVertexNormals<ModelVertex>({
     368                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
     369                           {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     370                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     371                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     372                           {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
     373                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
     374                        })),
     375                     {
     376                        0, 1, 2, 3, 4, 5
     377                     }, objects_modelPipeline, {
     378                        mat4(1.0f)
     379                     });
    380380
    381381                  texturedSquare.model_base =
     
    455455
    456456   for (size_t i = 0; i < modelObjects.size(); i++) {
    457       SceneObject<ModelVertex, SSBO_ModelObject>& obj = modelObjects[i];
    458       SSBO_ModelObject& objData = obj.ssbo;
     457      SceneObject<ModelVertex>& obj = modelObjects[i];
     458      SSBO_ModelObject& objData = objects_modelPipeline.get(i);
    459459
    460460      // Rotate the textured squares
     
    488488
    489489   modelPipeline.cleanupBuffers();
    490 
    491    for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
    492       vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
    493       vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
    494    }
    495490
    496491   // END UNREVIEWED SECTION
     
    12791274   createSyncObjects();
    12801275
    1281    // TODO: Move UBO creation/management into GraphicsPipeline_Vulkan, like I did with SSBOs
    1282    // TODO: Check if the shader stages and maybe some other properties of the pipeline can be re-used
    1283    // instead of recreated every time
    1284 
    12851276   createBufferSet(sizeof(UBO_VP_mats),
    1286       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    1287       uniformBuffers_modelPipeline);
     1277                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     1278                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     1279                   uniformBuffers_modelPipeline);
     1280
     1281   createBufferSet(objects_modelPipeline.memorySize(),
     1282                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     1283                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     1284                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     1285                   storageBuffers_modelPipeline);
    12881286
    12891287   modelPipeline.updateRenderPass(renderPass);
     
    13121310      vkDestroyBuffer(device, uniformBuffers_modelPipeline.buffers[i], nullptr);
    13131311      vkFreeMemory(device, uniformBuffers_modelPipeline.memory[i], nullptr);
     1312   }
     1313
     1314   for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
     1315      vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
     1316      vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
    13141317   }
    13151318
  • sdl-game.hpp

    rc1ec4f6 r6486ba8  
    9393// TODO: Create a typedef for index type so I can easily change uin16_t to something else later
    9494// TODO: Maybe create a typedef for each of the templated SceneObject types
    95 template<class VertexType, class SSBOType>
     95template<class VertexType>
    9696struct SceneObject {
    9797   vector<VertexType> vertices;
    9898   vector<uint16_t> indices;
    99    SSBOType ssbo;
    10099
    101100   mat4 model_base;
     
    109108   // Move the targetAsteroid stuff out of this class since it is very specific to lasers
    110109   // and makes moving SceneObject into its own header file more problematic
    111    SceneObject<ModelVertex, SSBO_Asteroid>* targetAsteroid; // currently only used for lasers
    112 };
    113 
    114 // TODO: Have to figure out how to include an optional ssbo parameter for each object
     110   SceneObject<ModelVertex>* targetAsteroid; // currently only used for lasers
     111};
     112
     113// TODO: Figure out how to include an optional ssbo parameter for each object
    115114// Could probably use the same approach to make indices optional
    116115// Figure out if there are sufficient use cases to make either of these optional or is it fine to make
     
    238237      // if there is a need to add other uniform variables to one or more of the shaders
    239238
    240       vector<SceneObject<ModelVertex, SSBO_ModelObject>> modelObjects;
     239      vector<SceneObject<ModelVertex>> modelObjects;
    241240
    242241      UBO_VP_mats object_VP_mats;
     
    307306      // stop using objects.back() to access the object that was just created
    308307      template<class VertexType, class SSBOType>
    309       SceneObject<VertexType, SSBOType>& addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
    310                                                    GraphicsPipeline_Vulkan<VertexType>& pipeline,
    311                                                    const vector<VertexType>& vertices, vector<uint16_t> indices,
    312                                                    VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo);
     308      SceneObject<VertexType>& addObject(vector<SceneObject<VertexType>>& objects,
     309                                         GraphicsPipeline_Vulkan<VertexType>& pipeline,
     310                                         const vector<VertexType>& vertices, vector<uint16_t> indices,
     311                                         VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo);
    313312
    314313      template<class VertexType>
     
    318317      vector<VertexType> addVertexNormals(vector<VertexType> vertices);
    319318
    320       template<class VertexType, class SSBOType>
    321       void centerObject(SceneObject<VertexType, SSBOType>& object);
     319      template<class VertexType>
     320      void centerObject(SceneObject<VertexType>& object);
    322321
    323322      void renderFrame(ImDrawData* draw_data);
     
    352351// Figure out a better way to allow the model matrix to be set during object creation
    353352template<class VertexType, class SSBOType>
    354 SceneObject<VertexType, SSBOType>& VulkanGame::addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
    355                                                          GraphicsPipeline_Vulkan<VertexType>& pipeline,
    356                                                          const vector<VertexType>& vertices, vector<uint16_t> indices,
    357                                                          VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo) {
     353SceneObject<VertexType>& VulkanGame::addObject(vector<SceneObject<VertexType>>& objects,
     354                                               GraphicsPipeline_Vulkan<VertexType>& pipeline,
     355                                               const vector<VertexType>& vertices, vector<uint16_t> indices,
     356                                               VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo) {
    358357   // TODO: Use the model field of ssbo to set the object's model_base
    359358   // currently, the passed-in model is useless since it gets overridden when ssbo.model is recalculated
     
    364363   }
    365364
    366    objects.push_back({ vertices, indices, ssbo, mat4(1.0f), mat4(1.0f) });
     365   objects.push_back({ vertices, indices, mat4(1.0f), mat4(1.0f) });
    367366   objectBuffer.add(ssbo);
    368367
    369    SceneObject<VertexType, SSBOType>& obj = objects.back();
     368   SceneObject<VertexType>& obj = objects.back();
    370369
    371370   // TODO: Specify whether to center the object outside of this function or, worst case, maybe
     
    410409}
    411410
    412 template<class VertexType, class SSBOType>
    413 void VulkanGame::centerObject(SceneObject<VertexType, SSBOType>& object) {
     411template<class VertexType>
     412void VulkanGame::centerObject(SceneObject<VertexType>& object) {
    414413   vector<VertexType>& vertices = object.vertices;
    415414
  • vulkan-buffer.hpp

    rc1ec4f6 r6486ba8  
    3333      void resize();
    3434
     35      T& get(uint32_t index);
    3536      void add(T obj);
    3637
     
    4142      size_t alignment;
    4243      size_t range;
     44      //size_t capacity;
    4345      size_t numObjects;
    4446
    45       T* srcData; // TODO: Rename this to something else probably and rename rawData to data
    46       vector<T>* vData;
    47 
    48       // Remember that this is a pointer to the mapped video memory
    49       // Maybe rename it to mappedData or something to make that clearer
    50       void* rawData;
     47      T* rawData;
     48      vector<void*> mappedData;
    5149
    5250      size_t memRequirement(size_t capacity);
     51      size_t memOffset(uint32_t index);
    5352};
    5453
     
    7372                              , numObjects(0)
    7473                              , resized(false)
    75                               , srcData(nullptr)
    7674                              , rawData(nullptr)
    77                               , vData(nullptr) {
     75                              , mappedData() {
    7876}
    7977
     
    8583                              , numObjects(0)
    8684                              , resized(false)
    87                               , srcData(nullptr)
    8885                              , rawData(nullptr)
    89                               , vData(nullptr) {
     86                              , mappedData() {
    9087   if (minOffsetAlignment > 0) {
    9188      alignment = (alignment + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1);
    9289   }
    9390
    94    srcData = (T*)malloc(memRequirement(capacity));
     91   rawData = (T*)malloc(memRequirement(capacity));
    9592}
    9693
     
    10299template<class T>
    103100VulkanBuffer<T>::~VulkanBuffer() {
    104    if (srcData != nullptr) {
    105       free(srcData);
     101   if (rawData != nullptr) {
     102      free(rawData);
    106103   }
    107104}
     
    117114      range = other.range;
    118115
    119       if (srcData != nullptr) {
    120          free(srcData);
     116      if (rawData != nullptr) {
     117         free(rawData);
    121118      }
    122119
    123       srcData = other.srcData;
     120      rawData = other.rawData;
    124121
    125122      other.capacity = 0;
     
    127124      other.range = 0;
    128125
    129       other.srcData = nullptr;
     126      other.rawData = nullptr;
    130127   }
    131128
     
    139136
    140137template<class T>
     138T& VulkanBuffer<T>::get(uint32_t index) {
     139   // TODO: Check that index < numObjects
     140
     141   T* obj = (T*)((size_t)rawData + memOffset(index));
     142   return *obj;
     143}
     144
     145template<class T>
    141146void VulkanBuffer<T>::add(T obj) {
    142147   if (numObjects == capacity) {
     
    144149      resized = true;
    145150
     151      size_t oldMemReq = memRequirement(capacity);
     152
    146153      capacity *= 2;
     154
     155      size_t newMemReq = memRequirement(capacity);
     156
     157      T* newData = (T*)malloc(newMemReq);
     158      // TODO: Check for failure
     159
     160      memcpy(newData, rawData, oldMemReq);
     161
     162      free(rawData);
     163      rawData = newData;
    147164   }
     165
     166   T* ptr = (T*)((size_t)rawData + memOffset(numObjects));
     167   *ptr = obj;
    148168
    149169   numObjects++;
     
    160180}
    161181
     182template<class T>
     183size_t VulkanBuffer<T>::memOffset(uint32_t index) {
     184   return (index / range) * alignment + (index % range) * sizeof(T);
     185}
     186
    162187#endif // _VULKAN_BUFFER_H
  • vulkan-game.cpp

    rc1ec4f6 r6486ba8  
    139139
    140140   createBufferSet(sizeof(UBO_VP_mats),
    141       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    142       uniformBuffers_modelPipeline);
     141                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     142                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     143                   uniformBuffers_modelPipeline);
     144
     145   createBufferSet(objects_modelPipeline.memorySize(),
     146                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     147                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     148                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     149                   storageBuffers_modelPipeline);
    143150
    144151   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    149156      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
    150157
    151    SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr;
     158   SceneObject<ModelVertex>* texturedSquare = nullptr;
    152159
    153160   texturedSquare = &addObject(modelObjects, modelPipeline,
     
    202209
    203210   createBufferSet(sizeof(UBO_VP_mats),
    204       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    205       uniformBuffers_shipPipeline);
     211                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     212                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     213                   uniformBuffers_shipPipeline);
     214
     215   createBufferSet(objects_shipPipeline.memorySize(),
     216                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     217                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     218                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     219                   storageBuffers_shipPipeline);
    206220
    207221   shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    212226   // TODO: With the normals, indexing basically becomes pointless since no vertices will have exactly
    213227   // the same data. Add an option to make some pipelines not use indexing
    214    SceneObject<ModelVertex, SSBO_ModelObject>& ship = addObject(shipObjects, shipPipeline,
     228   SceneObject<ModelVertex>& ship = addObject(shipObjects, shipPipeline,
    215229      addObjectIndex<ModelVertex>(shipObjects.size(),
    216230         addVertexNormals<ModelVertex>({
     
    462476
    463477   createBufferSet(sizeof(UBO_VP_mats),
    464       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    465       uniformBuffers_asteroidPipeline);
     478                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     479                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     480                   uniformBuffers_asteroidPipeline);
     481
     482   createBufferSet(objects_asteroidPipeline.memorySize(),
     483                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     484                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     485                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     486                   storageBuffers_asteroidPipeline);
    466487
    467488   asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    480501
    481502   createBufferSet(sizeof(UBO_VP_mats),
    482       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    483       uniformBuffers_laserPipeline);
     503                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     504                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     505                   uniformBuffers_laserPipeline);
     506
     507   createBufferSet(objects_laserPipeline.memorySize(),
     508                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     509                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     510                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     511                   storageBuffers_laserPipeline);
    484512
    485513   laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    500528
    501529   createBufferSet(sizeof(UBO_Explosion),
    502       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    503       uniformBuffers_explosionPipeline);
     530                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     531                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     532                   uniformBuffers_explosionPipeline);
     533
     534   createBufferSet(objects_explosionPipeline.memorySize(),
     535                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     536                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     537                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     538                   storageBuffers_explosionPipeline);
    504539
    505540   explosionPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     
    615650      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 24, 24);
    616651
    617    createBufferSet(objects_modelPipeline.capacity * sizeof(SSBO_ModelObject),
    618                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    619                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    620                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    621                    storageBuffers_modelPipeline);
    622 
    623652   shipPipeline = GraphicsPipeline_Vulkan<ModelVertex>(
    624653      VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
    625654      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 138, 138);
    626655
    627    createBufferSet(objects_shipPipeline.capacity * sizeof(SSBO_ModelObject),
    628                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    629                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    630                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    631                    storageBuffers_shipPipeline);
    632 
    633656   asteroidPipeline = GraphicsPipeline_Vulkan<ModelVertex>(
    634657      VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
    635658      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 24, 36);
    636659
    637    createBufferSet(objects_asteroidPipeline.capacity * sizeof(SSBO_Asteroid),
    638                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    639                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    640                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    641                    storageBuffers_asteroidPipeline);
    642 
    643660   laserPipeline = GraphicsPipeline_Vulkan<LaserVertex>(
    644661      VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass,
    645662      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 8, 18);
    646 
    647    createBufferSet(objects_laserPipeline.capacity * sizeof(SSBO_Laser),
    648                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    649                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    650                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    651                    storageBuffers_laserPipeline);
    652663
    653664   explosionPipeline = GraphicsPipeline_Vulkan<ExplosionVertex>(
     
    655666      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height },
    656667      EXPLOSION_PARTICLE_COUNT, EXPLOSION_PARTICLE_COUNT);
    657 
    658    createBufferSet(objects_explosionPipeline.capacity * sizeof(SSBO_Explosion),
    659                    VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
    660                    | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
    661                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    662                    storageBuffers_explosionPipeline);
    663668}
    664669
     
    767772                  float zOffset = -2.0f + (0.5f * modelObjects.size());
    768773
    769                   SceneObject<ModelVertex, SSBO_ModelObject>& texturedSquare =
    770                      addObject(modelObjects, modelPipeline,
    771                         addObjectIndex<ModelVertex>(modelObjects.size(),
    772                            addVertexNormals<ModelVertex>({
    773                               {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
    774                               {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
    775                               {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
    776                               {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
    777                               {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
    778                               {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
    779                            })),
    780                         {
    781                            0, 1, 2, 3, 4, 5
    782                         }, objects_modelPipeline, {
    783                            mat4(1.0f)
    784                         });
     774                  SceneObject<ModelVertex>& texturedSquare = addObject(modelObjects, modelPipeline,
     775                     addObjectIndex<ModelVertex>(modelObjects.size(),
     776                        addVertexNormals<ModelVertex>({
     777                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
     778                           {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     779                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     780                           {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     781                           {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
     782                           {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}
     783                        })),
     784                     {
     785                        0, 1, 2, 3, 4, 5
     786                     }, objects_modelPipeline, {
     787                        mat4(1.0f)
     788                     });
    785789
    786790                  texturedSquare.model_base =
     
    817821               // START UNREVIEWED SECTION
    818822               if (e.key.keycode == SDL_SCANCODE_Z && leftLaserIdx != -1) {
    819                   laserObjects[leftLaserIdx].ssbo.deleted = true;
     823                  objects_laserPipeline.get(leftLaserIdx).deleted = true;
    820824                  leftLaserIdx = -1;
    821825
     
    825829                  }
    826830               } else if (e.key.keycode == SDL_SCANCODE_X && rightLaserIdx != -1) {
    827                   laserObjects[rightLaserIdx].ssbo.deleted = true;
     831                  objects_laserPipeline.get(rightLaserIdx).deleted = true;
    828832                  rightLaserIdx = -1;
    829833
     
    857861      // Check which keys are held down
    858862
    859       SceneObject<ModelVertex, SSBO_ModelObject>& ship = shipObjects[0];
     863      SceneObject<ModelVertex>& ship = shipObjects[0];
    860864
    861865      if (gui->keyPressed(SDL_SCANCODE_LEFT)) {
     
    936940// where it will run just once per frame
    937941void VulkanGame::updateScene() {
    938    if (curTime - this->lastSpawn_asteroid > this->spawnRate_asteroid) {
    939       this->lastSpawn_asteroid = curTime;
    940 
    941       SceneObject<ModelVertex, SSBO_Asteroid>& asteroid =
    942          addObject(asteroidObjects, asteroidPipeline,
    943             addObjectIndex<ModelVertex>(asteroidObjects.size(),
    944                addVertexNormals<ModelVertex>({
    945 
    946                   // front
    947                   {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    948                   {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    949                   {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    950                   {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    951                   {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    952                   {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    953 
    954                   // top
    955                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    956                   {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    957                   {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    958                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    959                   {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    960                   {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    961 
    962                   // bottom
    963                   {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    964                   {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    965                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    966                   {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    967                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    968                   {{ 1.0f, -1.0f, -1.0}, {0.4f, 0.4f, 0.4f}},
    969 
    970                   // back
    971                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    972                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    973                   {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    974                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    975                   {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    976                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    977 
    978                   // right
    979                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    980                   {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    981                   {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    982                   {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    983                   {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    984                   {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    985 
    986                   // left
    987                   {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    988                   {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    989                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    990                   {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    991                   {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
    992                   {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
    993                })),
    994             {
    995                 0,  1,  2,  3,  4,  5,
    996                 6,  7,  8,  9, 10, 11,
    997                12, 13, 14, 15, 16, 17,
    998                18, 19, 20, 21, 22, 23,
    999                24, 25, 26, 27, 28, 29,
    1000                30, 31, 32, 33, 34, 35,
    1001             }, objects_asteroidPipeline, {
    1002                mat4(1.0f),
    1003                10.0f,
    1004                false
    1005             });
     942   if (curTime - lastSpawn_asteroid > spawnRate_asteroid) {
     943      lastSpawn_asteroid = curTime;
     944
     945      SceneObject<ModelVertex>& asteroid = addObject(asteroidObjects, asteroidPipeline,
     946         addObjectIndex<ModelVertex>(asteroidObjects.size(),
     947            addVertexNormals<ModelVertex>({
     948
     949               // front
     950               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     951               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     952               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     953               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     954               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     955               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     956
     957               // top
     958               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     959               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     960               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     961               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     962               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     963               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     964
     965               // bottom
     966               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     967               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     968               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     969               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     970               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     971               {{ 1.0f, -1.0f, -1.0}, {0.4f, 0.4f, 0.4f}},
     972
     973               // back
     974               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     975               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     976               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     977               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     978               {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     979               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     980
     981               // right
     982               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     983               {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     984               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     985               {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     986               {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     987               {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     988
     989               // left
     990               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     991               {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     992               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     993               {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     994               {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
     995               {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
     996            })),
     997         {
     998             0,  1,  2,  3,  4,  5,
     999             6,  7,  8,  9, 10, 11,
     1000            12, 13, 14, 15, 16, 17,
     1001            18, 19, 20, 21, 22, 23,
     1002            24, 25, 26, 27, 28, 29,
     1003            30, 31, 32, 33, 34, 35,
     1004         }, objects_asteroidPipeline, {
     1005            mat4(1.0f),
     1006            10.0f,
     1007            false
     1008         });
    10061009
    10071010      // This accounts for the scaling in model_base.
     
    10331036
    10341037   for (size_t i = 0; i < modelObjects.size(); i++) {
    1035       SceneObject<ModelVertex, SSBO_ModelObject>& obj = modelObjects[i];
    1036       SSBO_ModelObject& objData = obj.ssbo;
     1038      SceneObject<ModelVertex>& obj = modelObjects[i];
     1039      SSBO_ModelObject& objData = objects_modelPipeline.get(i);
    10371040
    10381041      // Rotate the textured squares
     
    10581061   // TODO: Move ship position updates from the ui event handling code into this function
    10591062   for (size_t i = 0; i < shipObjects.size(); i++) {
    1060       SceneObject<ModelVertex, SSBO_ModelObject>& obj = shipObjects[i];
    1061       SSBO_ModelObject& objData = obj.ssbo;
     1063      SceneObject<ModelVertex>& obj = shipObjects[i];
     1064      SSBO_ModelObject& objData = objects_shipPipeline.get(i);
    10621065
    10631066      objData.model = obj.model_transform * obj.model_base;
     
    10771080
    10781081   for (size_t i = 0; i < asteroidObjects.size(); i++) {
    1079       SceneObject<ModelVertex, SSBO_Asteroid>& obj = asteroidObjects[i];
    1080       SSBO_Asteroid& objData = obj.ssbo;
     1082      SceneObject<ModelVertex>& obj = asteroidObjects[i];
     1083      SSBO_Asteroid& objData = objects_asteroidPipeline.get(i);
    10811084
    10821085      if (!objData.deleted) {
     
    11271130
    11281131   for (size_t i = 0; i < laserObjects.size(); i++) {
    1129       SceneObject<LaserVertex, SSBO_Laser>& obj = laserObjects[i];
    1130       SSBO_Laser& objData = obj.ssbo;
     1132      SceneObject<LaserVertex>& obj = laserObjects[i];
     1133      SSBO_Laser& objData = objects_laserPipeline.get(i);
    11311134
    11321135      objData.model = obj.model_transform * obj.model_base;
     
    11461149
    11471150   for (size_t i = 0; i < explosionObjects.size(); i++) {
    1148       SceneObject<ExplosionVertex, SSBO_Explosion>& obj = explosionObjects[i];
    1149       SSBO_Explosion& objData = obj.ssbo;
     1151      SceneObject<ExplosionVertex>& obj = explosionObjects[i];
     1152      SSBO_Explosion& objData = objects_explosionPipeline.get(i);
    11501153
    11511154      if (!objData.deleted) {
     
    12121215   laserPipeline.cleanupBuffers();
    12131216   explosionPipeline.cleanupBuffers();
    1214 
    1215    for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
    1216       vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
    1217       vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
    1218    }
    1219 
    1220    for (size_t i = 0; i < storageBuffers_shipPipeline.buffers.size(); i++) {
    1221       vkDestroyBuffer(device, storageBuffers_shipPipeline.buffers[i], nullptr);
    1222       vkFreeMemory(device, storageBuffers_shipPipeline.memory[i], nullptr);
    1223    }
    1224 
    1225    for (size_t i = 0; i < storageBuffers_asteroidPipeline.buffers.size(); i++) {
    1226       vkDestroyBuffer(device, storageBuffers_asteroidPipeline.buffers[i], nullptr);
    1227       vkFreeMemory(device, storageBuffers_asteroidPipeline.memory[i], nullptr);
    1228    }
    1229 
    1230    for (size_t i = 0; i < storageBuffers_laserPipeline.buffers.size(); i++) {
    1231       vkDestroyBuffer(device, storageBuffers_laserPipeline.buffers[i], nullptr);
    1232       vkFreeMemory(device, storageBuffers_laserPipeline.memory[i], nullptr);
    1233    }
    1234 
    1235    for (size_t i = 0; i < storageBuffers_explosionPipeline.buffers.size(); i++) {
    1236       vkDestroyBuffer(device, storageBuffers_explosionPipeline.buffers[i], nullptr);
    1237       vkFreeMemory(device, storageBuffers_explosionPipeline.memory[i], nullptr);
    1238    }
    12391217
    12401218   // END UNREVIEWED SECTION
     
    20041982   float length = glm::length(ray);
    20051983
    2006    SceneObject<LaserVertex, SSBO_Laser>& laser = addObject(
    2007       laserObjects, laserPipeline,
     1984   SceneObject<LaserVertex>& laser = addObject(laserObjects, laserPipeline,
    20081985      addObjectIndex<LaserVertex>(laserObjects.size(), {
    20091986         {{ width / 2, 0.0f, -width / 2         }, {1.0f, 0.5f }},
     
    20512028
    20522029void VulkanGame::translateLaser(size_t index, const vec3& translation) {
    2053    SceneObject<LaserVertex, SSBO_Laser>& laser = this->laserObjects[index];
     2030   SceneObject<LaserVertex>& laser = laserObjects[index];
    20542031
    20552032   // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
     
    20812058
    20822059void VulkanGame::updateLaserTarget(size_t index) {
    2083    SceneObject<LaserVertex, SSBO_Laser>& laser = this->laserObjects[index];
     2060   SceneObject<LaserVertex>& laser = laserObjects[index];
    20842061
    20852062   // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
     
    20902067
    20912068   vec3 intersection(0.0f), closestIntersection(0.0f);
    2092    SceneObject<ModelVertex, SSBO_Asteroid>* closestAsteroid = nullptr;
     2069   SceneObject<ModelVertex>* closestAsteroid = nullptr;
    20932070   unsigned int closestAsteroidIndex = -1;
    20942071
    2095    for (int i = 0; i < this->asteroidObjects.size(); i++) {
    2096       if (!this->asteroidObjects[i].ssbo.deleted &&
    2097             this->getLaserAndAsteroidIntersection(this->asteroidObjects[i], start, end, intersection)) {
     2072   for (int i = 0; i < asteroidObjects.size(); i++) {
     2073      if (!objects_asteroidPipeline.get(i).deleted &&
     2074          getLaserAndAsteroidIntersection(asteroidObjects[i], start, end, intersection)) {
    20982075         // TODO: Implement a more generic algorithm for testing the closest object by getting the distance between the points
    20992076         // TODO: Also check which intersection is close to the start of the laser. This would make the algorithm work
     
    21192096      }
    21202097
    2121       EffectOverTime<ModelVertex, SSBO_Asteroid>* eot = nullptr;
     2098      EffectOverTime<SSBO_Asteroid>* eot = nullptr;
    21222099
    21232100      if (closestAsteroid != nullptr) {
    2124          // TODO: Use some sort of smart pointer instead
    2125          eot = new EffectOverTime<ModelVertex, SSBO_Asteroid>(asteroidPipeline, asteroidObjects, closestAsteroidIndex,
    2126             offset_of(&SSBO_Asteroid::hp), curTime, -20.0f);
     2101         // TODO: Figure out if I should use a smart pointer instead
     2102         eot = new EffectOverTime(objects_asteroidPipeline, closestAsteroidIndex, offset_of(&SSBO_Asteroid::hp),
     2103                                  curTime, -20.0f);
    21272104         effects.push_back(eot);
    21282105      }
     
    21462123
    21472124   // TODO: Consider if I want to set a flag and do this update in updateScene() instead
    2148    updateObjectVertices(this->laserPipeline, laser, index);
     2125   updateObjectVertices(laserPipeline, laser, index);
    21492126}
    21502127
    21512128// TODO: Determine if I should pass start and end by reference or value since they don't get changed
    21522129// Probably use const reference
    2153 bool VulkanGame::getLaserAndAsteroidIntersection(SceneObject<ModelVertex, SSBO_Asteroid>& asteroid,
    2154       vec3& start, vec3& end, vec3& intersection) {
     2130bool VulkanGame::getLaserAndAsteroidIntersection(SceneObject<ModelVertex>& asteroid, vec3& start, vec3& end,
     2131                                                vec3& intersection) {
    21552132   /*
    21562133   ### LINE EQUATIONS ###
     
    22212198   iota(indices.begin(), indices.end(), 0);
    22222199
    2223    SceneObject<ExplosionVertex, SSBO_Explosion>& explosion = addObject(explosionObjects, explosionPipeline,
     2200   SceneObject<ExplosionVertex>& explosion = addObject(explosionObjects, explosionPipeline,
    22242201      addObjectIndex(explosionObjects.size(), vertices), indices, objects_explosionPipeline, {
    22252202         mat4(1.0f),
     
    22542231   createSyncObjects();
    22552232
    2256    // TODO: Move UBO creation/management into GraphicsPipeline_Vulkan, like I did with SSBOs
    2257    // TODO: Check if the shader stages and maybe some other properties of the pipeline can be re-used
    2258    // instead of recreated every time
    2259 
    22602233   createBufferSet(sizeof(UBO_VP_mats),
    2261       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    2262       uniformBuffers_modelPipeline);
     2234                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     2235                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2236                   uniformBuffers_modelPipeline);
     2237
     2238   createBufferSet(objects_modelPipeline.memorySize(),
     2239                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     2240                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     2241                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2242                   storageBuffers_modelPipeline);
    22632243
    22642244   modelPipeline.updateRenderPass(renderPass);
     
    22682248
    22692249   createBufferSet(sizeof(UBO_VP_mats),
    2270       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    2271       uniformBuffers_shipPipeline);
     2250                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     2251                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2252                   uniformBuffers_shipPipeline);
     2253
     2254   createBufferSet(objects_shipPipeline.memorySize(),
     2255                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     2256                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     2257                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2258                   storageBuffers_shipPipeline);
    22722259
    22732260   shipPipeline.updateRenderPass(renderPass);
     
    22772264
    22782265   createBufferSet(sizeof(UBO_VP_mats),
    2279       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    2280       uniformBuffers_asteroidPipeline);
     2266                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     2267                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2268                   uniformBuffers_asteroidPipeline);
     2269
     2270   createBufferSet(objects_asteroidPipeline.memorySize(),
     2271                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     2272                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     2273                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2274                   storageBuffers_asteroidPipeline);
    22812275
    22822276   asteroidPipeline.updateRenderPass(renderPass);
     
    22862280
    22872281   createBufferSet(sizeof(UBO_VP_mats),
    2288       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    2289       uniformBuffers_laserPipeline);
     2282                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     2283                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2284                   uniformBuffers_laserPipeline);
     2285
     2286   createBufferSet(objects_laserPipeline.memorySize(),
     2287                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     2288                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     2289                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2290                   storageBuffers_laserPipeline);
    22902291
    22912292   laserPipeline.updateRenderPass(renderPass);
     
    22952296
    22962297   createBufferSet(sizeof(UBO_Explosion),
    2297       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
    2298       uniformBuffers_explosionPipeline);
     2298                   VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     2299                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2300                   uniformBuffers_explosionPipeline);
     2301
     2302   createBufferSet(objects_explosionPipeline.memorySize(),
     2303                   VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
     2304                   | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
     2305                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     2306                   storageBuffers_explosionPipeline);
    22992307
    23002308   explosionPipeline.updateRenderPass(renderPass);
     
    23292337   }
    23302338
     2339   for (size_t i = 0; i < storageBuffers_modelPipeline.buffers.size(); i++) {
     2340      vkDestroyBuffer(device, storageBuffers_modelPipeline.buffers[i], nullptr);
     2341      vkFreeMemory(device, storageBuffers_modelPipeline.memory[i], nullptr);
     2342   }
     2343
    23312344   for (size_t i = 0; i < uniformBuffers_shipPipeline.buffers.size(); i++) {
    23322345      vkDestroyBuffer(device, uniformBuffers_shipPipeline.buffers[i], nullptr);
     
    23342347   }
    23352348
     2349   for (size_t i = 0; i < storageBuffers_shipPipeline.buffers.size(); i++) {
     2350      vkDestroyBuffer(device, storageBuffers_shipPipeline.buffers[i], nullptr);
     2351      vkFreeMemory(device, storageBuffers_shipPipeline.memory[i], nullptr);
     2352   }
     2353
    23362354   for (size_t i = 0; i < uniformBuffers_asteroidPipeline.buffers.size(); i++) {
    23372355      vkDestroyBuffer(device, uniformBuffers_asteroidPipeline.buffers[i], nullptr);
     
    23392357   }
    23402358
     2359   for (size_t i = 0; i < storageBuffers_asteroidPipeline.buffers.size(); i++) {
     2360      vkDestroyBuffer(device, storageBuffers_asteroidPipeline.buffers[i], nullptr);
     2361      vkFreeMemory(device, storageBuffers_asteroidPipeline.memory[i], nullptr);
     2362   }
     2363
    23412364   for (size_t i = 0; i < uniformBuffers_laserPipeline.buffers.size(); i++) {
    23422365      vkDestroyBuffer(device, uniformBuffers_laserPipeline.buffers[i], nullptr);
     
    23442367   }
    23452368
     2369   for (size_t i = 0; i < storageBuffers_laserPipeline.buffers.size(); i++) {
     2370      vkDestroyBuffer(device, storageBuffers_laserPipeline.buffers[i], nullptr);
     2371      vkFreeMemory(device, storageBuffers_laserPipeline.memory[i], nullptr);
     2372   }
     2373
    23462374   for (size_t i = 0; i < uniformBuffers_explosionPipeline.buffers.size(); i++) {
    23472375      vkDestroyBuffer(device, uniformBuffers_explosionPipeline.buffers[i], nullptr);
    23482376      vkFreeMemory(device, uniformBuffers_explosionPipeline.memory[i], nullptr);
     2377   }
     2378
     2379   for (size_t i = 0; i < storageBuffers_explosionPipeline.buffers.size(); i++) {
     2380      vkDestroyBuffer(device, storageBuffers_explosionPipeline.buffers[i], nullptr);
     2381      vkFreeMemory(device, storageBuffers_explosionPipeline.memory[i], nullptr);
    23492382   }
    23502383
  • vulkan-game.hpp

    rc1ec4f6 r6486ba8  
    109109// TODO: Create a typedef for index type so I can easily change uin16_t to something else later
    110110// TODO: Maybe create a typedef for each of the templated SceneObject types
    111 template<class VertexType, class SSBOType>
     111template<class VertexType>
    112112struct SceneObject {
    113113   vector<VertexType> vertices;
    114114   vector<uint16_t> indices;
    115    SSBOType ssbo;
    116115
    117116   mat4 model_base;
     
    125124   // Move the targetAsteroid stuff out of this class since it is very specific to lasers
    126125   // and makes moving SceneObject into its own header file more problematic
    127    SceneObject<ModelVertex, SSBO_Asteroid>* targetAsteroid; // currently only used for lasers
    128 };
    129 
    130 // TODO: Have to figure out how to include an optional ssbo parameter for each object
     126   SceneObject<ModelVertex>* targetAsteroid; // currently only used for lasers
     127};
     128
     129// TODO: Figure out how to include an optional ssbo parameter for each object
    131130// Could probably use the same approach to make indices optional
    132131// Figure out if there are sufficient use cases to make either of these optional or is it fine to make
     
    149148};
    150149
    151 template<class VertexType, class SSBOType>
     150// TODO: Move this into its own hpp and cpp files
     151// TODO: Actually, since this is only used to make lasers deal damage to asteroids, review the logic
     152// and see if there is a more straightforward way of implementing this.
     153// If there is a simple and straightforward way to implement this in updateScene(), I should just do that instead of
     154// using this class. A general feature like this is useful, but, depending on the actual game, it might not be used
     155// that often, and using this class might actually make things more complicated if it doesn't quite implement the
     156// desired features
     157template<class SSBOType>
    152158struct EffectOverTime : public BaseEffectOverTime {
    153    GraphicsPipeline_Vulkan<VertexType>& pipeline;
    154    vector<SceneObject<VertexType, SSBOType>>& objects;
    155    unsigned int objectIndex;
     159   VulkanBuffer<SSBOType> &buffer;
     160   uint32_t objectIndex;
    156161   size_t effectedFieldOffset;
    157162   float startValue;
     
    159164   float changePerSecond;
    160165
    161    EffectOverTime(GraphicsPipeline_Vulkan<VertexType>& pipeline, vector<SceneObject<VertexType, SSBOType>>& objects,
    162                   unsigned int objectIndex, size_t effectedFieldOffset, float startTime, float changePerSecond)
    163                : pipeline(pipeline)
    164                , objects(objects)
     166   EffectOverTime(VulkanBuffer<SSBOType> &buffer, uint32_t objectIndex, size_t effectedFieldOffset, float startTime,
     167                  float changePerSecond)
     168               : buffer(buffer)
    165169               , objectIndex(objectIndex)
    166170               , effectedFieldOffset(effectedFieldOffset)
    167171               , startTime(startTime)
    168172               , changePerSecond(changePerSecond) {
    169       size_t ssboOffset = offset_of(&SceneObject<VertexType, SSBOType>::ssbo);
    170 
    171       unsigned char* effectedFieldPtr = reinterpret_cast<unsigned char*>(&objects[objectIndex]) +
    172          ssboOffset + effectedFieldOffset;
    173 
    174       startValue = *reinterpret_cast<float*>(effectedFieldPtr);
     173      startValue = *reinterpret_cast<float*>(getEffectedFieldPtr());
     174   }
     175
     176   unsigned char* getEffectedFieldPtr() {
     177      return reinterpret_cast<unsigned char*>(&buffer.get(objectIndex)) + effectedFieldOffset;
    175178   }
    176179
    177180   void applyEffect(float curTime) {
    178       if (objects[objectIndex].ssbo.deleted) {
    179          this->deleted = true;
     181      if (buffer.get(objectIndex).deleted) {
     182         deleted = true;
    180183         return;
    181184      }
    182185
    183       size_t ssboOffset = offset_of(&SceneObject<VertexType, SSBOType>::ssbo);
    184 
    185       unsigned char* effectedFieldPtr = reinterpret_cast<unsigned char*>(&objects[objectIndex]) +
    186          ssboOffset + effectedFieldOffset;
    187 
    188       *reinterpret_cast<float*>(effectedFieldPtr) = startValue + (curTime - startTime) * changePerSecond;
     186      *reinterpret_cast<float*>(getEffectedFieldPtr()) = startValue + (curTime - startTime) * changePerSecond;
    189187   }
    190188};
     
    341339      // if there is a need to add other uniform variables to one or more of the shaders
    342340
    343       vector<SceneObject<ModelVertex, SSBO_ModelObject>> modelObjects;
     341      vector<SceneObject<ModelVertex>> modelObjects;
    344342
    345343      UBO_VP_mats object_VP_mats;
    346344
    347       vector<SceneObject<ModelVertex, SSBO_ModelObject>> shipObjects;
     345      vector<SceneObject<ModelVertex>> shipObjects;
    348346
    349347      UBO_VP_mats ship_VP_mats;
    350348
    351       vector<SceneObject<ModelVertex, SSBO_Asteroid>> asteroidObjects;
     349      vector<SceneObject<ModelVertex>> asteroidObjects;
    352350
    353351      UBO_VP_mats asteroid_VP_mats;
    354352
    355       vector<SceneObject<LaserVertex, SSBO_Laser>> laserObjects;
     353      vector<SceneObject<LaserVertex>> laserObjects;
    356354
    357355      UBO_VP_mats laser_VP_mats;
    358356
    359       vector<SceneObject<ExplosionVertex, SSBO_Explosion>> explosionObjects;
     357      vector<SceneObject<ExplosionVertex>> explosionObjects;
    360358
    361359      UBO_Explosion explosion_UBO;
     
    370368
    371369      unsigned int leftLaserIdx = -1;
    372       EffectOverTime<ModelVertex, SSBO_Asteroid>* leftLaserEffect = nullptr;
     370      EffectOverTime<SSBO_Asteroid>* leftLaserEffect = nullptr;
    373371
    374372      unsigned int rightLaserIdx = -1;
    375       EffectOverTime<ModelVertex, SSBO_Asteroid>* rightLaserEffect = nullptr;
     373      EffectOverTime<SSBO_Asteroid>* rightLaserEffect = nullptr;
    376374
    377375      /*** High-level vars ***/
     
    440438      // stop using objects.back() to access the object that was just created
    441439      template<class VertexType, class SSBOType>
    442       SceneObject<VertexType, SSBOType>& addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
    443                                                    GraphicsPipeline_Vulkan<VertexType>& pipeline,
    444                                                    const vector<VertexType>& vertices, vector<uint16_t> indices,
    445                                                    VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo);
     440      SceneObject<VertexType>& addObject(vector<SceneObject<VertexType>>& objects,
     441                                         GraphicsPipeline_Vulkan<VertexType>& pipeline,
     442                                         const vector<VertexType>& vertices, vector<uint16_t> indices,
     443                                         VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo);
    446444
    447445      template<class VertexType>
     
    451449      vector<VertexType> addVertexNormals(vector<VertexType> vertices);
    452450
    453       template<class VertexType, class SSBOType>
    454       void centerObject(SceneObject<VertexType, SSBOType>& object);
    455 
    456       template<class VertexType, class SSBOType>
    457       void updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline,
    458             SceneObject<VertexType, SSBOType>& obj, size_t index);
     451      template<class VertexType>
     452      void centerObject(SceneObject<VertexType>& object);
     453
     454      template<class VertexType>
     455      void updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline, SceneObject<VertexType>& obj,
     456                                size_t index);
    459457
    460458      void addLaser(vec3 start, vec3 end, vec3 color, float width);
    461459      void translateLaser(size_t index, const vec3& translation);
    462460      void updateLaserTarget(size_t index);
    463       bool getLaserAndAsteroidIntersection(SceneObject<ModelVertex, SSBO_Asteroid>& asteroid,
    464             vec3& start, vec3& end, vec3& intersection);
     461      bool getLaserAndAsteroidIntersection(SceneObject<ModelVertex>& asteroid, vec3& start, vec3& end,
     462                                          vec3& intersection);
    465463
    466464      void addExplosion(mat4 model_mat, float duration, float cur_time);
     
    488486
    489487template<>
    490 inline void VulkanGame::centerObject(SceneObject<ExplosionVertex, SSBO_Explosion>& object) {
     488inline void VulkanGame::centerObject(SceneObject<ExplosionVertex>& object) {
    491489}
    492490
     
    505503// Figure out a better way to allow the model matrix to be set during object creation
    506504template<class VertexType, class SSBOType>
    507 SceneObject<VertexType, SSBOType>& VulkanGame::addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
    508                                                          GraphicsPipeline_Vulkan<VertexType>& pipeline,
    509                                                          const vector<VertexType>& vertices, vector<uint16_t> indices,
    510                                                          VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo) {
     505SceneObject<VertexType>& VulkanGame::addObject(vector<SceneObject<VertexType>>& objects,
     506                                               GraphicsPipeline_Vulkan<VertexType>& pipeline,
     507                                               const vector<VertexType>& vertices, vector<uint16_t> indices,
     508                                               VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo) {
    511509   // TODO: Use the model field of ssbo to set the object's model_base
    512510   // currently, the passed-in model is useless since it gets overridden when ssbo.model is recalculated
     
    517515   }
    518516
    519    objects.push_back({ vertices, indices, ssbo, mat4(1.0f), mat4(1.0f) });
     517   objects.push_back({ vertices, indices, mat4(1.0f), mat4(1.0f) });
    520518   objectBuffer.add(ssbo);
    521519
    522    SceneObject<VertexType, SSBOType>& obj = objects.back();
     520   SceneObject<VertexType>& obj = objects.back();
    523521
    524522   // TODO: Specify whether to center the object outside of this function or, worst case, maybe
     
    571569}
    572570
    573 template<class VertexType, class SSBOType>
    574 void VulkanGame::centerObject(SceneObject<VertexType, SSBOType>& object) {
     571template<class VertexType>
     572void VulkanGame::centerObject(SceneObject<VertexType>& object) {
    575573   vector<VertexType>& vertices = object.vertices;
    576574
     
    617615}
    618616
    619 template<class VertexType, class SSBOType>
    620 void VulkanGame::updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline,
    621       SceneObject<VertexType, SSBOType>& obj, size_t index) {
     617template<class VertexType>
     618void VulkanGame::updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline, SceneObject<VertexType>& obj,
     619                                      size_t index) {
    622620   pipeline.updateObjectVertices(index, obj.vertices, resourceCommandPool, graphicsQueue);
    623621}
Note: See TracChangeset for help on using the changeset viewer.