Changeset b8777b7 in opengl-game


Ignore:
Timestamp:
Nov 16, 2019, 8:38:22 PM (5 years ago)
Author:
Dmitry Portnoy <dmitry.portnoy@…>
Branches:
feature/imgui-sdl, master, points-test
Children:
5a0242e
Parents:
cd487fb
Message:

Templatize GraphicsPipeline_Vulkan by adding a VertexType parameter and moving all the function definitions into the header file, separate the model and overlay pipelines into separate variables in VulkanGame instead of storing them in a vector

Files:
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • graphics-pipeline_vulkan.hpp

    rcd487fb rb8777b7  
    44#include "graphics-pipeline.hpp"
    55
     6#include <fstream>
    67#include <stdexcept>
    78#include <vector>
     
    2324};
    2425
     26template<class VertexType>
     27struct SceneObject {
     28   vector<VertexType> vertices;
     29   vector<uint16_t> indices; // TODO: Create a typedef for index type so I can easily change uin16_t to something else later
     30};
     31
     32template<class VertexType>
    2533class GraphicsPipeline_Vulkan : public GraphicsPipeline {
    2634   public:
     35      GraphicsPipeline_Vulkan();
    2736      GraphicsPipeline_Vulkan(VkPhysicalDevice physicalDevice, VkDevice device, VkRenderPass renderPass,
    2837         Viewport viewport, int vertexSize);
     
    3140      void updateRenderPass(VkRenderPass renderPass);
    3241
    33       template<class VertexType>
    3442      void bindData(const vector<VertexType>& vertices, const vector<uint16_t>& indices,
    3543         VkCommandPool commandPool, VkQueue graphicsQueue);
     
    5462      void createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage);
    5563
    56       template<class VertexType>
    5764      bool addObject(const vector<VertexType>& vertices, vector<uint16_t>& indices, VkCommandPool commandPool,
    5865         VkQueue graphicsQueue);
     
    6269   
    6370   private:
    64       VkShaderModule createShaderModule(const vector<char>& code);
    65       vector<char> readFile(const string& filename);
    66 
    6771      VkPhysicalDevice physicalDevice;
    6872      VkDevice device;
     
    9094      VkBuffer indexBuffer;
    9195      VkDeviceMemory indexBufferMemory;
     96
     97      vector<SceneObject<VertexType>> objects;
     98
     99      VkShaderModule createShaderModule(const vector<char>& code);
     100      vector<char> readFile(const string& filename);
     101
     102      void resizeDataBuffers();
    92103};
     104
     105/*** PUBLIC METHODS ***/
     106
     107template<class VertexType>
     108GraphicsPipeline_Vulkan<VertexType>::GraphicsPipeline_Vulkan() {
     109}
     110
     111template<class VertexType>
     112GraphicsPipeline_Vulkan<VertexType>::GraphicsPipeline_Vulkan(VkPhysicalDevice physicalDevice, VkDevice device,
     113      VkRenderPass renderPass, Viewport viewport, int vertexSize) {
     114   this->physicalDevice = physicalDevice;
     115   this->device = device;
     116   this->renderPass = renderPass;
     117   this->viewport = viewport;
     118
     119   // Since there is only one array of vertex data, we use binding = 0
     120   // I'll probably do that for the foreseeable future
     121   // I can calculate the stride myself given info about all the varying attributes
     122   this->bindingDescription.binding = 0;
     123   this->bindingDescription.stride = vertexSize;
     124   this->bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
     125}
     126
     127template<class VertexType>
     128GraphicsPipeline_Vulkan<VertexType>::~GraphicsPipeline_Vulkan() {
     129}
     130
     131template<class VertexType>
     132void GraphicsPipeline_Vulkan<VertexType>::updateRenderPass(VkRenderPass renderPass) {
     133   this->renderPass = renderPass;
     134}
    93135
    94136// TODO: Probably better to template the whole class
     
    96138
    97139// TODO: combine this function and the constructor since I call this right after the constructor anyway
    98 template<class VertexType>
    99 void GraphicsPipeline_Vulkan::bindData(const vector<VertexType>& vertices, const vector<uint16_t>& indices,
     140// TODO: Creating the initial buffers could occur in the constructor and instead of calling this function
     141// and passing in vertices and indices, addObject() could be called instead and this function could be
     142// removed
     143template<class VertexType>
     144void GraphicsPipeline_Vulkan<VertexType>::bindData(const vector<VertexType>& vertices, const vector<uint16_t>& indices,
    100145      VkCommandPool commandPool, VkQueue graphicsQueue) {
    101146   numVertices = vertices.size();
     
    109154
    110155template<class VertexType>
    111 bool GraphicsPipeline_Vulkan::addObject(const vector<VertexType>& vertices, vector<uint16_t>& indices,
     156void GraphicsPipeline_Vulkan<VertexType>::createVertexBuffer(const void* bufferData, int vertexSize,
    112157      VkCommandPool commandPool, VkQueue graphicsQueue) {
    113 
    114    if (numVertices + vertices.size() > vertexCapacity) {
    115       throw runtime_error("ERROR: Need to resize vertex buffers");
    116    } else if (numIndices + indices.size() > indexCapacity) {
    117       throw runtime_error("ERROR: Need to resize index buffers");
    118    } else {
    119       for (uint16_t& idx : indices) {
    120          idx += numVertices;
     158   VkDeviceSize bufferSize = numVertices * vertexSize;
     159   VkDeviceSize bufferCapacity = vertexCapacity * vertexSize;
     160
     161   VkBuffer stagingBuffer;
     162   VkDeviceMemory stagingBufferMemory;
     163   VulkanUtils::createBuffer(device, physicalDevice, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
     164      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     165      stagingBuffer, stagingBufferMemory);
     166
     167   void* data;
     168   vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
     169   memcpy(data, bufferData, (size_t) bufferSize);
     170   vkUnmapMemory(device, stagingBufferMemory);
     171
     172   VulkanUtils::createBuffer(device, physicalDevice, bufferCapacity,
     173      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
     174      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
     175
     176   VulkanUtils::copyBuffer(device, commandPool, stagingBuffer, vertexBuffer, 0, 0, bufferSize, graphicsQueue);
     177
     178   vkDestroyBuffer(device, stagingBuffer, nullptr);
     179   vkFreeMemory(device, stagingBufferMemory, nullptr);
     180}
     181
     182template<class VertexType>
     183void GraphicsPipeline_Vulkan<VertexType>::createIndexBuffer(const void* bufferData, int indexSize,
     184      VkCommandPool commandPool, VkQueue graphicsQueue) {
     185   VkDeviceSize bufferSize = numIndices * indexSize;
     186   VkDeviceSize bufferCapacity = indexCapacity * indexSize;
     187
     188   VkBuffer stagingBuffer;
     189   VkDeviceMemory stagingBufferMemory;
     190   VulkanUtils::createBuffer(device, physicalDevice, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
     191      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     192      stagingBuffer, stagingBufferMemory);
     193
     194   void* data;
     195   vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
     196   memcpy(data, bufferData, (size_t) bufferSize);
     197   vkUnmapMemory(device, stagingBufferMemory);
     198
     199   VulkanUtils::createBuffer(device, physicalDevice, bufferCapacity,
     200      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
     201      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
     202
     203   VulkanUtils::copyBuffer(device, commandPool, stagingBuffer, indexBuffer, 0, 0, bufferSize, graphicsQueue);
     204
     205   vkDestroyBuffer(device, stagingBuffer, nullptr);
     206   vkFreeMemory(device, stagingBufferMemory, nullptr);
     207}
     208
     209template<class VertexType>
     210void GraphicsPipeline_Vulkan<VertexType>::addAttribute(VkFormat format, size_t offset) {
     211   VkVertexInputAttributeDescription attributeDesc = {};
     212
     213   attributeDesc.binding = 0;
     214   attributeDesc.location = this->attributeDescriptions.size();
     215   attributeDesc.format = format;
     216   attributeDesc.offset = offset;
     217
     218   this->attributeDescriptions.push_back(attributeDesc);
     219}
     220
     221template<class VertexType>
     222void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) {
     223   this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr });
     224}
     225
     226template<class VertexType>
     227void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) {
     228   this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData });
     229}
     230
     231template<class VertexType>
     232void GraphicsPipeline_Vulkan<VertexType>::createPipeline(string vertShaderFile, string fragShaderFile) {
     233   vector<char> vertShaderCode = readFile(vertShaderFile);
     234   vector<char> fragShaderCode = readFile(fragShaderFile);
     235
     236   VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
     237   VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
     238
     239   VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
     240   vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
     241   vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
     242   vertShaderStageInfo.module = vertShaderModule;
     243   vertShaderStageInfo.pName = "main";
     244
     245   VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
     246   fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
     247   fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
     248   fragShaderStageInfo.module = fragShaderModule;
     249   fragShaderStageInfo.pName = "main";
     250
     251   VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
     252
     253   VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
     254   vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
     255
     256   vertexInputInfo.vertexBindingDescriptionCount = 1;
     257   vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(this->attributeDescriptions.size());
     258   vertexInputInfo.pVertexBindingDescriptions = &this->bindingDescription;
     259   vertexInputInfo.pVertexAttributeDescriptions = this->attributeDescriptions.data();
     260
     261   VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
     262   inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
     263   inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
     264   inputAssembly.primitiveRestartEnable = VK_FALSE;
     265
     266   VkViewport viewport = {};
     267   viewport.x = (float)this->viewport.x;
     268   viewport.y = (float)this->viewport.y;
     269   viewport.width = (float)this->viewport.width;
     270   viewport.height = (float)this->viewport.height;
     271   viewport.minDepth = 0.0f;
     272   viewport.maxDepth = 1.0f;
     273
     274   VkRect2D scissor = {};
     275   scissor.offset = { 0, 0 };
     276   scissor.extent = { (uint32_t)this->viewport.width, (uint32_t)this->viewport.height };
     277
     278   VkPipelineViewportStateCreateInfo viewportState = {};
     279   viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
     280   viewportState.viewportCount = 1;
     281   viewportState.pViewports = &viewport;
     282   viewportState.scissorCount = 1;
     283   viewportState.pScissors = &scissor;
     284
     285   VkPipelineRasterizationStateCreateInfo rasterizer = {};
     286   rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
     287   rasterizer.depthClampEnable = VK_FALSE;
     288   rasterizer.rasterizerDiscardEnable = VK_FALSE;
     289   rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
     290   rasterizer.lineWidth = 1.0f;
     291   rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
     292   rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
     293   rasterizer.depthBiasEnable = VK_FALSE;
     294
     295   VkPipelineMultisampleStateCreateInfo multisampling = {};
     296   multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
     297   multisampling.sampleShadingEnable = VK_FALSE;
     298   multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
     299
     300   VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
     301   colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
     302   colorBlendAttachment.blendEnable = VK_TRUE;
     303   colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
     304   colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
     305   colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
     306   colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
     307   colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
     308   colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
     309
     310   VkPipelineColorBlendStateCreateInfo colorBlending = {};
     311   colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
     312   colorBlending.logicOpEnable = VK_FALSE;
     313   colorBlending.logicOp = VK_LOGIC_OP_COPY;
     314   colorBlending.attachmentCount = 1;
     315   colorBlending.pAttachments = &colorBlendAttachment;
     316   colorBlending.blendConstants[0] = 0.0f;
     317   colorBlending.blendConstants[1] = 0.0f;
     318   colorBlending.blendConstants[2] = 0.0f;
     319   colorBlending.blendConstants[3] = 0.0f;
     320
     321   VkPipelineDepthStencilStateCreateInfo depthStencil = {};
     322   depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
     323   depthStencil.depthTestEnable = VK_TRUE;
     324   depthStencil.depthWriteEnable = VK_TRUE;
     325   depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
     326   depthStencil.depthBoundsTestEnable = VK_FALSE;
     327   depthStencil.minDepthBounds = 0.0f;
     328   depthStencil.maxDepthBounds = 1.0f;
     329   depthStencil.stencilTestEnable = VK_FALSE;
     330   depthStencil.front = {};
     331   depthStencil.back = {};
     332
     333   VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
     334   pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
     335   pipelineLayoutInfo.setLayoutCount = 1;
     336   pipelineLayoutInfo.pSetLayouts = &this->descriptorSetLayout;
     337   pipelineLayoutInfo.pushConstantRangeCount = 0;
     338
     339   if (vkCreatePipelineLayout(this->device, &pipelineLayoutInfo, nullptr, &this->pipelineLayout) != VK_SUCCESS) {
     340      throw runtime_error("failed to create pipeline layout!");
     341   }
     342
     343   VkGraphicsPipelineCreateInfo pipelineInfo = {};
     344   pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
     345   pipelineInfo.stageCount = 2;
     346   pipelineInfo.pStages = shaderStages;
     347   pipelineInfo.pVertexInputState = &vertexInputInfo;
     348   pipelineInfo.pInputAssemblyState = &inputAssembly;
     349   pipelineInfo.pViewportState = &viewportState;
     350   pipelineInfo.pRasterizationState = &rasterizer;
     351   pipelineInfo.pMultisampleState = &multisampling;
     352   pipelineInfo.pDepthStencilState = &depthStencil;
     353   pipelineInfo.pColorBlendState = &colorBlending;
     354   pipelineInfo.pDynamicState = nullptr;
     355   pipelineInfo.layout = this->pipelineLayout;
     356   pipelineInfo.renderPass = this->renderPass;
     357   pipelineInfo.subpass = 0;
     358   pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
     359   pipelineInfo.basePipelineIndex = -1;
     360
     361   if (vkCreateGraphicsPipelines(this->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &this->pipeline) != VK_SUCCESS) {
     362      throw runtime_error("failed to create graphics pipeline!");
     363   }
     364
     365   vkDestroyShaderModule(this->device, vertShaderModule, nullptr);
     366   vkDestroyShaderModule(this->device, fragShaderModule, nullptr);
     367}
     368
     369template<class VertexType>
     370void GraphicsPipeline_Vulkan<VertexType>::createDescriptorSetLayout() {
     371   vector<VkDescriptorSetLayoutBinding> bindings(this->descriptorInfoList.size());
     372
     373   for (size_t i = 0; i < bindings.size(); i++) {
     374      bindings[i].binding = i;
     375      bindings[i].descriptorCount = 1;
     376      bindings[i].descriptorType = this->descriptorInfoList[i].type;
     377      bindings[i].stageFlags = this->descriptorInfoList[i].stageFlags;
     378      bindings[i].pImmutableSamplers = nullptr;
     379   }
     380
     381   VkDescriptorSetLayoutCreateInfo layoutInfo = {};
     382   layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
     383   layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
     384   layoutInfo.pBindings = bindings.data();
     385
     386   if (vkCreateDescriptorSetLayout(this->device, &layoutInfo, nullptr, &this->descriptorSetLayout) != VK_SUCCESS) {
     387      throw runtime_error("failed to create descriptor set layout!");
     388   }
     389}
     390
     391template<class VertexType>
     392void GraphicsPipeline_Vulkan<VertexType>::createDescriptorPool(vector<VkImage>& swapChainImages) {
     393   vector<VkDescriptorPoolSize> poolSizes(this->descriptorInfoList.size());
     394
     395   for (size_t i = 0; i < poolSizes.size(); i++) {
     396      poolSizes[i].type = this->descriptorInfoList[i].type;
     397      poolSizes[i].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
     398   }
     399
     400   VkDescriptorPoolCreateInfo poolInfo = {};
     401   poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
     402   poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
     403   poolInfo.pPoolSizes = poolSizes.data();
     404   poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
     405
     406   if (vkCreateDescriptorPool(this->device, &poolInfo, nullptr, &this->descriptorPool) != VK_SUCCESS) {
     407      throw runtime_error("failed to create descriptor pool!");
     408   }
     409}
     410
     411template<class VertexType>
     412void GraphicsPipeline_Vulkan<VertexType>::createDescriptorSets(vector<VkImage>& swapChainImages) {
     413   vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), this->descriptorSetLayout);
     414
     415   VkDescriptorSetAllocateInfo allocInfo = {};
     416   allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
     417   allocInfo.descriptorPool = this->descriptorPool;
     418   allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
     419   allocInfo.pSetLayouts = layouts.data();
     420
     421   this->descriptorSets.resize(swapChainImages.size());
     422   if (vkAllocateDescriptorSets(device, &allocInfo, this->descriptorSets.data()) != VK_SUCCESS) {
     423      throw runtime_error("failed to allocate descriptor sets!");
     424   }
     425
     426   for (size_t i = 0; i < swapChainImages.size(); i++) {
     427      vector<VkWriteDescriptorSet> descriptorWrites(this->descriptorInfoList.size());
     428
     429      for (size_t j = 0; j < descriptorWrites.size(); j++) {
     430         descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     431         descriptorWrites[j].dstSet = this->descriptorSets[i];
     432         descriptorWrites[j].dstBinding = j;
     433         descriptorWrites[j].dstArrayElement = 0;
     434         descriptorWrites[j].descriptorType = this->descriptorInfoList[j].type;
     435         descriptorWrites[j].descriptorCount = 1;
     436         descriptorWrites[j].pBufferInfo = nullptr;
     437         descriptorWrites[j].pImageInfo = nullptr;
     438         descriptorWrites[j].pTexelBufferView = nullptr;
     439
     440         switch (descriptorWrites[j].descriptorType) {
     441            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
     442               descriptorWrites[j].pBufferInfo = &(*this->descriptorInfoList[j].bufferDataList)[i];
     443               break;
     444            case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
     445               descriptorWrites[j].pImageInfo = this->descriptorInfoList[j].imageData;
     446               break;
     447            default:
     448               throw runtime_error("Unknown descriptor type: " + to_string(descriptorWrites[j].descriptorType));
     449         }
    121450      }
    122451
    123       VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, vertices, vertexBuffer, numVertices,
    124          graphicsQueue);
    125       numVertices += vertices.size();
    126 
    127       VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, indices, indexBuffer, numIndices,
    128          graphicsQueue);
    129       numIndices += indices.size();
    130 
    131       return true;
    132    }
    133 
    134    return false;
     452      vkUpdateDescriptorSets(this->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
     453   }
     454}
     455
     456template<class VertexType>
     457void GraphicsPipeline_Vulkan<VertexType>::createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage) {
     458   vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
     459   vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1,
     460      &descriptorSets[currentImage], 0, nullptr);
     461
     462   VkBuffer vertexBuffers[] = { vertexBuffer };
     463   VkDeviceSize offsets[] = { 0 };
     464   vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
     465
     466   vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
     467
     468   vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(numIndices), 1, 0, 0, 0);
     469}
     470
     471template<class VertexType>
     472bool GraphicsPipeline_Vulkan<VertexType>::addObject(const vector<VertexType>& vertices, vector<uint16_t>& indices,
     473      VkCommandPool commandPool, VkQueue graphicsQueue) {
     474
     475   if (numVertices + vertices.size() > vertexCapacity ||
     476       numIndices + indices.size() > indexCapacity) {
     477      resizeDataBuffers();
     478
     479      throw runtime_error("ERROR: Need to resize data buffers");
     480   }
     481
     482   for (uint16_t& idx : indices) {
     483      idx += numVertices;
     484   }
     485
     486   VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, vertices, vertexBuffer, numVertices,
     487      graphicsQueue);
     488   numVertices += vertices.size();
     489
     490   VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, indices, indexBuffer, numIndices,
     491      graphicsQueue);
     492   numIndices += indices.size();
     493
     494   return true;
     495}
     496
     497template<class VertexType>
     498void GraphicsPipeline_Vulkan<VertexType>::cleanup() {
     499   vkDestroyPipeline(device, pipeline, nullptr);
     500   vkDestroyDescriptorPool(device, descriptorPool, nullptr);
     501   vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
     502}
     503
     504template<class VertexType>
     505void GraphicsPipeline_Vulkan<VertexType>::cleanupBuffers() {
     506   vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
     507
     508   vkDestroyBuffer(device, vertexBuffer, nullptr);
     509   vkFreeMemory(device, vertexBufferMemory, nullptr);
     510   vkDestroyBuffer(device, indexBuffer, nullptr);
     511   vkFreeMemory(device, indexBufferMemory, nullptr);
     512}
     513
     514/*** PRIVATE METHODS ***/
     515
     516template<class VertexType>
     517VkShaderModule GraphicsPipeline_Vulkan<VertexType>::createShaderModule(const vector<char>& code) {
     518   VkShaderModuleCreateInfo createInfo = {};
     519   createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
     520   createInfo.codeSize = code.size();
     521   createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
     522
     523   VkShaderModule shaderModule;
     524   if (vkCreateShaderModule(this->device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
     525      throw runtime_error("failed to create shader module!");
     526   }
     527
     528   return shaderModule;
     529}
     530
     531template<class VertexType>
     532vector<char> GraphicsPipeline_Vulkan<VertexType>::readFile(const string& filename) {
     533   ifstream file(filename, ios::ate | ios::binary);
     534
     535   if (!file.is_open()) {
     536      throw runtime_error("failed to open file!");
     537   }
     538
     539   size_t fileSize = (size_t)file.tellg();
     540   vector<char> buffer(fileSize);
     541
     542   file.seekg(0);
     543   file.read(buffer.data(), fileSize);
     544
     545   file.close();
     546
     547   return buffer;
     548}
     549
     550template<class VertexType>
     551void GraphicsPipeline_Vulkan<VertexType>::resizeDataBuffers() {
     552   
     553   vkDestroyBuffer(device, vertexBuffer, nullptr);
     554   vkFreeMemory(device, vertexBufferMemory, nullptr);
     555   vkDestroyBuffer(device, indexBuffer, nullptr);
     556   vkFreeMemory(device, indexBufferMemory, nullptr);
     557
     558   vertexCapacity *= 2;
     559   indexCapacity *= 2;
     560
     561   VulkanUtils::createBuffer(device, physicalDevice, vertexCapacity * sizeof(VertexType),
     562      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
     563      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
     564
     565   VulkanUtils::createBuffer(device, physicalDevice, indexCapacity * sizeof(uint16_t),
     566      VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
     567      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
    135568}
    136569
  • makefile

    rcd487fb rb8777b7  
    5959        $(CC) $(CXX_FLAGS) -o $@ $^ $(LIB_FLAGS) -DGAMEGUI_INCLUDE_VULKAN
    6060
    61 vulkangame: main-vulkan.cpp vulkan-game.cpp crash-logger.cpp logger.cpp vulkan-utils.cpp game-gui-sdl.cpp graphics-pipeline_vulkan.cpp
     61vulkangame: main-vulkan.cpp vulkan-game.cpp crash-logger.cpp logger.cpp vulkan-utils.cpp game-gui-sdl.cpp
    6262        $(CC) $(CXX_FLAGS) -o $@ $^ $(LIB_FLAGS) -DGAMEGUI_INCLUDE_VULKAN
    6363
  • vulkan-game.cpp

    rcd487fb rb8777b7  
    194194   createUniformBuffers();
    195195
    196    vector<Vertex> sceneVertices = {
    197       {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
    198       {{ 0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
    199       {{ 0.5f,  0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
    200       {{-0.5f,  0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
    201 
    202       {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
    203       {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
    204       {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
    205       {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
     196   vector<ModelVertex> sceneVertices = {
     197      {{-0.5f, -0.5f, -2.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
     198      {{ 0.5f, -0.5f, -2.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     199      {{ 0.5f,  0.5f, -2.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     200      {{-0.5f,  0.5f, -2.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
     201
     202      {{-0.5f, -0.5f, -1.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
     203      {{ 0.5f, -0.5f, -1.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     204      {{ 0.5f,  0.5f, -1.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
     205      {{-0.5f,  0.5f, -1.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
    206206   };
    207207   vector<uint16_t> sceneIndices = {
     
    210210   };
    211211
    212    graphicsPipelines.push_back(GraphicsPipeline_Vulkan(physicalDevice, device, renderPass,
    213       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, sizeof(Vertex)));
    214 
    215    graphicsPipelines.back().bindData(sceneVertices, sceneIndices, commandPool, graphicsQueue);
    216 
    217    graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::pos));
    218    graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::color));
    219    graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&Vertex::texCoord));
    220 
    221    graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     212   modelPipeline = GraphicsPipeline_Vulkan<ModelVertex>(physicalDevice, device, renderPass,
     213      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, sizeof(ModelVertex));
     214
     215   modelPipeline.bindData(sceneVertices, sceneIndices, commandPool, graphicsQueue);
     216
     217   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::pos));
     218   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::color));
     219   modelPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&ModelVertex::texCoord));
     220
     221   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
    222222      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList);
    223    graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
     223   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
    224224      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
    225225
    226    graphicsPipelines.back().createDescriptorSetLayout();
    227    graphicsPipelines.back().createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
    228    graphicsPipelines.back().createDescriptorPool(swapChainImages);
    229    graphicsPipelines.back().createDescriptorSets(swapChainImages);
     226   modelPipeline.createDescriptorSetLayout();
     227   modelPipeline.createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
     228   modelPipeline.createDescriptorPool(swapChainImages);
     229   modelPipeline.createDescriptorSets(swapChainImages);
    230230
    231231   vector<OverlayVertex> overlayVertices = {
     
    239239   };
    240240
    241    graphicsPipelines.push_back(GraphicsPipeline_Vulkan(physicalDevice, device, renderPass,
    242       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, sizeof(OverlayVertex)));
    243 
    244    graphicsPipelines.back().bindData(overlayVertices, overlayIndices, commandPool, graphicsQueue);
    245 
    246    graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&OverlayVertex::pos));
    247    graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
    248 
    249    graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
     241   overlayPipeline = GraphicsPipeline_Vulkan<OverlayVertex>(physicalDevice, device, renderPass,
     242      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, sizeof(OverlayVertex));
     243
     244   overlayPipeline.bindData(overlayVertices, overlayIndices, commandPool, graphicsQueue);
     245
     246   overlayPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&OverlayVertex::pos));
     247   overlayPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
     248
     249   overlayPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
    250250      VK_SHADER_STAGE_FRAGMENT_BIT, &sdlOverlayImageDescriptor);
    251251
    252    graphicsPipelines.back().createDescriptorSetLayout();
    253    graphicsPipelines.back().createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
    254    graphicsPipelines.back().createDescriptorPool(swapChainImages);
    255    graphicsPipelines.back().createDescriptorSets(swapChainImages);
    256 
    257    cout << "Created " << graphicsPipelines.size() << " graphics pipelines" << endl;
     252   overlayPipeline.createDescriptorSetLayout();
     253   overlayPipeline.createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
     254   overlayPipeline.createDescriptorPool(swapChainImages);
     255   overlayPipeline.createDescriptorSets(swapChainImages);
     256
     257   cout << "Created all the graphics pipelines" << endl;
    258258
    259259   numPlanes = 2;
     
    290290               } else if (e.key.keycode == SDL_SCANCODE_SPACE) {
    291291                  cout << "Adding a plane" << endl;
    292                   float zOffset = -0.5f + (0.5f * numPlanes);
    293                   vector<Vertex> vertices = {
     292                  float zOffset = -2.0f + (0.5f * numPlanes);
     293                  vector<ModelVertex> vertices = {
    294294                     {{-0.5f, -0.5f,  zOffset}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
    295295                     {{ 0.5f, -0.5f,  zOffset}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
     
    301301                  };
    302302
    303                   if (graphicsPipelines[0].addObject(vertices, indices, commandPool, graphicsQueue)) {
    304                      vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
    305                      createCommandBuffers();
    306 
    307                      numPlanes++;
    308                   }
     303                  // TODO: Encapsulate these lines into an addObject() function in vulkan-game
     304
     305                  vkDeviceWaitIdle(device);
     306                  vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
     307
     308                  modelPipeline.addObject(vertices, indices, commandPool, graphicsQueue);
     309
     310                  createCommandBuffers();
     311
     312                  numPlanes++;
    309313               } else {
    310314                  cout << "Key event detected" << endl;
     
    429433   vkDestroySampler(device, textureSampler, nullptr);
    430434
    431    for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
    432       pipeline.cleanupBuffers();
    433    }
     435   modelPipeline.cleanupBuffers();
     436   overlayPipeline.cleanupBuffers();
    434437
    435438   for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
     
    929932      vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
    930933
    931       for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
    932          pipeline.createRenderCommands(commandBuffers[i], i);
    933       }
     934      modelPipeline.createRenderCommands(commandBuffers[i], i);
     935      overlayPipeline.createRenderCommands(commandBuffers[i], i);
    934936
    935937      vkCmdEndRenderPass(commandBuffers[i]);
     
    986988   createUniformBuffers();
    987989
    988    graphicsPipelines[0].updateRenderPass(renderPass);
    989    graphicsPipelines[0].createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
    990    graphicsPipelines[0].createDescriptorPool(swapChainImages);
    991    graphicsPipelines[0].createDescriptorSets(swapChainImages);
    992 
    993    graphicsPipelines[1].updateRenderPass(renderPass);
    994    graphicsPipelines[1].createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
    995    graphicsPipelines[1].createDescriptorPool(swapChainImages);
    996    graphicsPipelines[1].createDescriptorSets(swapChainImages);
     990   modelPipeline.updateRenderPass(renderPass);
     991   modelPipeline.createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
     992   modelPipeline.createDescriptorPool(swapChainImages);
     993   modelPipeline.createDescriptorSets(swapChainImages);
     994
     995   overlayPipeline.updateRenderPass(renderPass);
     996   overlayPipeline.createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
     997   overlayPipeline.createDescriptorPool(swapChainImages);
     998   overlayPipeline.createDescriptorSets(swapChainImages);
    997999
    9981000   createCommandBuffers();
     
    10261028   vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
    10271029
    1028    for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
    1029       pipeline.cleanup();
    1030    }
     1030   modelPipeline.cleanup();
     1031   overlayPipeline.cleanup();
    10311032
    10321033   vkDestroyRenderPass(device, renderPass, nullptr);
  • vulkan-game.hpp

    rcd487fb rb8777b7  
    1515#endif
    1616
    17 // TODO: Figure out if these structs should be defined in the VulkanGame class
    18 
    19 struct Vertex {
     17struct ModelVertex {
    2018   glm::vec3 pos;
    2119   glm::vec3 color;
     
    4038      GameGui* gui;
    4139
    42       vector<GraphicsPipeline_Vulkan> graphicsPipelines;
     40      GraphicsPipeline_Vulkan<ModelVertex> modelPipeline;
     41      GraphicsPipeline_Vulkan<OverlayVertex> overlayPipeline;
    4342
    4443      SDL_version sdlVersion;
Note: See TracChangeset for help on using the changeset viewer.