Changeset b8777b7 in opengl-game
- Timestamp:
- Nov 16, 2019, 8:38:22 PM (5 years ago)
- Branches:
- feature/imgui-sdl, master, points-test
- Children:
- 5a0242e
- Parents:
- cd487fb
- Files:
-
- 1 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
graphics-pipeline_vulkan.hpp
rcd487fb rb8777b7 4 4 #include "graphics-pipeline.hpp" 5 5 6 #include <fstream> 6 7 #include <stdexcept> 7 8 #include <vector> … … 23 24 }; 24 25 26 template<class VertexType> 27 struct 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 32 template<class VertexType> 25 33 class GraphicsPipeline_Vulkan : public GraphicsPipeline { 26 34 public: 35 GraphicsPipeline_Vulkan(); 27 36 GraphicsPipeline_Vulkan(VkPhysicalDevice physicalDevice, VkDevice device, VkRenderPass renderPass, 28 37 Viewport viewport, int vertexSize); … … 31 40 void updateRenderPass(VkRenderPass renderPass); 32 41 33 template<class VertexType>34 42 void bindData(const vector<VertexType>& vertices, const vector<uint16_t>& indices, 35 43 VkCommandPool commandPool, VkQueue graphicsQueue); … … 54 62 void createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage); 55 63 56 template<class VertexType>57 64 bool addObject(const vector<VertexType>& vertices, vector<uint16_t>& indices, VkCommandPool commandPool, 58 65 VkQueue graphicsQueue); … … 62 69 63 70 private: 64 VkShaderModule createShaderModule(const vector<char>& code);65 vector<char> readFile(const string& filename);66 67 71 VkPhysicalDevice physicalDevice; 68 72 VkDevice device; … … 90 94 VkBuffer indexBuffer; 91 95 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(); 92 103 }; 104 105 /*** PUBLIC METHODS ***/ 106 107 template<class VertexType> 108 GraphicsPipeline_Vulkan<VertexType>::GraphicsPipeline_Vulkan() { 109 } 110 111 template<class VertexType> 112 GraphicsPipeline_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 127 template<class VertexType> 128 GraphicsPipeline_Vulkan<VertexType>::~GraphicsPipeline_Vulkan() { 129 } 130 131 template<class VertexType> 132 void GraphicsPipeline_Vulkan<VertexType>::updateRenderPass(VkRenderPass renderPass) { 133 this->renderPass = renderPass; 134 } 93 135 94 136 // TODO: Probably better to template the whole class … … 96 138 97 139 // 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 143 template<class VertexType> 144 void GraphicsPipeline_Vulkan<VertexType>::bindData(const vector<VertexType>& vertices, const vector<uint16_t>& indices, 100 145 VkCommandPool commandPool, VkQueue graphicsQueue) { 101 146 numVertices = vertices.size(); … … 109 154 110 155 template<class VertexType> 111 bool GraphicsPipeline_Vulkan::addObject(const vector<VertexType>& vertices, vector<uint16_t>& indices,156 void GraphicsPipeline_Vulkan<VertexType>::createVertexBuffer(const void* bufferData, int vertexSize, 112 157 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 182 template<class VertexType> 183 void 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 209 template<class VertexType> 210 void 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 221 template<class VertexType> 222 void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) { 223 this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr }); 224 } 225 226 template<class VertexType> 227 void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) { 228 this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData }); 229 } 230 231 template<class VertexType> 232 void 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 369 template<class VertexType> 370 void 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 391 template<class VertexType> 392 void 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 411 template<class VertexType> 412 void 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 } 121 450 } 122 451 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 456 template<class VertexType> 457 void 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 471 template<class VertexType> 472 bool 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 497 template<class VertexType> 498 void GraphicsPipeline_Vulkan<VertexType>::cleanup() { 499 vkDestroyPipeline(device, pipeline, nullptr); 500 vkDestroyDescriptorPool(device, descriptorPool, nullptr); 501 vkDestroyPipelineLayout(device, pipelineLayout, nullptr); 502 } 503 504 template<class VertexType> 505 void 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 516 template<class VertexType> 517 VkShaderModule 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 531 template<class VertexType> 532 vector<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 550 template<class VertexType> 551 void 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); 135 568 } 136 569 -
makefile
rcd487fb rb8777b7 59 59 $(CC) $(CXX_FLAGS) -o $@ $^ $(LIB_FLAGS) -DGAMEGUI_INCLUDE_VULKAN 60 60 61 vulkangame: main-vulkan.cpp vulkan-game.cpp crash-logger.cpp logger.cpp vulkan-utils.cpp game-gui-sdl.cpp graphics-pipeline_vulkan.cpp61 vulkangame: main-vulkan.cpp vulkan-game.cpp crash-logger.cpp logger.cpp vulkan-utils.cpp game-gui-sdl.cpp 62 62 $(CC) $(CXX_FLAGS) -o $@ $^ $(LIB_FLAGS) -DGAMEGUI_INCLUDE_VULKAN 63 63 -
vulkan-game.cpp
rcd487fb rb8777b7 194 194 createUniformBuffers(); 195 195 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}} 206 206 }; 207 207 vector<uint16_t> sceneIndices = { … … 210 210 }; 211 211 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, 222 222 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, 224 224 VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor); 225 225 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); 230 230 231 231 vector<OverlayVertex> overlayVertices = { … … 239 239 }; 240 240 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, 250 250 VK_SHADER_STAGE_FRAGMENT_BIT, &sdlOverlayImageDescriptor); 251 251 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; 258 258 259 259 numPlanes = 2; … … 290 290 } else if (e.key.keycode == SDL_SCANCODE_SPACE) { 291 291 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 = { 294 294 {{-0.5f, -0.5f, zOffset}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}, 295 295 {{ 0.5f, -0.5f, zOffset}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}}, … … 301 301 }; 302 302 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++; 309 313 } else { 310 314 cout << "Key event detected" << endl; … … 429 433 vkDestroySampler(device, textureSampler, nullptr); 430 434 431 for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) { 432 pipeline.cleanupBuffers(); 433 } 435 modelPipeline.cleanupBuffers(); 436 overlayPipeline.cleanupBuffers(); 434 437 435 438 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { … … 929 932 vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); 930 933 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); 934 936 935 937 vkCmdEndRenderPass(commandBuffers[i]); … … 986 988 createUniformBuffers(); 987 989 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); 997 999 998 1000 createCommandBuffers(); … … 1026 1028 vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data()); 1027 1029 1028 for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) { 1029 pipeline.cleanup(); 1030 } 1030 modelPipeline.cleanup(); 1031 overlayPipeline.cleanup(); 1031 1032 1032 1033 vkDestroyRenderPass(device, renderPass, nullptr); -
vulkan-game.hpp
rcd487fb rb8777b7 15 15 #endif 16 16 17 // TODO: Figure out if these structs should be defined in the VulkanGame class 18 19 struct Vertex { 17 struct ModelVertex { 20 18 glm::vec3 pos; 21 19 glm::vec3 color; … … 40 38 GameGui* gui; 41 39 42 vector<GraphicsPipeline_Vulkan> graphicsPipelines; 40 GraphicsPipeline_Vulkan<ModelVertex> modelPipeline; 41 GraphicsPipeline_Vulkan<OverlayVertex> overlayPipeline; 43 42 44 43 SDL_version sdlVersion;
Note:
See TracChangeset
for help on using the changeset viewer.