SimpleGL  1.1.0
A framework for platform independent rendering
graphics_pipeline.cpp
Go to the documentation of this file.
1 
9 
10 #include <stdexcept>
11 
12 #include <glm/glm.hpp>
13 
16 
17 using namespace std;
18 using namespace glm;
19 
20 namespace sgl {
21 
22  GraphicsPipeline::GraphicsPipeline(RenderPass* renderPass, std::vector<ShaderModule*> shaderModules) {
23  VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
24  SwapchainData swapchainData = VulkanContext::getCurrent()->getSwapchain()->getSwapchainData();
25 
26  /* Initialize the shader stage create infos */
27  vector<VkPipelineShaderStageCreateInfo> shaderStages(shaderModules.size());
28  for (uint32_t i = 0; i < shaderStages.size(); i++) {
29  shaderStages[i] = {};
30  shaderStages[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
31  shaderStages[i].stage = shaderModules[i]->getShaderStageBit();
32  shaderStages[i].module = shaderModules[i]->getHandle();
33  shaderStages[i].pName = "main";
34  }
35 
36  /* Initialize the vertex input binding descriptions */
37  vector<VkVertexInputBindingDescription> vertexBindingDescriptions(4);
38 
39  /* Position vertex binding */
40  vertexBindingDescriptions[0].binding = 0;
41  vertexBindingDescriptions[0].stride = sizeof (vec3);
42  vertexBindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
43 
44  /* Color vertex binding */
45  vertexBindingDescriptions[1].binding = 1;
46  vertexBindingDescriptions[1].stride = sizeof (vec4);
47  vertexBindingDescriptions[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
48 
49  /* TexCoord vertex binding */
50  vertexBindingDescriptions[2].binding = 2;
51  vertexBindingDescriptions[2].stride = sizeof (vec2);
52  vertexBindingDescriptions[2].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
53 
54  /* Normal vertex binding */
55  vertexBindingDescriptions[3].binding = 3;
56  vertexBindingDescriptions[3].stride = sizeof (vec3);
57  vertexBindingDescriptions[3].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
58 
59  /* Initialize the vertex input attribute descriptions */
60  vector<VkVertexInputAttributeDescription> vertexAttributeDescriptions(4);
61 
62  /* Position vertex attribute */
63  vertexAttributeDescriptions[0].location = 0;
64  vertexAttributeDescriptions[0].binding = 0;
65  vertexAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
66  vertexAttributeDescriptions[0].offset = 0;
67 
68  /* Color vertex attribute */
69  vertexAttributeDescriptions[1].location = 1;
70  vertexAttributeDescriptions[1].binding = 1;
71  vertexAttributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
72  vertexAttributeDescriptions[1].offset = 0;
73 
74  /* TexCoord vertex attribute */
75  vertexAttributeDescriptions[2].location = 2;
76  vertexAttributeDescriptions[2].binding = 2;
77  vertexAttributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
78  vertexAttributeDescriptions[2].offset = 0;
79 
80  /* Normal vertex attribute */
81  vertexAttributeDescriptions[3].location = 3;
82  vertexAttributeDescriptions[3].binding = 3;
83  vertexAttributeDescriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT;
84  vertexAttributeDescriptions[3].offset = 0;
85 
86  /* Initialize a vertex input state create info */
87  VkPipelineVertexInputStateCreateInfo vertexInputState = {};
88  vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
89  vertexInputState.vertexBindingDescriptionCount = vertexBindingDescriptions.size();
90  vertexInputState.pVertexBindingDescriptions = vertexBindingDescriptions.data();
91  vertexInputState.vertexAttributeDescriptionCount = vertexAttributeDescriptions.size();
92  vertexInputState.pVertexAttributeDescriptions = vertexAttributeDescriptions.data();
93 
94  /* Initialize a input assembly state create info */
95  VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
96  inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
97  inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
98  inputAssemblyState.primitiveRestartEnable = VK_FALSE;
99 
100  /* Initialize a viewport */
101  VkViewport viewport = {};
102  viewport.x = 0.0f;
103  viewport.y = 0.0f;
104  viewport.width = swapchainData.extent.width;
105  viewport.height = swapchainData.extent.height;
106  viewport.minDepth = 0.0f;
107  viewport.maxDepth = 1.0f;
108 
109  /* Initialize a scissor rectangle */
110  VkRect2D scissor = {};
111  scissor.offset.x = 0;
112  scissor.offset.y = 0;
113  scissor.extent = swapchainData.extent;
114 
115  /* Initialize a viewport state create info */
116  VkPipelineViewportStateCreateInfo viewportState = {};
117  viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
118  viewportState.viewportCount = 1;
119  viewportState.pViewports = &viewport;
120  viewportState.scissorCount = 1;
121  viewportState.pScissors = &scissor;
122 
123  /* Initialize a rasterization state create info */
124  VkPipelineRasterizationStateCreateInfo rasterizationState = {};
125  rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
126  rasterizationState.depthClampEnable = VK_FALSE;
127  rasterizationState.rasterizerDiscardEnable = VK_FALSE;
128  rasterizationState.polygonMode = VK_POLYGON_MODE_FILL;
129  rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;
130  rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
131  rasterizationState.depthBiasEnable = VK_FALSE;
132  rasterizationState.lineWidth = 1.0f;
133 
134  /* Initialize a multisample state create info */
135  VkPipelineMultisampleStateCreateInfo multisampleState = {};
136  multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
137  multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
138  multisampleState.sampleShadingEnable = VK_FALSE;
139 
140  /* Initialize a depth stencil state create info */
141  VkPipelineDepthStencilStateCreateInfo depthStencilState = {};
142  depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
143  depthStencilState.depthTestEnable = VK_TRUE;
144  depthStencilState.depthWriteEnable = VK_TRUE;
145  depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS;
146  depthStencilState.depthBoundsTestEnable = VK_FALSE;
147  depthStencilState.stencilTestEnable = VK_FALSE;
148 
149  /* Inizialize a color blend attachment state */
150  VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
151  colorBlendAttachment.blendEnable = VK_FALSE;
152  colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
153 
154  /* Initialize a color blend state create info */
155  VkPipelineColorBlendStateCreateInfo colorBlendState = {};
156  colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
157  colorBlendState.logicOpEnable = VK_FALSE;
158  colorBlendState.attachmentCount = 1;
159  colorBlendState.pAttachments = &colorBlendAttachment;
160 
161  /* Initialize a descriptor set layout binding */
162  vector<VkDescriptorSetLayoutBinding> bindings(2);
163  bindings[0].binding = 0;
164  bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
165  bindings[0].descriptorCount = 1;
166  bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
167  bindings[1].binding = 1;
168  bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
169  bindings[1].descriptorCount = 1;
170  bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
171  bindings[1].pImmutableSamplers = nullptr;
172 
173  /* Initialize a descriptor set layout create info */
174  VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {};
175  setLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
176  setLayoutCreateInfo.bindingCount = bindings.size();
177  setLayoutCreateInfo.pBindings = bindings.data();
178 
179  /* Create a descriptor set layout */
180  if (vkCreateDescriptorSetLayout(device, &setLayoutCreateInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
181  throw runtime_error("Could not create a descriptor set layout!");
182  }
183 
184  /* Create a pipeline layout */
185  VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
186  pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
187  pipelineLayoutCreateInfo.setLayoutCount = 1;
188  pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;
189  if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
190  throw runtime_error("Could not create a pipeline layout!");
191  }
192 
193  /* Initialize a graphics pipeline create info */
194  VkGraphicsPipelineCreateInfo createInfo = {};
195  createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
196  createInfo.stageCount = shaderStages.size();
197  createInfo.pStages = shaderStages.data();
198  createInfo.pVertexInputState = &vertexInputState;
199  createInfo.pInputAssemblyState = &inputAssemblyState;
200  createInfo.pViewportState = &viewportState;
201  createInfo.pRasterizationState = &rasterizationState;
202  createInfo.pMultisampleState = &multisampleState;
203  createInfo.pDepthStencilState = &depthStencilState;
204  createInfo.pColorBlendState = &colorBlendState;
205  createInfo.layout = pipelineLayout;
206  createInfo.renderPass = renderPass->getHandle();
207  createInfo.subpass = 0;
208 
209  /* Create the graphics pipeline */
210  if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &handle) != VK_SUCCESS) {
211  throw runtime_error("Could not create a graphics pipeline!");
212  }
213  }
214 
215  GraphicsPipeline::~GraphicsPipeline(void) {
216  VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
217 
218  /* Destroy the descriptor set layout */
219  vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
220 
221  /* Destroy the pipeline layout */
222  vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
223 
224  /* Destroy the graphics pipeline */
225  vkDestroyPipeline(device, handle, nullptr);
226  }
227 
228  VkPipeline GraphicsPipeline::getHandle() {
229  return handle;
230  }
231 
232  VkDescriptorSetLayout GraphicsPipeline::getDescriptorSetLayout() {
233  return descriptorSetLayout;
234  }
235 
236  VkPipelineLayout GraphicsPipeline::getPipelineLayout() {
237  return pipelineLayout;
238  }
239 }
VkRenderPass getHandle()
Returns the handle of the render pass.
Generic namespace for the SimpleGL framework.
Definition: application.hpp:18
VkExtent2D extent
The swapchain extent.
Definition: swapchain.hpp:40
This struct stores relevant swapchain data.
Definition: swapchain.hpp:28
This class wraps a Vulkan render pass.
Definition: render_pass.hpp:22