source: opengl-game/graphics-pipeline_vulkan.hpp@ b8777b7

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

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

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