Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanPipeline.cpp
Go to the documentation of this file.
2 
3 #ifdef USING_VULKAN
6 #include <fstream>
7 #include <iostream>
8 #include <stdio.h>
9 
10 namespace Engine {
11 
12  uint32_t VulkanPipeline::pipelineIdCounter = 0;
13 
14  VulkanPipeline::VulkanPipeline(VulkanLogicalDevice* device, VulkanRenderer* renderer)
15  {
16  this->pipelineId = pipelineIdCounter;
17  pipelineIdCounter++;
18 
19  this->device = device;
20  this->renderer = renderer;
21 
22  InputAssemblyStateCreateInfo = {};
23  InputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
24  InputAssemblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
25  InputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
26 
27  vertexInputInfo = {};
28  vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
29  vertexInputInfo.vertexBindingDescriptionCount = 0;
30  vertexInputInfo.pVertexBindingDescriptions = nullptr;
31  vertexInputInfo.vertexAttributeDescriptionCount = 0;
32  vertexInputInfo.pVertexAttributeDescriptions = nullptr;
33 
34  viewport = {};
35  viewport.x = 0.f;
36  viewport.y = 0.f;
37  viewport.width = static_cast<float>(renderer->swapChainImageExtent.width);
38  viewport.height = static_cast<float>(renderer->swapChainImageExtent.height);
39  viewport.minDepth = 0.f;
40  viewport.maxDepth = 1.f;
41 
42  scissor = {};
43  scissor.offset = { 0,0 };
44  scissor.extent = renderer->swapChainImageExtent;
45 
46  rasterizer = {};
47  rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
48  rasterizer.depthClampEnable = VK_FALSE;
49  rasterizer.rasterizerDiscardEnable = VK_FALSE;
50  rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
51  rasterizer.lineWidth = 1.f;
52  rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
53  rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
54  rasterizer.depthBiasEnable = VK_FALSE;
55  rasterizer.depthBiasConstantFactor = 0.f;
56  rasterizer.depthBiasClamp = 0.f;
57  rasterizer.depthBiasSlopeFactor = 0.f;
58 
59  multisampling = {};
60  multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
61  multisampling.sampleShadingEnable = VK_FALSE;
62  multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
63  multisampling.minSampleShading = 1.0f;
64  multisampling.pSampleMask = nullptr;
65  multisampling.alphaToCoverageEnable = VK_FALSE;
66  multisampling.alphaToOneEnable = VK_FALSE;
67 
68  pipelineLayoutCreateInfo = {};
69  pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
70  pipelineLayoutCreateInfo.setLayoutCount = 0;
71  pipelineLayoutCreateInfo.pSetLayouts = nullptr;
72  pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
73  pipelineLayoutCreateInfo.pPushConstantRanges = nullptr;
74 
75  depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
76  depthStencilStateCreateInfo.depthTestEnable = VK_TRUE;
77  depthStencilStateCreateInfo.depthWriteEnable = VK_TRUE;
78  depthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
79  depthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
80  depthStencilStateCreateInfo.minDepthBounds = 0.f;
81  depthStencilStateCreateInfo.maxDepthBounds = 1.f;
82  depthStencilStateCreateInfo.stencilTestEnable = VK_FALSE;
83  depthStencilStateCreateInfo.front = {};
84  depthStencilStateCreateInfo.back = {};
85 
86 
87  }
88 
89  VulkanPipeline::~VulkanPipeline()
90  {
91  if (pipeline != 0)
92  vkDestroyPipeline(device->GetDevice(), pipeline, nullptr);
93 
94  if (pipelineLayout != 0)
95  vkDestroyPipelineLayout(device->GetDevice(), pipelineLayout, nullptr);
96 
97  for (int i = 0; i < static_cast<int>(descriptorSets.size()); i++) {
98  vkDestroyDescriptorSetLayout(device->GetDevice(), descriptorSets[i].descriptorSet, nullptr);
99 
100  }
101 
102  if (descriptorSetLayout != 0)
103  vkDestroyDescriptorSetLayout(device->GetDevice(), descriptorSetLayout, nullptr);
104 
105  if (vertexShaderModule != 0)
106  vkDestroyShaderModule(device->GetDevice(), vertexShaderModule, nullptr);
107 
108  if (teslationEvaluationShaderModule != 0)
109  vkDestroyShaderModule(device->GetDevice(), teslationEvaluationShaderModule, nullptr);
110 
111  if (teslationControlShaderModule != 0)
112  vkDestroyShaderModule(device->GetDevice(), teslationControlShaderModule, nullptr);
113 
114  if (geometryShaderModule != 0)
115  vkDestroyShaderModule(device->GetDevice(), geometryShaderModule, nullptr);
116 
117  if (fragmentShaderModule != 0)
118  vkDestroyShaderModule(device->GetDevice(), fragmentShaderModule, nullptr);
119 
120  }
121 
122  bool VulkanPipeline::LoadShader(SHADER_TYPE type, eastl::string name, bool spirv)
123  {
124  if (!spirv)
125  return false;
126 
127  eastl::string path = "Resources/Shaders/Vulkan/Compiled/" + name;
128 
129  FILE* file = fopen(path.c_str(), "rb");
130 
131  if (!file) {
132  eastl::string s = "[ERROR] Opening shader file " + path + " failed";
133  std::cout << s.c_str() << std::endl;
134  return false;
135  }
136  fseek(file, 0L, SEEK_END);
137  size_t fileSize = static_cast<size_t>(ftell(file));
138  eastl::vector<char> buffer(fileSize);
139  fseek(file, 0L, SEEK_SET);
140  fread(buffer.data(), sizeof(char), fileSize, file);
141 
142  int ret;
143 
144  switch (type) {
145  case SHADER_TYPE::VERTEX_SHADER:
146  vertexShader = buffer;
147  ret = CompileShaderModule(buffer, &vertexShaderModule);
148  if (ret != 0) {
149  vertexShader.clear();
150  }
151  else {
152  VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
153  vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
154  vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
155  vertShaderStageInfo.module = vertexShaderModule;
156  vertShaderStageInfo.pName = "main";
157  ShaderStageCreateInfo[0] = vertShaderStageInfo;
158  }
159 
160  break;
161  case SHADER_TYPE::TESLATION_EVALUATION_SHADER:
162  teslationEvaluationShader = buffer;
163  ret = CompileShaderModule(buffer, &teslationEvaluationShaderModule);
164  if (ret != 0)
165  teslationEvaluationShader.clear();
166  else {
167  VkPipelineShaderStageCreateInfo tesEvalShaderStageInfo = {};
168  tesEvalShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
169  tesEvalShaderStageInfo.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
170  tesEvalShaderStageInfo.module = teslationEvaluationShaderModule;
171  tesEvalShaderStageInfo.pName = "main";
172  ShaderStageCreateInfo[1] = tesEvalShaderStageInfo;
173  }
174  break;
175  case SHADER_TYPE::TESLATION_CONTROL_SHADER:
176  teslationControlShader = buffer;
177  ret = CompileShaderModule(buffer, &teslationControlShaderModule);
178  if (ret != 0)
179  teslationControlShader.clear();
180  else {
181  VkPipelineShaderStageCreateInfo tesCtrlShaderStageInfo = {};
182  tesCtrlShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
183  tesCtrlShaderStageInfo.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
184  tesCtrlShaderStageInfo.module = teslationControlShaderModule;
185  tesCtrlShaderStageInfo.pName = "main";
186  ShaderStageCreateInfo[2] = tesCtrlShaderStageInfo;
187  }
188  break;
189  case SHADER_TYPE::GEOMETRY_SHADER:
190  geometryShader = buffer;
191  ret = CompileShaderModule(buffer, &geometryShaderModule);
192  if (ret != 0)
193  geometryShader.clear();
194  else {
195  VkPipelineShaderStageCreateInfo geomShaderStageInfo = {};
196  geomShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
197  geomShaderStageInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
198  geomShaderStageInfo.module = geometryShaderModule;
199  geomShaderStageInfo.pName = "main";
200  ShaderStageCreateInfo[3] = geomShaderStageInfo;
201  }
202  break;
203  case SHADER_TYPE::FRAGMENT_SHADER:
204  fragmentShader = buffer;
205  ret = CompileShaderModule(buffer, &fragmentShaderModule);
206  if (ret != 0)
207  fragmentShader.clear();
208  else {
209  VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
210  fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
211  fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
212  fragShaderStageInfo.module = fragmentShaderModule;
213  fragShaderStageInfo.pName = "main";
214  ShaderStageCreateInfo[4] = fragShaderStageInfo;
215  }
216  break;
217  }
218 
219  fclose(file);
220  if (ret != 0)
221  return false;
222  return true;
223  }
224 
225  int VulkanPipeline::Compile()
226  {
227  if (vertexShader.size() == 0)
228  return VULKAN_PIPELINE_COMPILE_MISSING_SHADER_VERTEX;
229  if (fragmentShader.size() == 0)
230  return VULKAN_PIPELINE_COMPILE_MISSING_SHADER_FRAGMENT;
231 
232  VkPipelineViewportStateCreateInfo viewportCreateInfo = {};
233  viewportCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
234  viewportCreateInfo.viewportCount = 1;
235  viewportCreateInfo.pViewports = &viewport;
236  viewportCreateInfo.scissorCount = 1;
237  viewportCreateInfo.pScissors = &scissor;
238 
239  VkPipelineColorBlendStateCreateInfo colorBlending = {};
240  colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
241  colorBlending.logicOpEnable = VK_FALSE;
242  colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
243  colorBlending.attachmentCount = static_cast<uint32_t>(colorBlendAttachments.size());
244  colorBlending.pAttachments = colorBlendAttachments.data();
245  colorBlending.blendConstants[0] = 0.0f; // Optional
246  colorBlending.blendConstants[1] = 0.0f; // Optional
247  colorBlending.blendConstants[2] = 0.0f; // Optional
248  colorBlending.blendConstants[3] = 0.0f; // Optional
249 
250  eastl::vector<VkDynamicState> dynamicStates;
251 
252  dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
253 
254  VkPipelineDynamicStateCreateInfo dynamicState = {};
255  dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
256  dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
257  dynamicState.pDynamicStates = dynamicStates.data();
258 
259  eastl::vector<VkDescriptorSetLayout> descriptorLayouts;
260 
261  for (int i = 0; i < static_cast<int>(descriptorSets.size()); i++) {
262  if (descriptorSets[i].descriptorSet == 0) {
263  VkDescriptorSetLayoutCreateInfo createInfo = {};
264  createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
265  createInfo.bindingCount = static_cast<uint32_t>(descriptorSets[i].descriptionSetLayoutBindings.size());
266  createInfo.pBindings = descriptorSets[i].descriptionSetLayoutBindings.data();
267  vkCreateDescriptorSetLayout(device->GetDevice(), &createInfo, nullptr, &descriptorSets[i].descriptorSet);
268  }
269  descriptorLayouts.push_back(descriptorSets[i].descriptorSet);
270 
271  }
272 
273 
274  pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(descriptorLayouts.size());
275  pipelineLayoutCreateInfo.pSetLayouts = descriptorLayouts.data();
276  pipelineLayoutCreateInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
277  pipelineLayoutCreateInfo.pPushConstantRanges = pushConstantRanges.data();
278 
279  VkResult res = vkCreatePipelineLayout(device->GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
280  if (res != VK_SUCCESS) {
281  eastl::string s = eastl::string("[ERROR] [CODE:") + std::to_string(res).c_str() + "] Creating pipeline layout failed";
282  std::cout << s.c_str() << std::endl;
283  return res;
284  }
285 
286  eastl::vector<VkPipelineShaderStageCreateInfo> shaderStages;
287 
288  for (int i = 0; i < 5; i++) {
289  if (ShaderStageCreateInfo[i].sType != 0) {
290  shaderStages.push_back(ShaderStageCreateInfo[i]);
291  }
292  }
293 
294  VkGraphicsPipelineCreateInfo pipelineInfo = {};
295  pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
296  pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
297  pipelineInfo.pStages = shaderStages.data();
298  pipelineInfo.pVertexInputState = &vertexInputInfo;
299  pipelineInfo.pInputAssemblyState = &InputAssemblyStateCreateInfo;
300  pipelineInfo.pViewportState = &viewportCreateInfo;
301  pipelineInfo.pRasterizationState = &rasterizer;
302  pipelineInfo.pMultisampleState = &multisampling;
303  pipelineInfo.pDepthStencilState = &depthStencilStateCreateInfo;
304  pipelineInfo.pColorBlendState = &colorBlending;
305  pipelineInfo.pDynamicState = &dynamicState;
306  pipelineInfo.layout = pipelineLayout;
307  pipelineInfo.renderPass = renderPass;
308  pipelineInfo.subpass = subPass;
309  pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
310  pipelineInfo.basePipelineIndex = -1;
311 
312  res = vkCreateGraphicsPipelines(device->GetDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline);
313  if (res != VK_SUCCESS) {
314  eastl::string s = eastl::string("[ERROR] [CODE:") + std::to_string(res).c_str() + "] Creating pipeline failed";
315  std::cout << s.c_str() << std::endl;
316  return res;
317  }
318 
319  return 0;
320  }
321 
322  void VulkanPipeline::SetInputAssemblyState(VkPrimitiveTopology topology, bool primitiveRestartEnabled)
323  {
324  InputAssemblyStateCreateInfo = {};
325  InputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
326  InputAssemblyStateCreateInfo.topology = topology;
327  if (primitiveRestartEnabled)
328  InputAssemblyStateCreateInfo.primitiveRestartEnable = VK_TRUE;
329  else
330  InputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
331  }
332 
333  void VulkanPipeline::AddVertexInputBindingDescription(uint32_t binding, uint32_t stride, VkVertexInputRate inputRate)
334  {
335  VkVertexInputBindingDescription description = {};
336  description.binding = binding;
337  description.stride = stride;
338  description.inputRate = inputRate;
339  vertexInputBindingDescriptions.push_back(description);
340 
341  vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexInputBindingDescriptions.size());
342  vertexInputInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions.data();
343  }
344 
345  void VulkanPipeline::AddVertexInputBindingDescription(VkVertexInputBindingDescription description)
346  {
347  vertexInputBindingDescriptions.push_back(description);
348 
349  vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexInputBindingDescriptions.size());
350  vertexInputInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions.data();
351  }
352 
353  void VulkanPipeline::AddVertexInputAttributeDescription(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset)
354  {
355  VkVertexInputAttributeDescription description = {};
356  description.location = location;
357  description.binding = binding;
358  description.format = format;
359  description.offset = offset;
360  vertexInputAttributeDescriptions.push_back(description);
361 
362  vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexInputAttributeDescriptions.size());
363  vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions.data();
364  }
365 
366  void VulkanPipeline::AddVertexInputAttributeDescription(VkVertexInputAttributeDescription description)
367  {
368  vertexInputAttributeDescriptions.push_back(description);
369 
370  vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexInputAttributeDescriptions.size());
371  vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions.data();
372  }
373 
374  void VulkanPipeline::SetRasterizerSettings(VkBool32 depthClamp, VkBool32 discardEnable, VkPolygonMode polygonMode, float lineWidth, VkCullModeFlagBits culling, VkFrontFace frontFace, VkBool32 depthBiasEnabled, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
375  {
376  rasterizer.depthClampEnable = depthClamp;
377  rasterizer.rasterizerDiscardEnable = discardEnable;
378  rasterizer.polygonMode = polygonMode;
379  rasterizer.lineWidth = lineWidth;
380  rasterizer.cullMode = culling;
381  rasterizer.frontFace = frontFace;
382  rasterizer.depthBiasEnable = depthBiasEnabled;
383  rasterizer.depthBiasConstantFactor = depthBiasConstantFactor;
384  rasterizer.depthBiasClamp = depthBiasClamp;
385  rasterizer.depthBiasSlopeFactor = depthBiasSlopeFactor;
386  }
387 
388  void VulkanPipeline::CreateColorBlendAttachment(VkBool32 blendEnabled, VkColorComponentFlags colorWriteMask, VkBlendFactor colorSrcFactor, VkBlendFactor colorDstFactor, VkBlendOp colorBlendOp, VkBlendFactor alphaSrcFactor, VkBlendFactor alphaDstFactor, VkBlendOp alphaBlendOp)
389  {
390  VkPipelineColorBlendAttachmentState colorBlendAttachment;
391  colorBlendAttachment.blendEnable = blendEnabled;
392  colorBlendAttachment.colorWriteMask = colorWriteMask;
393  colorBlendAttachment.srcColorBlendFactor = colorSrcFactor;
394  colorBlendAttachment.dstColorBlendFactor = colorDstFactor;
395  colorBlendAttachment.colorBlendOp = colorBlendOp;
396  colorBlendAttachment.srcAlphaBlendFactor = alphaSrcFactor;
397  colorBlendAttachment.dstAlphaBlendFactor = alphaDstFactor;
398  colorBlendAttachment.alphaBlendOp = alphaBlendOp;
399 
400  colorBlendAttachments.push_back(colorBlendAttachment);
401  }
402 
403  void VulkanPipeline::SetDepthStencilState(VkBool32 depthTestEnable,
404  VkBool32 depthWriteEnable,
405  VkCompareOp depthCompareOp,
406  VkBool32 depthBoundsTestEnable,
407  float minDepthBounds,
408  float maxDepthBounds,
409  VkBool32 stencilTestEnable,
410  VkStencilOpState front,
411  VkStencilOpState back)
412  {
413  depthStencilStateCreateInfo.depthTestEnable = depthTestEnable;
414  depthStencilStateCreateInfo.depthWriteEnable = depthWriteEnable;
415  depthStencilStateCreateInfo.depthCompareOp = depthCompareOp;
416  depthStencilStateCreateInfo.depthBoundsTestEnable = depthBoundsTestEnable;
417  depthStencilStateCreateInfo.minDepthBounds = minDepthBounds;
418  depthStencilStateCreateInfo.maxDepthBounds = maxDepthBounds;
419  depthStencilStateCreateInfo.stencilTestEnable = stencilTestEnable;
420  depthStencilStateCreateInfo.front = front;
421  depthStencilStateCreateInfo.back = back;
422  }
423 
424  void VulkanPipeline::AddDescriptorSetBinding(descriptorSetHandle set, uint32_t binding, VkDescriptorType type, uint32_t descriptorCount, VkShaderStageFlags shaderStage, const VkSampler * immutableSamplers)
425  {
426  VkDescriptorSetLayoutBinding descriptorBinding = {};
427  descriptorBinding.binding = binding;
428  descriptorBinding.descriptorCount = descriptorCount;
429  descriptorBinding.descriptorType = type;
430  descriptorBinding.stageFlags = shaderStage;
431  descriptorBinding.pImmutableSamplers = immutableSamplers;
432 
433  if (set<descriptorSets.size()) {
434  descriptorSets[set].descriptionSetLayoutBindings.push_back(descriptorBinding);
435  }
436  }
437 
438  void VulkanPipeline::SetRenderPassInfo(VkRenderPass renderPass, uint32_t subPass)
439  {
440  this->renderPass = renderPass;
441  this->subPass = subPass;
442  }
443 
444  VulkanPipeline::descriptorSetHandle VulkanPipeline::CreateDescriptorSet()
445  {
446  DescriptorSet_t set = {};
447  descriptorSets.push_back(set);
448  return descriptorSets.size() - 1;
449  }
450 
451  VulkanPipeline::descriptorSetHandle VulkanPipeline::AddDescriptorSetLayout(VkDescriptorSetLayout layout)
452  {
453  DescriptorSet_t set = {};
454  set.descriptorSet = layout;
455  set.external = true;
456  descriptorSets.push_back(set);
457  return descriptorSets.size() - 1;
458  }
459 
460  VkDescriptorSetLayout VulkanPipeline::GetDescriptorSetLayout(descriptorSetHandle handle)
461  {
462  return descriptorSets[handle].descriptorSet;
463  }
464 
465  VkPipeline VulkanPipeline::GetPipeline() const
466  {
467  return pipeline;
468  }
469 
470  VkPipelineLayout VulkanPipeline::GetPipelineLayout() const
471  {
472  return pipelineLayout;
473  }
474 
475  uint32_t VulkanPipeline::GetPipelineId() const
476  {
477  return pipelineId;
478  }
479 
480  void VulkanPipeline::AddPushConstantRange(VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size)
481  {
482  VkPushConstantRange range = {};
483  range.stageFlags = stageFlags;
484  range.size = size;
485  range.offset = offset;
486 
487  pushConstantRanges.push_back(range);
488  }
489 
490  void VulkanPipeline::Clean() const
491  {
492  vkDestroyPipeline(device->GetDevice(), pipeline, nullptr);
493  vkDestroyPipelineLayout(device->GetDevice(), pipelineLayout, nullptr);
494  }
495 
496  void VulkanPipeline::Recreate()
497  {
498  viewport = {};
499  viewport.x = 0.f;
500  viewport.y = 0.f;
501  viewport.width = static_cast<float>(renderer->swapChainImageExtent.width);
502  viewport.height = static_cast<float>(renderer->swapChainImageExtent.height);
503  viewport.minDepth = 0.f;
504  viewport.maxDepth = 1.f;
505 
506  scissor = {};
507  scissor.offset = { 0,0 };
508  scissor.extent = renderer->swapChainImageExtent;
509 
510  VkPipelineViewportStateCreateInfo viewportCreateInfo = {};
511  viewportCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
512  viewportCreateInfo.viewportCount = 1;
513  viewportCreateInfo.pViewports = &viewport;
514  viewportCreateInfo.scissorCount = 1;
515  viewportCreateInfo.pScissors = &scissor;
516 
517  VkPipelineColorBlendStateCreateInfo colorBlending = {};
518  colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
519  colorBlending.logicOpEnable = VK_FALSE;
520  colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
521  colorBlending.attachmentCount = static_cast<uint32_t>(colorBlendAttachments.size());
522  colorBlending.pAttachments = colorBlendAttachments.data();
523  colorBlending.blendConstants[0] = 0.0f; // Optional
524  colorBlending.blendConstants[1] = 0.0f; // Optional
525  colorBlending.blendConstants[2] = 0.0f; // Optional
526  colorBlending.blendConstants[3] = 0.0f; // Optional
527 
528  eastl::vector<VkDynamicState> states;
529 
530  states.push_back(VK_DYNAMIC_STATE_SCISSOR);
531 
532  VkPipelineDynamicStateCreateInfo dynamicState = {};
533  dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
534  dynamicState.dynamicStateCount = static_cast<uint32_t>(states.size());
535  dynamicState.pDynamicStates = states.data();
536 
537  eastl::vector<VkDescriptorSetLayout> descriptorLayouts;
538 
539  for (int i = 0; i < static_cast<int>(descriptorSets.size()); i++) {
540  if (descriptorSets[i].descriptorSet == 0) {
541  VkDescriptorSetLayoutCreateInfo createInfo = {};
542  createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
543  createInfo.bindingCount = static_cast<uint32_t>(descriptorSets[i].descriptionSetLayoutBindings.size());
544  createInfo.pBindings = descriptorSets[i].descriptionSetLayoutBindings.data();
545  vkCreateDescriptorSetLayout(device->GetDevice(), &createInfo, nullptr, &descriptorSets[i].descriptorSet);
546  }
547  descriptorLayouts.push_back(descriptorSets[i].descriptorSet);
548 
549  }
550 
551  pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(descriptorLayouts.size());
552  pipelineLayoutCreateInfo.pSetLayouts = descriptorLayouts.data();
553 
554  VkResult res = vkCreatePipelineLayout(device->GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
555  if (res != VK_SUCCESS) {
556  eastl::string s = eastl::string("[ERROR] [CODE:") + std::to_string(res).c_str() + "] Creating pipeline layout failed";
557  std::cout << s.c_str() << std::endl;
558  }
559 
560  eastl::vector<VkPipelineShaderStageCreateInfo> shaderStages;
561 
562  for (int i = 0; i < 5; i++) {
563  if (ShaderStageCreateInfo[i].sType != 0) {
564  shaderStages.push_back(ShaderStageCreateInfo[i]);
565  }
566  }
567 
568  VkGraphicsPipelineCreateInfo pipelineInfo = {};
569  pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
570  pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
571  pipelineInfo.pStages = shaderStages.data();
572  pipelineInfo.pVertexInputState = &vertexInputInfo;
573  pipelineInfo.pInputAssemblyState = &InputAssemblyStateCreateInfo;
574  pipelineInfo.pViewportState = &viewportCreateInfo;
575  pipelineInfo.pRasterizationState = &rasterizer;
576  pipelineInfo.pMultisampleState = &multisampling;
577  pipelineInfo.pDepthStencilState = &depthStencilStateCreateInfo;
578  pipelineInfo.pColorBlendState = &colorBlending;
579  pipelineInfo.pDynamicState = &dynamicState;
580  pipelineInfo.layout = pipelineLayout;
581  pipelineInfo.renderPass = renderPass;
582  pipelineInfo.subpass = subPass;
583  pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
584  pipelineInfo.basePipelineIndex = -1;
585 
586  res = vkCreateGraphicsPipelines(device->GetDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline);
587  if (res != VK_SUCCESS) {
588  eastl::string s = eastl::string("[ERROR] [CODE:") + std::to_string(res).c_str() + "] Creating pipeline failed";
589  std::cout << s.c_str() << std::endl;
590  }
591 
592  }
593 
594  int VulkanPipeline::CompileShaderModule(eastl::vector<char> code, VkShaderModule * shaderModule)
595  {
596  VkShaderModuleCreateInfo createInfo = {};
597  createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
598  createInfo.codeSize = code.size();
599  createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
600 
601  VkResult res = vkCreateShaderModule(device->GetDevice(), &createInfo, nullptr, shaderModule);
602  if (res != VK_SUCCESS) {
603  eastl::string s = eastl::string("[ERROR] [CODE:") + std::to_string(res).c_str() + "] Creating shader module failed";
604  std::cout << s.c_str() << std::endl;
605  }
606 
607  return res;
608  }
609 }
610 
611 #endif // USING_VULKAN