Changeset 9d21aac in opengl-game for graphics-pipeline_vulkan.hpp
- Timestamp:
- May 6, 2021, 3:24:42 AM (4 years ago)
- Branches:
- feature/imgui-sdl
- Children:
- 996dd3e
- Parents:
- 756162f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
graphics-pipeline_vulkan.hpp
r756162f r9d21aac 21 21 22 22 using namespace glm; 23 24 // TODO: Maybe change the name of this struct so I can call the list something other than descriptorInfoList25 struct DescriptorInfo {26 VkDescriptorType type;27 VkShaderStageFlags stageFlags;28 29 // Only one of the below properties should be set30 vector<VkDescriptorBufferInfo>* bufferDataList;31 VkDescriptorImageInfo* imageData;32 };33 23 34 24 // TODO: Use this struct for uniform buffers as well and rename it to VulkanBuffer (maybe move it to VulkanUtils) … … 41 31 }; 42 32 43 template<class VertexType, class SSBOType> 33 // TODO: Maybe change the name of this struct so I can call the list something other than descriptorInfoList 34 struct DescriptorInfo { 35 VkDescriptorType type; 36 VkShaderStageFlags stageFlags; 37 38 // Only one of the below properties should be set 39 vector<VkDescriptorBufferInfo>* bufferDataList; 40 VkDescriptorImageInfo* imageData; 41 }; 42 43 template<class VertexType> 44 44 class GraphicsPipeline_Vulkan : public GraphicsPipeline { 45 45 public: 46 46 string vertShaderFile, fragShaderFile; 47 48 // TODO: Move this outside this classs, since it is no longer used here 49 StorageBufferSet storageBufferSet; 50 51 // Both of these are only used for managing the SSBO, so move them out as well 52 size_t objectCapacity; 53 size_t numObjects; 47 54 48 55 GraphicsPipeline_Vulkan(); … … 64 71 void addAttribute(VkFormat format, size_t offset); 65 72 66 void addStorageDescriptor(VkShaderStageFlags stageFlags);67 68 73 // TODO: I might be able to use a single VkDescriptorBufferInfo here and reuse it when creating the descriptor sets 69 74 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, … … 71 76 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData); 72 77 78 void updateDescriptorInfo(uint32_t index, vector<VkDescriptorBufferInfo>* bufferData); 79 // TODO: Maybe make an analogous one for updating image info 80 73 81 void createPipeline(string vertShaderFile, string fragShaderFile); 74 82 void createDescriptorSetLayout(); … … 78 86 void createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage); 79 87 80 bool addObject(const vector<VertexType>& vertices, vector<uint16_t> indices, SSBOType& ssbo, 81 VkCommandPool commandPool, VkQueue graphicsQueue); 82 83 void updateObject(size_t objIndex, SSBOType& ssbo); 88 void addObject(const vector<VertexType>& vertices, vector<uint16_t> indices, VkCommandPool commandPool, 89 VkQueue graphicsQueue); 84 90 85 91 void updateObjectVertices(size_t objIndex, const vector<VertexType>& vertices, VkCommandPool commandPool, … … 117 123 VkDeviceMemory indexBufferMemory; 118 124 119 size_t numObjects;120 size_t objectCapacity;121 122 StorageBufferSet storageBufferSet;123 124 125 VkShaderModule createShaderModule(const vector<char>& code); 125 126 vector<char> readFile(const string& filename); … … 127 128 void resizeVertexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue); 128 129 void resizeIndexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue); 129 void resizeStorageBufferSet(StorageBufferSet& set, VkCommandPool commandPool, VkQueue graphicsQueue);130 130 }; 131 131 132 132 /*** PUBLIC METHODS ***/ 133 133 134 template<class VertexType , class SSBOType>135 GraphicsPipeline_Vulkan<VertexType , SSBOType>::GraphicsPipeline_Vulkan() {134 template<class VertexType> 135 GraphicsPipeline_Vulkan<VertexType>::GraphicsPipeline_Vulkan() { 136 136 } 137 137 … … 139 139 // TODO: See if it would be feasible to move code in the createPipeline method 140 140 // into the constructor. That way, I can also put relevant cleanup code into the destructor 141 template<class VertexType , class SSBOType>142 GraphicsPipeline_Vulkan<VertexType , SSBOType>::GraphicsPipeline_Vulkan(141 template<class VertexType> 142 GraphicsPipeline_Vulkan<VertexType>::GraphicsPipeline_Vulkan( 143 143 VkPrimitiveTopology topology, VkPhysicalDevice physicalDevice, VkDevice device, 144 144 VkRenderPass renderPass, Viewport viewport, vector<VkImage>& swapChainImages, … … 173 173 this->numObjects = 0; 174 174 this->objectCapacity = objectCapacity; 175 176 // Hacky way to allow an SSBO to be optional177 // Specifying void* as the SSBOType will skip allocating the related buffers178 if (!is_same_v<SSBOType, void*>) {179 VkDeviceSize bufferSize = objectCapacity * sizeof(SSBOType);180 cout << "NUM SWAP CHAIN IMAGES: " << swapChainImages.size() << endl;181 182 storageBufferSet.buffers.resize(swapChainImages.size());183 storageBufferSet.memory.resize(swapChainImages.size());184 storageBufferSet.infoSet.resize(swapChainImages.size());185 186 for (size_t i = 0; i < swapChainImages.size(); i++) {187 VulkanUtils::createBuffer(this->device, this->physicalDevice, bufferSize,188 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,189 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,190 storageBufferSet.buffers[i], storageBufferSet.memory[i]);191 192 storageBufferSet.infoSet[i].buffer = storageBufferSet.buffers[i];193 storageBufferSet.infoSet[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now194 storageBufferSet.infoSet[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE195 }196 }197 175 } 198 176 199 177 // TODO: Move as much cleanup as I can into the destructor 200 template<class VertexType , class SSBOType>201 GraphicsPipeline_Vulkan<VertexType , SSBOType>::~GraphicsPipeline_Vulkan() {202 } 203 204 template<class VertexType , class SSBOType>205 size_t GraphicsPipeline_Vulkan<VertexType , SSBOType>::getNumVertices() {178 template<class VertexType> 179 GraphicsPipeline_Vulkan<VertexType>::~GraphicsPipeline_Vulkan() { 180 } 181 182 template<class VertexType> 183 size_t GraphicsPipeline_Vulkan<VertexType>::getNumVertices() { 206 184 return numVertices; 207 185 } 208 186 209 template<class VertexType , class SSBOType>210 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::updateRenderPass(VkRenderPass renderPass) {187 template<class VertexType> 188 void GraphicsPipeline_Vulkan<VertexType>::updateRenderPass(VkRenderPass renderPass) { 211 189 this->renderPass = renderPass; 212 190 } 213 191 214 template<class VertexType , class SSBOType>215 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::addAttribute(VkFormat format, size_t offset) {192 template<class VertexType> 193 void GraphicsPipeline_Vulkan<VertexType>::addAttribute(VkFormat format, size_t offset) { 216 194 VkVertexInputAttributeDescription attributeDesc = {}; 217 195 … … 224 202 } 225 203 226 // TODO: The SSBOType check isn't really needed since I call this function in VulkanGame explicitly 227 template<class VertexType, class SSBOType> 228 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addStorageDescriptor(VkShaderStageFlags stageFlags) { 229 if (!is_same_v<SSBOType, void*>) { 230 addDescriptorInfo(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 231 stageFlags, &storageBufferSet.infoSet); 232 } 233 } 234 235 template<class VertexType, class SSBOType> 236 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addDescriptorInfo(VkDescriptorType type, 204 template<class VertexType> 205 void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, 237 206 VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) { 238 207 this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr }); 239 208 } 240 209 241 template<class VertexType , class SSBOType>242 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::addDescriptorInfo(VkDescriptorType type,210 template<class VertexType> 211 void GraphicsPipeline_Vulkan<VertexType>::addDescriptorInfo(VkDescriptorType type, 243 212 VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) { 244 213 this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData }); 245 214 } 246 215 247 template<class VertexType, class SSBOType> 248 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createPipeline(string vertShaderFile, string fragShaderFile) { 216 template<class VertexType> 217 void GraphicsPipeline_Vulkan<VertexType>::updateDescriptorInfo(uint32_t index, 218 vector<VkDescriptorBufferInfo>* bufferData) { 219 this->descriptorInfoList[index].bufferDataList = bufferData; 220 } 221 222 template<class VertexType> 223 void GraphicsPipeline_Vulkan<VertexType>::createPipeline(string vertShaderFile, string fragShaderFile) { 249 224 this->vertShaderFile = vertShaderFile; 250 225 this->fragShaderFile = fragShaderFile; … … 386 361 } 387 362 388 template<class VertexType , class SSBOType>389 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::createDescriptorSetLayout() {363 template<class VertexType> 364 void GraphicsPipeline_Vulkan<VertexType>::createDescriptorSetLayout() { 390 365 vector<VkDescriptorSetLayoutBinding> bindings(this->descriptorInfoList.size()); 391 366 … … 408 383 } 409 384 410 template<class VertexType , class SSBOType>411 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::createDescriptorPool(vector<VkImage>& swapChainImages) {385 template<class VertexType> 386 void GraphicsPipeline_Vulkan<VertexType>::createDescriptorPool(vector<VkImage>& swapChainImages) { 412 387 vector<VkDescriptorPoolSize> poolSizes(this->descriptorInfoList.size()); 413 388 … … 429 404 430 405 // TODO: Since I only need the size of the swapChainImages array, I should just pass that in instead of the whole array 431 template<class VertexType , class SSBOType>432 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::createDescriptorSets(vector<VkImage>& swapChainImages) {406 template<class VertexType> 407 void GraphicsPipeline_Vulkan<VertexType>::createDescriptorSets(vector<VkImage>& swapChainImages) { 433 408 vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), this->descriptorSetLayout); 434 409 … … 476 451 } 477 452 478 template<class VertexType, class SSBOType> 479 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createRenderCommands(VkCommandBuffer& commandBuffer, 480 uint32_t currentImage) { 481 453 template<class VertexType> 454 void GraphicsPipeline_Vulkan<VertexType>::createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage) { 482 455 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); 483 456 … … 494 467 } 495 468 496 template<class VertexType, class SSBOType> 497 bool GraphicsPipeline_Vulkan<VertexType, SSBOType>::addObject( 498 const vector<VertexType>& vertices, vector<uint16_t> indices, 499 SSBOType& ssbo, VkCommandPool commandPool, VkQueue graphicsQueue) { 500 469 template<class VertexType> 470 void GraphicsPipeline_Vulkan<VertexType>::addObject(const vector<VertexType>& vertices, vector<uint16_t> indices, 471 VkCommandPool commandPool, VkQueue graphicsQueue) { 501 472 // TODO: When resizing the vertex or index buffer, take deleted objects into account. 502 473 // Remove their data from the buffer and determine the new size of the bufer based on # of remining objects … … 522 493 this->indexBuffer, this->numIndices, graphicsQueue); 523 494 this->numIndices += indices.size(); 524 525 bool resizedStorageBuffer = false;526 527 if (!is_same_v<SSBOType, void*>) {528 if (this->numObjects == this->objectCapacity) {529 resizeStorageBufferSet(storageBufferSet, commandPool, graphicsQueue);530 cleanup();531 532 // Assume the SSBO is always the 2nd binding533 this->descriptorInfoList[1].bufferDataList = &storageBufferSet.infoSet;534 resizedStorageBuffer = true;535 536 cout << "SSBO resized, New object capacity: " << this->objectCapacity << endl;537 538 // TODO: I'll need to correctly update the descriptor set array instead of appending to it539 // Then, I'll have to call createDescriptorSets() and finally createCommandBuffers() (from vulkan-game)540 // This isn't too bad actually, since I have to call createCommandBuffers() every time I add a newobject541 // anyway. So, in this function, I'll just have to call createDescriptorSets()542 }543 544 updateObject(this->numObjects, ssbo);545 }546 547 this->numObjects++;548 549 return resizedStorageBuffer;550 }551 552 // TODO: Allow a swapchain index to be passed in instead of updating all of them553 // Actually, since I'm in the process of replacing SSBOs with dynamic UBOs, I can ignore that for this function554 template<class VertexType, class SSBOType>555 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::updateObject(size_t objIndex, SSBOType& ssbo) {556 if (!is_same_v<SSBOType, void*>) {557 for (size_t i = 0; i < storageBufferSet.memory.size(); i++) {558 VulkanUtils::copyDataToMemory(this->device, ssbo, storageBufferSet.memory[i], objIndex * sizeof(SSBOType));559 }560 }561 495 } 562 496 563 497 // Should only be used if the number of vertices has not changed 564 template<class VertexType , class SSBOType>565 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::updateObjectVertices(size_t objIndex,498 template<class VertexType> 499 void GraphicsPipeline_Vulkan<VertexType>::updateObjectVertices(size_t objIndex, 566 500 const vector<VertexType>& vertices, VkCommandPool commandPool, VkQueue graphicsQueue) { 567 501 VulkanUtils::copyDataToBuffer(this->device, this->physicalDevice, commandPool, vertices, … … 569 503 } 570 504 571 template<class VertexType , class SSBOType>572 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::cleanup() {505 template<class VertexType> 506 void GraphicsPipeline_Vulkan<VertexType>::cleanup() { 573 507 vkDestroyPipeline(device, pipeline, nullptr); 574 508 vkDestroyDescriptorPool(device, descriptorPool, nullptr); … … 579 513 } 580 514 581 template<class VertexType , class SSBOType>582 void GraphicsPipeline_Vulkan<VertexType , SSBOType>::cleanupBuffers() {515 template<class VertexType> 516 void GraphicsPipeline_Vulkan<VertexType>::cleanupBuffers() { 583 517 vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); 584 518 … … 587 521 vkDestroyBuffer(device, indexBuffer, nullptr); 588 522 vkFreeMemory(device, indexBufferMemory, nullptr); 589 590 if (!is_same_v<SSBOType, void*>) {591 for (size_t i = 0; i < storageBufferSet.buffers.size(); i++) {592 vkDestroyBuffer(device, storageBufferSet.buffers[i], nullptr);593 vkFreeMemory(device, storageBufferSet.memory[i], nullptr);594 }595 }596 523 } 597 524 598 525 /*** PRIVATE METHODS ***/ 599 526 600 template<class VertexType , class SSBOType>601 VkShaderModule GraphicsPipeline_Vulkan<VertexType , SSBOType>::createShaderModule(const vector<char>& code) {527 template<class VertexType> 528 VkShaderModule GraphicsPipeline_Vulkan<VertexType>::createShaderModule(const vector<char>& code) { 602 529 VkShaderModuleCreateInfo createInfo = {}; 603 530 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; … … 613 540 } 614 541 615 template<class VertexType , class SSBOType>616 vector<char> GraphicsPipeline_Vulkan<VertexType , SSBOType>::readFile(const string& filename) {542 template<class VertexType> 543 vector<char> GraphicsPipeline_Vulkan<VertexType>::readFile(const string& filename) { 617 544 ifstream file(filename, ios::ate | ios::binary); 618 545 … … 632 559 } 633 560 634 template<class VertexType, class SSBOType> 635 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeVertexBuffer(VkCommandPool commandPool, 636 VkQueue graphicsQueue) { 561 template<class VertexType> 562 void GraphicsPipeline_Vulkan<VertexType>::resizeVertexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue) { 637 563 VkBuffer newVertexBuffer; 638 564 VkDeviceMemory newVertexBufferMemory; … … 652 578 } 653 579 654 template<class VertexType, class SSBOType> 655 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeIndexBuffer(VkCommandPool commandPool, 656 VkQueue graphicsQueue) { 580 template<class VertexType> 581 void GraphicsPipeline_Vulkan<VertexType>::resizeIndexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue) { 657 582 VkBuffer newIndexBuffer; 658 583 VkDeviceMemory newIndexBufferMemory; … … 672 597 } 673 598 674 template<class VertexType, class SSBOType>675 void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeStorageBufferSet(StorageBufferSet& set,676 VkCommandPool commandPool, VkQueue graphicsQueue) {677 this->objectCapacity *= 2;678 VkDeviceSize bufferSize = objectCapacity * sizeof(SSBOType);679 680 for (size_t i = 0; i < set.buffers.size(); i++) {681 VkBuffer newStorageBuffer;682 VkDeviceMemory newStorageBufferMemory;683 684 VulkanUtils::createBuffer(this->device, this->physicalDevice, bufferSize,685 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,686 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,687 newStorageBuffer, newStorageBufferMemory);688 689 VulkanUtils::copyBuffer(this->device, commandPool, set.buffers[i], newStorageBuffer,690 0, 0, this->numObjects * sizeof(SSBOType), graphicsQueue);691 692 vkDestroyBuffer(this->device, set.buffers[i], nullptr);693 vkFreeMemory(this->device, set.memory[i], nullptr);694 695 set.buffers[i] = newStorageBuffer;696 set.memory[i] = newStorageBufferMemory;697 698 set.infoSet[i].buffer = set.buffers[i];699 set.infoSet[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now700 set.infoSet[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE701 }702 }703 704 599 #endif // _GRAPHICS_PIPELINE_VULKAN_H
Note:
See TracChangeset
for help on using the changeset viewer.