source: opengl-game/graphics-pipeline_vulkan.cpp@ 603b5bc

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

In vulkangame, add code to create the frame buffers and command buffers

  • Property mode set to 100644
File size: 13.6 KB
Line 
1#include "graphics-pipeline_vulkan.hpp"
2
3#include <fstream>
4#include <stdexcept>
5#include <iostream>
6
7using namespace std;
8
9// TODO: Remove any instances of cout and instead throw exceptions
10
11GraphicsPipeline_Vulkan::GraphicsPipeline_Vulkan(VkDevice device, VkRenderPass renderPass, Viewport viewport,
12 int vertexSize) {
13 this->device = device;
14 this->renderPass = renderPass;
15 this->viewport = viewport;
16
17 this->bindingDescription.binding = 0;
18 this->bindingDescription.stride = vertexSize;
19 this->bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
20}
21
22GraphicsPipeline_Vulkan::~GraphicsPipeline_Vulkan() {
23}
24
25void GraphicsPipeline_Vulkan::addAttribute(VkFormat format, size_t offset) {
26 VkVertexInputAttributeDescription attributeDesc = {};
27
28 attributeDesc.binding = 0;
29 attributeDesc.location = this->attributeDescriptions.size();
30 attributeDesc.format = format;
31 attributeDesc.offset = offset;
32
33 this->attributeDescriptions.push_back(attributeDesc);
34}
35
36void GraphicsPipeline_Vulkan::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) {
37 this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr });
38}
39
40void GraphicsPipeline_Vulkan::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) {
41 this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData });
42}
43
44void GraphicsPipeline_Vulkan::createPipeline(string vertShaderFile, string fragShaderFile) {
45 vector<char> vertShaderCode = readFile(vertShaderFile);
46 vector<char> fragShaderCode = readFile(fragShaderFile);
47
48 VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
49 VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
50
51 VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
52 vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
53 vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
54 vertShaderStageInfo.module = vertShaderModule;
55 vertShaderStageInfo.pName = "main";
56
57 VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
58 fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
59 fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
60 fragShaderStageInfo.module = fragShaderModule;
61 fragShaderStageInfo.pName = "main";
62
63 VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
64
65 VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
66 vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
67
68 vertexInputInfo.vertexBindingDescriptionCount = 1;
69 vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(this->attributeDescriptions.size());
70 vertexInputInfo.pVertexBindingDescriptions = &this->bindingDescription;
71 vertexInputInfo.pVertexAttributeDescriptions = this->attributeDescriptions.data();
72
73 VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
74 inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
75 inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
76 inputAssembly.primitiveRestartEnable = VK_FALSE;
77
78 VkViewport viewport = {};
79 viewport.x = (float)this->viewport.x;
80 viewport.y = (float)this->viewport.y;
81 viewport.width = (float)this->viewport.width;
82 viewport.height = (float)this->viewport.height;
83 viewport.minDepth = 0.0f;
84 viewport.maxDepth = 1.0f;
85
86 VkRect2D scissor = {};
87 scissor.offset = { 0, 0 };
88 scissor.extent = { (uint32_t)this->viewport.width, (uint32_t)this->viewport.height };
89
90 VkPipelineViewportStateCreateInfo viewportState = {};
91 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
92 viewportState.viewportCount = 1;
93 viewportState.pViewports = &viewport;
94 viewportState.scissorCount = 1;
95 viewportState.pScissors = &scissor;
96
97 VkPipelineRasterizationStateCreateInfo rasterizer = {};
98 rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
99 rasterizer.depthClampEnable = VK_FALSE;
100 rasterizer.rasterizerDiscardEnable = VK_FALSE;
101 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
102 rasterizer.lineWidth = 1.0f;
103 rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
104 rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
105 rasterizer.depthBiasEnable = VK_FALSE;
106
107 VkPipelineMultisampleStateCreateInfo multisampling = {};
108 multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
109 multisampling.sampleShadingEnable = VK_FALSE;
110 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
111
112 VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
113 colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
114 colorBlendAttachment.blendEnable = VK_TRUE;
115 colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
116 colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
117 colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
118 colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
119 colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
120 colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
121
122 VkPipelineColorBlendStateCreateInfo colorBlending = {};
123 colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
124 colorBlending.logicOpEnable = VK_FALSE;
125 colorBlending.logicOp = VK_LOGIC_OP_COPY;
126 colorBlending.attachmentCount = 1;
127 colorBlending.pAttachments = &colorBlendAttachment;
128 colorBlending.blendConstants[0] = 0.0f;
129 colorBlending.blendConstants[1] = 0.0f;
130 colorBlending.blendConstants[2] = 0.0f;
131 colorBlending.blendConstants[3] = 0.0f;
132
133 VkPipelineDepthStencilStateCreateInfo depthStencil = {};
134 depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
135 depthStencil.depthTestEnable = VK_TRUE;
136 depthStencil.depthWriteEnable = VK_TRUE;
137 depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
138 depthStencil.depthBoundsTestEnable = VK_FALSE;
139 depthStencil.minDepthBounds = 0.0f;
140 depthStencil.maxDepthBounds = 1.0f;
141 depthStencil.stencilTestEnable = VK_FALSE;
142 depthStencil.front = {};
143 depthStencil.back = {};
144
145 VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
146 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
147 pipelineLayoutInfo.setLayoutCount = 1;
148 pipelineLayoutInfo.pSetLayouts = &this->descriptorSetLayout;
149 pipelineLayoutInfo.pushConstantRangeCount = 0;
150
151 if (vkCreatePipelineLayout(this->device, &pipelineLayoutInfo, nullptr, &this->pipelineLayout) != VK_SUCCESS) {
152 throw runtime_error("failed to create pipeline layout!");
153 }
154
155 VkGraphicsPipelineCreateInfo pipelineInfo = {};
156 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
157 pipelineInfo.stageCount = 2;
158 pipelineInfo.pStages = shaderStages;
159 pipelineInfo.pVertexInputState = &vertexInputInfo;
160 pipelineInfo.pInputAssemblyState = &inputAssembly;
161 pipelineInfo.pViewportState = &viewportState;
162 pipelineInfo.pRasterizationState = &rasterizer;
163 pipelineInfo.pMultisampleState = &multisampling;
164 pipelineInfo.pDepthStencilState = &depthStencil;
165 pipelineInfo.pColorBlendState = &colorBlending;
166 pipelineInfo.pDynamicState = nullptr;
167 pipelineInfo.layout = this->pipelineLayout;
168 pipelineInfo.renderPass = this->renderPass;
169 pipelineInfo.subpass = 0;
170 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
171 pipelineInfo.basePipelineIndex = -1;
172
173 if (vkCreateGraphicsPipelines(this->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &this->pipeline) != VK_SUCCESS) {
174 throw runtime_error("failed to create graphics pipeline!");
175 }
176
177 vkDestroyShaderModule(this->device, vertShaderModule, nullptr);
178 vkDestroyShaderModule(this->device, fragShaderModule, nullptr);
179}
180
181void GraphicsPipeline_Vulkan::createDescriptorSetLayout() {
182 vector<VkDescriptorSetLayoutBinding> bindings(this->descriptorInfoList.size());
183
184 for (size_t i = 0; i < bindings.size(); i++) {
185 bindings[i].binding = i;
186 bindings[i].descriptorCount = 1;
187 bindings[i].descriptorType = this->descriptorInfoList[i].type;
188 bindings[i].stageFlags = this->descriptorInfoList[i].stageFlags;
189 bindings[i].pImmutableSamplers = nullptr;
190 }
191
192 VkDescriptorSetLayoutCreateInfo layoutInfo = {};
193 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
194 layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
195 layoutInfo.pBindings = bindings.data();
196
197 if (vkCreateDescriptorSetLayout(this->device, &layoutInfo, nullptr, &this->descriptorSetLayout) != VK_SUCCESS) {
198 throw runtime_error("failed to create descriptor set layout!");
199 }
200}
201
202void GraphicsPipeline_Vulkan::createDescriptorPool(vector<VkImage>& swapChainImages) {
203 vector<VkDescriptorPoolSize> poolSizes(this->descriptorInfoList.size());
204
205 for (size_t i = 0; i < poolSizes.size(); i++) {
206 poolSizes[i].type = this->descriptorInfoList[i].type;
207 poolSizes[i].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
208 }
209
210 VkDescriptorPoolCreateInfo poolInfo = {};
211 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
212 poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
213 poolInfo.pPoolSizes = poolSizes.data();
214 poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
215
216 if (vkCreateDescriptorPool(this->device, &poolInfo, nullptr, &this->descriptorPool) != VK_SUCCESS) {
217 throw runtime_error("failed to create descriptor pool!");
218 }
219}
220
221void GraphicsPipeline_Vulkan::createDescriptorSets(vector<VkImage>& swapChainImages) {
222 vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), this->descriptorSetLayout);
223
224 VkDescriptorSetAllocateInfo allocInfo = {};
225 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
226 allocInfo.descriptorPool = this->descriptorPool;
227 allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
228 allocInfo.pSetLayouts = layouts.data();
229
230 this->descriptorSets.resize(swapChainImages.size());
231 if (vkAllocateDescriptorSets(device, &allocInfo, this->descriptorSets.data()) != VK_SUCCESS) {
232 throw runtime_error("failed to allocate descriptor sets!");
233 }
234
235 for (size_t i = 0; i < swapChainImages.size(); i++) {
236 vector<VkWriteDescriptorSet> descriptorWrites(this->descriptorInfoList.size());
237
238 for (size_t j = 0; j < descriptorWrites.size(); j++) {
239 descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
240 descriptorWrites[j].dstSet = this->descriptorSets[i];
241 descriptorWrites[j].dstBinding = j;
242 descriptorWrites[j].dstArrayElement = 0;
243 descriptorWrites[j].descriptorType = this->descriptorInfoList[j].type;
244 descriptorWrites[j].descriptorCount = 1;
245 descriptorWrites[j].pBufferInfo = nullptr;
246 descriptorWrites[j].pImageInfo = nullptr;
247 descriptorWrites[j].pTexelBufferView = nullptr;
248
249 switch (descriptorWrites[j].descriptorType) {
250 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
251 descriptorWrites[j].pBufferInfo = &(*this->descriptorInfoList[j].bufferDataList)[i];
252 break;
253 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
254 descriptorWrites[j].pImageInfo = this->descriptorInfoList[j].imageData;
255 break;
256 default:
257 cout << "Unknown descriptor type: " << descriptorWrites[j].descriptorType << endl;
258 }
259 }
260
261 vkUpdateDescriptorSets(this->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
262 }
263}
264
265void GraphicsPipeline_Vulkan::createRenderCommands(VkCommandBuffer& commandBuffer, uint32_t currentImage) {
266 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
267 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1,
268 &descriptorSets[currentImage], 0, nullptr);
269
270 // TODO: Implement once I add vertex and index buffers to the pipeline
271 /*
272 VkBuffer vertexBuffers[] = { info.vertexBuffer };
273 VkDeviceSize offsets[] = { 0 };
274 vkCmdBindVertexBuffers(commandBuffers[currentImage], 0, 1, vertexBuffers, offsets);
275
276 vkCmdBindIndexBuffer(commandBuffers[currentImage], info.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
277
278 vkCmdDrawIndexed(commandBuffers[currentImage], static_cast<uint32_t>(info.numIndices), 1, 0, 0, 0);
279 */
280}
281
282VkShaderModule GraphicsPipeline_Vulkan::createShaderModule(const vector<char>& code) {
283 VkShaderModuleCreateInfo createInfo = {};
284 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
285 createInfo.codeSize = code.size();
286 createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
287
288 VkShaderModule shaderModule;
289 if (vkCreateShaderModule(this->device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
290 throw runtime_error("failed to create shader module!");
291 }
292
293 return shaderModule;
294}
295
296vector<char> GraphicsPipeline_Vulkan::readFile(const string& filename) {
297 ifstream file(filename, ios::ate | ios::binary);
298
299 if (!file.is_open()) {
300 throw runtime_error("failed to open file!");
301 }
302
303 size_t fileSize = (size_t)file.tellg();
304 vector<char> buffer(fileSize);
305
306 file.seekg(0);
307 file.read(buffer.data(), fileSize);
308
309 file.close();
310
311 return buffer;
312}
313
314void GraphicsPipeline_Vulkan::cleanup() {
315 vkDestroyPipeline(this->device, this->pipeline, nullptr);
316 vkDestroyDescriptorPool(this->device, this->descriptorPool, nullptr);
317 vkDestroyPipelineLayout(this->device, this->pipelineLayout, nullptr);
318}
319
320void GraphicsPipeline_Vulkan::cleanupBuffers() {
321 vkDestroyDescriptorSetLayout(this->device, this->descriptorSetLayout, nullptr);
322}
Note: See TracBrowser for help on using the repository browser.