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
Line 
1#ifndef _GRAPHICS_PIPELINE_VULKAN_H
2#define _GRAPHICS_PIPELINE_VULKAN_H
3
4#include "graphics-pipeline.hpp"
5
6#include <fstream>
7#include <iostream>
8#include <stdexcept>
9#include <vector>
10
11#include <vulkan/vulkan.h>
12
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
20#include "vulkan-utils.hpp"
21
22using namespace glm;
23
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
34struct StorageBufferSet {
35 vector<VkBuffer> buffers;
36 vector<VkDeviceMemory> memory;
37 vector<VkDescriptorBufferInfo> infoSet;
38};
39
40template<class VertexType, class SSBOType>
41class GraphicsPipeline_Vulkan : public GraphicsPipeline {
42 public:
43 GraphicsPipeline_Vulkan();
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
48 GraphicsPipeline_Vulkan(VkPhysicalDevice physicalDevice, VkDevice device, VkRenderPass renderPass,
49 Viewport viewport, vector<VkImage>& swapChainImages,
50 size_t vertexCapacity, size_t indexCapacity, size_t objectCapacity);
51 ~GraphicsPipeline_Vulkan();
52
53 size_t getNumVertices();
54
55 void updateRenderPass(VkRenderPass renderPass);
56
57 // Maybe I should rename these to addVertexAttribute (addVaryingAttribute) and addUniformAttribute
58
59 void addAttribute(VkFormat format, size_t offset);
60
61 void addStorageDescriptor();
62
63 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData);
64 void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData);
65
66 void createPipeline(string vertShaderFile, string fragShaderFile);
67 void createDescriptorSetLayout();
68 void createDescriptorPool(vector<VkImage>& swapChainImages);
69 void createDescriptorSets(vector<VkImage>& swapChainImages);
70
71 void createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage);
72
73 void addVertices(const vector<VertexType>& vertices, vector<uint16_t> indices, VkCommandPool commandPool,
74 VkQueue graphicsQueue);
75
76 void cleanup();
77 void cleanupBuffers();
78
79 StorageBufferSet storageBufferSet;
80
81 private:
82 VkPhysicalDevice physicalDevice;
83 VkDevice device;
84 VkRenderPass renderPass;
85
86 VkPipeline pipeline;
87 VkPipelineLayout pipelineLayout;
88
89 VkVertexInputBindingDescription bindingDescription;
90
91 vector<VkVertexInputAttributeDescription> attributeDescriptions;
92 vector<DescriptorInfo> descriptorInfoList;
93
94 VkDescriptorSetLayout descriptorSetLayout;
95 VkDescriptorPool descriptorPool;
96 vector<VkDescriptorSet> descriptorSets;
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;
107
108 size_t numObjects;
109 size_t objectCapacity;
110
111 VkShaderModule createShaderModule(const vector<char>& code);
112 vector<char> readFile(const string& filename);
113
114 void resizeVertexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue);
115 void resizeIndexBuffer(VkCommandPool commandPool, VkQueue graphicsQueue);
116};
117
118/*** PUBLIC METHODS ***/
119
120template<class VertexType, class SSBOType>
121GraphicsPipeline_Vulkan<VertexType, SSBOType>::GraphicsPipeline_Vulkan() {
122}
123
124// TODO: Verify that vertex capacity and index capacity are both > 0
125template<class VertexType, class SSBOType>
126GraphicsPipeline_Vulkan<VertexType, SSBOType>::GraphicsPipeline_Vulkan(
127 VkPhysicalDevice physicalDevice, VkDevice device,
128 VkRenderPass renderPass, Viewport viewport, vector<VkImage>& swapChainImages,
129 size_t vertexCapacity, size_t indexCapacity, size_t objectCapacity) {
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;
139 this->bindingDescription.stride = sizeof(VertexType);
140 this->bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
141
142 this->numVertices = 0;
143 this->vertexCapacity = vertexCapacity;
144
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);
148
149 this->numIndices = 0;
150 this->indexCapacity = indexCapacity;
151
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);
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 }
180}
181
182// TODO: Move as much cleanup as I can into the destructor
183template<class VertexType, class SSBOType>
184GraphicsPipeline_Vulkan<VertexType, SSBOType>::~GraphicsPipeline_Vulkan() {
185}
186
187template<class VertexType, class SSBOType>
188size_t GraphicsPipeline_Vulkan<VertexType, SSBOType>::getNumVertices() {
189 return numVertices;
190}
191
192template<class VertexType, class SSBOType>
193void GraphicsPipeline_Vulkan<VertexType, SSBOType>::updateRenderPass(VkRenderPass renderPass) {
194 this->renderPass = renderPass;
195}
196
197template<class VertexType, class SSBOType>
198void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addAttribute(VkFormat format, size_t offset) {
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
209template<class VertexType, class SSBOType>
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) {
220 this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr });
221}
222
223template<class VertexType, class SSBOType>
224void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addDescriptorInfo(VkDescriptorType type,
225 VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) {
226 this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData });
227}
228
229template<class VertexType, class SSBOType>
230void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createPipeline(string vertShaderFile, string fragShaderFile) {
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
367template<class VertexType, class SSBOType>
368void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorSetLayout() {
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
389template<class VertexType, class SSBOType>
390void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorPool(vector<VkImage>& swapChainImages) {
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
409// TODO: Since I only need the size of the swapChainImages array, I should just pass that in instead of the whole array
410template<class VertexType, class SSBOType>
411void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createDescriptorSets(vector<VkImage>& swapChainImages) {
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 }
424
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:
441 case VK_DESCRIPTOR_TYPE_STORAGE_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 }
450 }
451
452 vkUpdateDescriptorSets(this->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
453 }
454}
455
456template<class VertexType, class SSBOType>
457void GraphicsPipeline_Vulkan<VertexType, SSBOType>::createRenderCommands(VkCommandBuffer& commandBuffer,
458 uint32_t currentImage) {
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
472template<class VertexType, class SSBOType>
473void GraphicsPipeline_Vulkan<VertexType, SSBOType>::addVertices(const vector<VertexType>& vertices, vector<uint16_t> indices,
474 VkCommandPool commandPool, VkQueue graphicsQueue) {
475
476 if (numVertices + vertices.size() > vertexCapacity) {
477 resizeVertexBuffer(commandPool, graphicsQueue);
478 }
479 if (numIndices + indices.size() > indexCapacity) {
480 resizeIndexBuffer(commandPool, graphicsQueue);
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
492template<class VertexType, class SSBOType>
493void GraphicsPipeline_Vulkan<VertexType, SSBOType>::cleanup() {
494 vkDestroyPipeline(device, pipeline, nullptr);
495 vkDestroyDescriptorPool(device, descriptorPool, nullptr);
496
497 // TODO: I read that the pipeline layout does not have to be recreated every time
498 // Try only creating it once
499 vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
500}
501
502template<class VertexType, class SSBOType>
503void GraphicsPipeline_Vulkan<VertexType, SSBOType>::cleanupBuffers() {
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);
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 }
517}
518
519/*** PRIVATE METHODS ***/
520
521template<class VertexType, class SSBOType>
522VkShaderModule GraphicsPipeline_Vulkan<VertexType, SSBOType>::createShaderModule(const vector<char>& code) {
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}
535
536template<class VertexType, class SSBOType>
537vector<char> GraphicsPipeline_Vulkan<VertexType, SSBOType>::readFile(const string& filename) {
538 ifstream file(filename, ios::ate | ios::binary);
539
540 if (!file.is_open()) {
541 throw runtime_error("failed to open file!");
542 }
543
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
555template<class VertexType, class SSBOType>
556void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeVertexBuffer(VkCommandPool commandPool,
557 VkQueue graphicsQueue) {
558 VkBuffer newVertexBuffer;
559 VkDeviceMemory newVertexBufferMemory;
560 this->vertexCapacity *= 2;
561
562 VulkanUtils::createBuffer(this->device, this->physicalDevice, this->vertexCapacity * sizeof(VertexType),
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
566 VulkanUtils::copyBuffer(this->device, commandPool, vertexBuffer, newVertexBuffer, 0, 0, numVertices * sizeof(VertexType), graphicsQueue);
567
568 vkDestroyBuffer(this->device, vertexBuffer, nullptr);
569 vkFreeMemory(this->device, vertexBufferMemory, nullptr);
570
571 vertexBuffer = newVertexBuffer;
572 vertexBufferMemory = newVertexBufferMemory;
573}
574
575template<class VertexType, class SSBOType>
576void GraphicsPipeline_Vulkan<VertexType, SSBOType>::resizeIndexBuffer(VkCommandPool commandPool,
577 VkQueue graphicsQueue) {
578 VkBuffer newIndexBuffer;
579 VkDeviceMemory newIndexBufferMemory;
580 this->indexCapacity *= 2;
581
582 VulkanUtils::createBuffer(this->device, this->physicalDevice, this->indexCapacity * sizeof(uint16_t),
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
586 VulkanUtils::copyBuffer(this->device, commandPool, indexBuffer, newIndexBuffer, 0, 0, numIndices * sizeof(uint16_t), graphicsQueue);
587
588 vkDestroyBuffer(this->device, indexBuffer, nullptr);
589 vkFreeMemory(this->device, indexBufferMemory, nullptr);
590
591 indexBuffer = newIndexBuffer;
592 indexBufferMemory = newIndexBufferMemory;
593}
594
595#endif // _GRAPHICS_PIPELINE_VULKAN_H
Note: See TracBrowser for help on using the repository browser.