source: opengl-game/graphics-pipeline_vulkan.hpp@ 860a0da

feature/imgui-sdl points-test
Last change on this file since 860a0da was 860a0da, checked in by Dmitry Portnoy <dmitry.portnoy@…>, 5 years ago

In VulkanGame, move fields related to the ssbo, as well as code to create thee ssbo, destroy it, and create a descriptor for it, into GraphicsPipeline_Vulkan

  • Property mode set to 100644
File size: 24.4 KB
RevLine 
[7d2b0b9]1#ifndef _GRAPHICS_PIPELINE_VULKAN_H
2#define _GRAPHICS_PIPELINE_VULKAN_H
3
4#include "graphics-pipeline.hpp"
5
[b8777b7]6#include <fstream>
[860a0da]7#include <iostream>
[cd487fb]8#include <stdexcept>
[7d2b0b9]9#include <vector>
10
[771b33a]11#include <vulkan/vulkan.h>
12
[cd1cb0f]13#define GLM_FORCE_RADIANS
14#define GLM_FORCE_DEPTH_ZERO_TO_ONE // Since, in Vulkan, the depth range is 0 to 1 instead of -1 to 1
15#define GLM_FORCE_RIGHT_HANDED
16
17#include <glm/glm.hpp>
18#include <glm/gtc/matrix_transform.hpp>
19
[e3bef3a]20#include "vulkan-utils.hpp"
21
[cd1cb0f]22using namespace glm;
23
[b794178]24// TODO: Maybe change the name of this struct so I can call the list something other than descriptorInfoList
25struct DescriptorInfo {
26 VkDescriptorType type;
27 VkShaderStageFlags stageFlags;
28
29 // Only one of the below properties should be set
30 vector<VkDescriptorBufferInfo>* bufferDataList;
31 VkDescriptorImageInfo* imageData;
32};
33
[860a0da]34struct StorageBufferSet {
35 vector<VkBuffer> buffers;
36 vector<VkDeviceMemory> memory;
37 vector<VkDescriptorBufferInfo> infoSet;
38};
39
[2d87297]40template<class VertexType, class SSBOType>
[7d2b0b9]41class GraphicsPipeline_Vulkan : public GraphicsPipeline {
42 public:
[b8777b7]43 GraphicsPipeline_Vulkan();
[860a0da]44
45 // TODO: swapChainImages is only ever used to get its size. Check how that is determined and,
46 // if it will never change, just pass it in the constructor and save it
47 // If it does change, I could add an updateSwapchainImageCount() function
[87c8f1a]48 GraphicsPipeline_Vulkan(VkPhysicalDevice physicalDevice, VkDevice device, VkRenderPass renderPass,
[860a0da]49 Viewport viewport, vector<VkImage>& swapChainImages,
50 size_t vertexCapacity, size_t indexCapacity, size_t objectCapacity);
[7d2b0b9]51 ~GraphicsPipeline_Vulkan();
52
[0fe8433]53 size_t getNumVertices();
54
[0ae182f]55 void updateRenderPass(VkRenderPass renderPass);
56
[b794178]57 // Maybe I should rename these to addVertexAttribute (addVaryingAttribute) and addUniformAttribute
58
[771b33a]59 void addAttribute(VkFormat format, size_t offset);
[b794178]60
[860a0da]61 void addStorageDescriptor();
62
[b794178]63 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData);
64 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData);
65
[7d2b0b9]66 void createPipeline(string vertShaderFile, string fragShaderFile);
[b794178]67 void createDescriptorSetLayout();
68 void createDescriptorPool(vector<VkImage>& swapChainImages);
69 void createDescriptorSets(vector<VkImage>& swapChainImages);
70
[603b5bc]71 void createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage);
72
[0fe8433]73 void addVertices(const vector<VertexType>& vertices, vector<uint16_t> indices, VkCommandPool commandPool,
[e3bef3a]74 VkQueue graphicsQueue);
75
[b794178]76 void cleanup();
77 void cleanupBuffers();
[860a0da]78
79 StorageBufferSet storageBufferSet;
[7d2b0b9]80
81 private:
[87c8f1a]82 VkPhysicalDevice physicalDevice;
[7d2b0b9]83 VkDevice device;
[b794178]84 VkRenderPass renderPass;
85
86 VkPipeline pipeline;
87 VkPipelineLayout pipelineLayout;
88
[771b33a]89 VkVertexInputBindingDescription bindingDescription;
[b794178]90
[771b33a]91 vector<VkVertexInputAttributeDescription> attributeDescriptions;
[b794178]92 vector<DescriptorInfo> descriptorInfoList;
[7d2b0b9]93
[b794178]94 VkDescriptorSetLayout descriptorSetLayout;
95 VkDescriptorPool descriptorPool;
96 vector<VkDescriptorSet> descriptorSets;
[87c8f1a]97
98 size_t numVertices;
99 size_t vertexCapacity;
100 VkBuffer vertexBuffer;
101 VkDeviceMemory vertexBufferMemory;
102
103 size_t numIndices;
104 size_t indexCapacity;
105 VkBuffer indexBuffer;
106 VkDeviceMemory indexBufferMemory;
[b8777b7]107
[860a0da]108 size_t numObjects;
109 size_t objectCapacity;
110
[b8777b7]111 VkShaderModule createShaderModule(const vector<char>& code);
112 vector<char> readFile(const string& filename);
113
[5a0242e]114 void resizeVertexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue);
115 void resizeIndexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue);
[7d2b0b9]116};
117
[b8777b7]118/*** PUBLIC METHODS ***/
119
[2d87297]120template<class VertexType, class SSBOType>
121GraphicsPipeline_Vulkan<VertexType, SSBOType>::GraphicsPipeline_Vulkan() {
[b8777b7]122}
123
[683dd55]124// TODO: Verify that vertex capacity and index capacity are both > 0
[2d87297]125template<class VertexType, class SSBOType>
126GraphicsPipeline_Vulkan<VertexType, SSBOType>::GraphicsPipeline_Vulkan(
127 VkPhysicalDevice physicalDevice, VkDevice device,
[860a0da]128 VkRenderPass renderPass, Viewport viewport, vector<VkImage>& swapChainImages,
129 size_t vertexCapacity, size_t indexCapacity, size_t objectCapacity) {
[b8777b7]130 this->physicalDevice = physicalDevice;
131 this->device = device;
132 this->renderPass = renderPass;
133 this->viewport = viewport;
134
135 // Since there is only one array of vertex data, we use binding = 0
136 // I'll probably do that for the foreseeable future
137 // I can calculate the stride myself given info about all the varying attributes
138 this->bindingDescription.binding = 0;
[5a0242e]139 this->bindingDescription.stride = sizeof(VertexType);
[b8777b7]140 this->bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
141
[5a0242e]142 this->numVertices = 0;
143 this->vertexCapacity = vertexCapacity;
[b8777b7]144
[5a0242e]145 VulkanUtils::createBuffer(device, physicalDevice, vertexCapacity * sizeof(VertexType),
146 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
147 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
[e3bef3a]148
[5a0242e]149 this->numIndices = 0;
150 this->indexCapacity = indexCapacity;
[87c8f1a]151
[5a0242e]152 VulkanUtils::createBuffer(device, physicalDevice, indexCapacity * sizeof(uint16_t),
153 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
154 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
[860a0da]155
156 this->numObjects = 0;
157 this->objectCapacity = objectCapacity;
158
159 // Hacky way to allow an SSBO to be optional
160 // Specifying void* as the SSBOType will skip allocating the related buffers
161 if (!is_same_v<SSBOType, void*>) {
162 VkDeviceSize bufferSize = objectCapacity * sizeof(SSBOType);
163 cout << "NUM SWAP CHAIN IMAGES: " << swapChainImages.size() << endl;
164
165 storageBufferSet.buffers.resize(swapChainImages.size());
166 storageBufferSet.memory.resize(swapChainImages.size());
167 storageBufferSet.infoSet.resize(swapChainImages.size());
168
169 for (size_t i = 0; i < swapChainImages.size(); i++) {
170 VulkanUtils::createBuffer(this->device, this->physicalDevice, bufferSize,
171 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
172 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
173 storageBufferSet.buffers[i], storageBufferSet.memory[i]);
174
175 storageBufferSet.infoSet[i].buffer = storageBufferSet.buffers[i];
176 storageBufferSet.infoSet[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now
177 storageBufferSet.infoSet[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE
178 }
179 }
[e3bef3a]180}
181
[860a0da]182// TODO: Move as much cleanup as I can into the destructor
[2d87297]183template<class VertexType, class SSBOType>
184GraphicsPipeline_Vulkan<VertexType, SSBOType>::~GraphicsPipeline_Vulkan() {
[b8777b7]185}
186
[2d87297]187template<class VertexType, class SSBOType>
188size_t GraphicsPipeline_Vulkan<VertexType, SSBOType>::getNumVertices() {
[0fe8433]189 return numVertices;
190}
191
[2d87297]192template<class VertexType, class SSBOType>
193void GraphicsPipeline_Vulkan<VertexType, SSBOType>::updateRenderPass(VkRenderPass renderPass) {
[5a0242e]194 this->renderPass = renderPass;
[b8777b7]195}
196
[2d87297]197template<class VertexType, class SSBOType>
198void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addAttribute(VkFormat format, size_t offset) {
[b8777b7]199 VkVertexInputAttributeDescription attributeDesc = {};
200
201 attributeDesc.binding = 0;
202 attributeDesc.location = this->attributeDescriptions.size();
203 attributeDesc.format = format;
204 attributeDesc.offset = offset;
205
206 this->attributeDescriptions.push_back(attributeDesc);
207}
208
[2d87297]209template<class VertexType, class SSBOType>
[860a0da]210void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addStorageDescriptor() {
211 if (!is_same_v<SSBOType, void*>) {
212 addDescriptorInfo(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
213 VK_SHADER_STAGE_VERTEX_BIT, &storageBufferSet.infoSet);
214 }
215}
216
217template<class VertexType, class SSBOType>
218void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addDescriptorInfo(VkDescriptorType type,
219 VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) {
[b8777b7]220 this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr });
221}
222
[2d87297]223template<class VertexType, class SSBOType>
[860a0da]224void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addDescriptorInfo(VkDescriptorType type,
225 VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) {
[b8777b7]226 this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData });
227}
228
[2d87297]229template<class VertexType, class SSBOType>
230void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createPipeline(string vertShaderFile, string fragShaderFile) {
[b8777b7]231 vector<char> vertShaderCode = readFile(vertShaderFile);
232 vector<char> fragShaderCode = readFile(fragShaderFile);
233
234 VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
235 VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
236
237 VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
238 vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
239 vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
240 vertShaderStageInfo.module = vertShaderModule;
241 vertShaderStageInfo.pName = "main";
242
243 VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
244 fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
245 fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
246 fragShaderStageInfo.module = fragShaderModule;
247 fragShaderStageInfo.pName = "main";
248
249 VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
250
251 VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
252 vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
253
254 vertexInputInfo.vertexBindingDescriptionCount = 1;
255 vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(this->attributeDescriptions.size());
256 vertexInputInfo.pVertexBindingDescriptions = &this->bindingDescription;
257 vertexInputInfo.pVertexAttributeDescriptions = this->attributeDescriptions.data();
258
259 VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
260 inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
261 inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
262 inputAssembly.primitiveRestartEnable = VK_FALSE;
263
264 VkViewport viewport = {};
265 viewport.x = (float)this->viewport.x;
266 viewport.y = (float)this->viewport.y;
267 viewport.width = (float)this->viewport.width;
268 viewport.height = (float)this->viewport.height;
269 viewport.minDepth = 0.0f;
270 viewport.maxDepth = 1.0f;
271
272 VkRect2D scissor = {};
273 scissor.offset = { 0, 0 };
274 scissor.extent = { (uint32_t)this->viewport.width, (uint32_t)this->viewport.height };
275
276 VkPipelineViewportStateCreateInfo viewportState = {};
277 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
278 viewportState.viewportCount = 1;
279 viewportState.pViewports = &viewport;
280 viewportState.scissorCount = 1;
281 viewportState.pScissors = &scissor;
282
283 VkPipelineRasterizationStateCreateInfo rasterizer = {};
284 rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
285 rasterizer.depthClampEnable = VK_FALSE;
286 rasterizer.rasterizerDiscardEnable = VK_FALSE;
287 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
288 rasterizer.lineWidth = 1.0f;
289 rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
290 rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
291 rasterizer.depthBiasEnable = VK_FALSE;
292
293 VkPipelineMultisampleStateCreateInfo multisampling = {};
294 multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
295 multisampling.sampleShadingEnable = VK_FALSE;
296 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
297
298 VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
299 colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
300 colorBlendAttachment.blendEnable = VK_TRUE;
301 colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
302 colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
303 colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
304 colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
305 colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
306 colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
307
308 VkPipelineColorBlendStateCreateInfo colorBlending = {};
309 colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
310 colorBlending.logicOpEnable = VK_FALSE;
311 colorBlending.logicOp = VK_LOGIC_OP_COPY;
312 colorBlending.attachmentCount = 1;
313 colorBlending.pAttachments = &colorBlendAttachment;
314 colorBlending.blendConstants[0] = 0.0f;
315 colorBlending.blendConstants[1] = 0.0f;
316 colorBlending.blendConstants[2] = 0.0f;
317 colorBlending.blendConstants[3] = 0.0f;
318
319 VkPipelineDepthStencilStateCreateInfo depthStencil = {};
320 depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
321 depthStencil.depthTestEnable = VK_TRUE;
322 depthStencil.depthWriteEnable = VK_TRUE;
323 depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
324 depthStencil.depthBoundsTestEnable = VK_FALSE;
325 depthStencil.minDepthBounds = 0.0f;
326 depthStencil.maxDepthBounds = 1.0f;
327 depthStencil.stencilTestEnable = VK_FALSE;
328 depthStencil.front = {};
329 depthStencil.back = {};
330
331 VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
332 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
333 pipelineLayoutInfo.setLayoutCount = 1;
334 pipelineLayoutInfo.pSetLayouts = &this->descriptorSetLayout;
335 pipelineLayoutInfo.pushConstantRangeCount = 0;
336
337 if (vkCreatePipelineLayout(this->device, &pipelineLayoutInfo, nullptr, &this->pipelineLayout) != VK_SUCCESS) {
338 throw runtime_error("failed to create pipeline layout!");
339 }
340
341 VkGraphicsPipelineCreateInfo pipelineInfo = {};
342 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
343 pipelineInfo.stageCount = 2;
344 pipelineInfo.pStages = shaderStages;
345 pipelineInfo.pVertexInputState = &vertexInputInfo;
346 pipelineInfo.pInputAssemblyState = &inputAssembly;
347 pipelineInfo.pViewportState = &viewportState;
348 pipelineInfo.pRasterizationState = &rasterizer;
349 pipelineInfo.pMultisampleState = &multisampling;
350 pipelineInfo.pDepthStencilState = &depthStencil;
351 pipelineInfo.pColorBlendState = &colorBlending;
352 pipelineInfo.pDynamicState = nullptr;
353 pipelineInfo.layout = this->pipelineLayout;
354 pipelineInfo.renderPass = this->renderPass;
355 pipelineInfo.subpass = 0;
356 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
357 pipelineInfo.basePipelineIndex = -1;
358
359 if (vkCreateGraphicsPipelines(this->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &this->pipeline) != VK_SUCCESS) {
360 throw runtime_error("failed to create graphics pipeline!");
361 }
362
363 vkDestroyShaderModule(this->device, vertShaderModule, nullptr);
364 vkDestroyShaderModule(this->device, fragShaderModule, nullptr);
365}
366
[2d87297]367template<class VertexType, class SSBOType>
368void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorSetLayout() {
[b8777b7]369 vector<VkDescriptorSetLayoutBinding> bindings(this->descriptorInfoList.size());
370
371 for (size_t i = 0; i < bindings.size(); i++) {
372 bindings[i].binding = i;
373 bindings[i].descriptorCount = 1;
374 bindings[i].descriptorType = this->descriptorInfoList[i].type;
375 bindings[i].stageFlags = this->descriptorInfoList[i].stageFlags;
376 bindings[i].pImmutableSamplers = nullptr;
377 }
378
379 VkDescriptorSetLayoutCreateInfo layoutInfo = {};
380 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
381 layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
382 layoutInfo.pBindings = bindings.data();
383
384 if (vkCreateDescriptorSetLayout(this->device, &layoutInfo, nullptr, &this->descriptorSetLayout) != VK_SUCCESS) {
385 throw runtime_error("failed to create descriptor set layout!");
386 }
387}
388
[2d87297]389template<class VertexType, class SSBOType>
390void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorPool(vector<VkImage>& swapChainImages) {
[b8777b7]391 vector<VkDescriptorPoolSize> poolSizes(this->descriptorInfoList.size());
392
393 for (size_t i = 0; i < poolSizes.size(); i++) {
394 poolSizes[i].type = this->descriptorInfoList[i].type;
395 poolSizes[i].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
396 }
397
398 VkDescriptorPoolCreateInfo poolInfo = {};
399 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
400 poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
401 poolInfo.pPoolSizes = poolSizes.data();
402 poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
403
404 if (vkCreateDescriptorPool(this->device, &poolInfo, nullptr, &this->descriptorPool) != VK_SUCCESS) {
405 throw runtime_error("failed to create descriptor pool!");
406 }
407}
408
[860a0da]409// TODO: Since I only need the size of the swapChainImages array, I should just pass that in instead of the whole array
[2d87297]410template<class VertexType, class SSBOType>
411void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorSets(vector<VkImage>& swapChainImages) {
[b8777b7]412 vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), this->descriptorSetLayout);
413
414 VkDescriptorSetAllocateInfo allocInfo = {};
415 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
416 allocInfo.descriptorPool = this->descriptorPool;
417 allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
418 allocInfo.pSetLayouts = layouts.data();
419
420 this->descriptorSets.resize(swapChainImages.size());
421 if (vkAllocateDescriptorSets(device, &allocInfo, this->descriptorSets.data()) != VK_SUCCESS) {
422 throw runtime_error("failed to allocate descriptor sets!");
423 }
[e3bef3a]424
[b8777b7]425 for (size_t i = 0; i < swapChainImages.size(); i++) {
426 vector<VkWriteDescriptorSet> descriptorWrites(this->descriptorInfoList.size());
427
428 for (size_t j = 0; j < descriptorWrites.size(); j++) {
429 descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
430 descriptorWrites[j].dstSet = this->descriptorSets[i];
431 descriptorWrites[j].dstBinding = j;
432 descriptorWrites[j].dstArrayElement = 0;
433 descriptorWrites[j].descriptorType = this->descriptorInfoList[j].type;
434 descriptorWrites[j].descriptorCount = 1;
435 descriptorWrites[j].pBufferInfo = nullptr;
436 descriptorWrites[j].pImageInfo = nullptr;
437 descriptorWrites[j].pTexelBufferView = nullptr;
438
439 switch (descriptorWrites[j].descriptorType) {
440 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
[055750a]441 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
[b8777b7]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 }
[e3bef3a]450 }
451
[b8777b7]452 vkUpdateDescriptorSets(this->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
453 }
454}
455
[2d87297]456template<class VertexType, class SSBOType>
[860a0da]457void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createRenderCommands(VkCommandBuffer& commandBuffer,
458 uint32_t currentImage) {
[b8777b7]459 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
460 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1,
461 &descriptorSets[currentImage], 0, nullptr);
462
463 VkBuffer vertexBuffers[] = { vertexBuffer };
464 VkDeviceSize offsets[] = { 0 };
465 vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
466
467 vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
468
469 vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(numIndices), 1, 0, 0, 0);
470}
471
[2d87297]472template<class VertexType, class SSBOType>
473void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addVertices(const vector<VertexType>& vertices, vector<uint16_t> indices,
[b8777b7]474 VkCommandPool commandPool, VkQueue graphicsQueue) {
475
[5a0242e]476 if (numVertices + vertices.size() > vertexCapacity) {
477 resizeVertexBuffer(commandPool, graphicsQueue);
478 }
479 if (numIndices + indices.size() > indexCapacity) {
480 resizeIndexBuffer(commandPool, graphicsQueue);
[b8777b7]481 }
482
483 VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, vertices, vertexBuffer, numVertices,
484 graphicsQueue);
485 numVertices += vertices.size();
486
487 VulkanUtils::copyDataToBuffer(device, physicalDevice, commandPool, indices, indexBuffer, numIndices,
488 graphicsQueue);
489 numIndices += indices.size();
490}
491
[2d87297]492template<class VertexType, class SSBOType>
493void GraphicsPipeline_Vulkan<VertexType, SSBOType>::cleanup() {
[b8777b7]494 vkDestroyPipeline(device, pipeline, nullptr);
495 vkDestroyDescriptorPool(device, descriptorPool, nullptr);
[860a0da]496
497 // TODO: I read that the pipeline layout does not have to be recreated every time
498 // Try only creating it once
[b8777b7]499 vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
500}
501
[2d87297]502template<class VertexType, class SSBOType>
503void GraphicsPipeline_Vulkan<VertexType, SSBOType>::cleanupBuffers() {
[b8777b7]504 vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
505
506 vkDestroyBuffer(device, vertexBuffer, nullptr);
507 vkFreeMemory(device, vertexBufferMemory, nullptr);
508 vkDestroyBuffer(device, indexBuffer, nullptr);
509 vkFreeMemory(device, indexBufferMemory, nullptr);
[860a0da]510
511 if (!is_same_v<SSBOType, void*>) {
512 for (size_t i = 0; i < storageBufferSet.buffers.size(); i++) {
513 vkDestroyBuffer(device, storageBufferSet.buffers[i], nullptr);
514 vkFreeMemory(device, storageBufferSet.memory[i], nullptr);
515 }
516 }
[b8777b7]517}
518
519/*** PRIVATE METHODS ***/
520
[2d87297]521template<class VertexType, class SSBOType>
522VkShaderModule GraphicsPipeline_Vulkan<VertexType, SSBOType>::createShaderModule(const vector<char>& code) {
[b8777b7]523 VkShaderModuleCreateInfo createInfo = {};
524 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
525 createInfo.codeSize = code.size();
526 createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
527
528 VkShaderModule shaderModule;
529 if (vkCreateShaderModule(this->device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
530 throw runtime_error("failed to create shader module!");
531 }
532
533 return shaderModule;
534}
[e3bef3a]535
[2d87297]536template<class VertexType, class SSBOType>
537vector<char> GraphicsPipeline_Vulkan<VertexType, SSBOType>::readFile(const string& filename) {
[b8777b7]538 ifstream file(filename, ios::ate | ios::binary);
[e3bef3a]539
[b8777b7]540 if (!file.is_open()) {
541 throw runtime_error("failed to open file!");
[e3bef3a]542 }
543
[b8777b7]544 size_t fileSize = (size_t)file.tellg();
545 vector<char> buffer(fileSize);
546
547 file.seekg(0);
548 file.read(buffer.data(), fileSize);
549
550 file.close();
551
552 return buffer;
553}
554
[2d87297]555template<class VertexType, class SSBOType>
[860a0da]556void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeVertexBuffer(VkCommandPool commandPool,
557 VkQueue graphicsQueue) {
[5a0242e]558 VkBuffer newVertexBuffer;
559 VkDeviceMemory newVertexBufferMemory;
[860a0da]560 this->vertexCapacity *= 2;
[5a0242e]561
[860a0da]562 VulkanUtils::createBuffer(this->device, this->physicalDevice, this->vertexCapacity * sizeof(VertexType),
[5a0242e]563 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
564 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, newVertexBuffer, newVertexBufferMemory);
565
[860a0da]566 VulkanUtils::copyBuffer(this->device, commandPool, vertexBuffer, newVertexBuffer, 0, 0, numVertices * sizeof(VertexType), graphicsQueue);
[5a0242e]567
[860a0da]568 vkDestroyBuffer(this->device, vertexBuffer, nullptr);
569 vkFreeMemory(this->device, vertexBufferMemory, nullptr);
[b8777b7]570
[5a0242e]571 vertexBuffer = newVertexBuffer;
572 vertexBufferMemory = newVertexBufferMemory;
573}
[b8777b7]574
[2d87297]575template<class VertexType, class SSBOType>
[860a0da]576void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeIndexBuffer(VkCommandPool commandPool,
577 VkQueue graphicsQueue) {
[5a0242e]578 VkBuffer newIndexBuffer;
579 VkDeviceMemory newIndexBufferMemory;
[860a0da]580 this->indexCapacity *= 2;
[b8777b7]581
[860a0da]582 VulkanUtils::createBuffer(this->device, this->physicalDevice, this->indexCapacity * sizeof(uint16_t),
[5a0242e]583 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
584 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, newIndexBuffer, newIndexBufferMemory);
585
[860a0da]586 VulkanUtils::copyBuffer(this->device, commandPool, indexBuffer, newIndexBuffer, 0, 0, numIndices * sizeof(uint16_t), graphicsQueue);
[5a0242e]587
[860a0da]588 vkDestroyBuffer(this->device, indexBuffer, nullptr);
589 vkFreeMemory(this->device, indexBufferMemory, nullptr);
[5a0242e]590
591 indexBuffer = newIndexBuffer;
592 indexBufferMemory = newIndexBufferMemory;
[87c8f1a]593}
594
[7d2b0b9]595#endif // _GRAPHICS_PIPELINE_VULKAN_H
Note: See TracBrowser for help on using the repository browser.