Chronos 0.0
A advanced 2D rendering and animation system
Loading...
Searching...
No Matches
object.cpp
Go to the documentation of this file.
1/*
2Copyright (c) 2024 Rahul Satish Vadhyar
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#include "object.hpp"
24#include <fstream>
25
38static inline VkShaderModule createShaderModule(
39 unsigned char* code, int code_size, VkDevice device)
40{
41 VkShaderModuleCreateInfo createInfo {};
42 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
43 createInfo.codeSize = code_size;
44 createInfo.pCode = reinterpret_cast<const uint32_t*>(code);
45 VkShaderModule shaderModule;
46 if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule)
47 != VK_SUCCESS) {
48 throw std::runtime_error("Failed to create shader module");
49 }
50 return shaderModule;
51}
52
54 VkCommandPool commandPool, SwapChain* swapChain, VkSampler textureSampler,
55 VkRenderPass* renderPass, ObjectType objectType, unsigned char* vertShaderCode,
56 int vertShaderCodeSize, unsigned char* fragShaderCode, int fragShaderCodeSize)
57{
58 this->device = device;
59 this->swapChain = swapChain;
60 this->commandPool = commandPool;
61 this->textureSampler = textureSampler;
62 this->renderPass = renderPass;
63 this->objectType = objectType;
64 this->vertShaderCode = vertShaderCode;
65 this->vertShaderCodeSize = vertShaderCodeSize;
66 this->fragShaderCode = fragShaderCode;
67 this->fragShaderCodeSize = fragShaderCodeSize;
68
70 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
72 }
73
78}
79
81{
83 = getPipelineAttributes();
84
85 VkShaderModule vertShaderModule
86 = createShaderModule(this->vertShaderCode, this->vertShaderCodeSize, device->device);
87 VkShaderModule fragShaderModule
88 = createShaderModule(this->fragShaderCode, this->fragShaderCodeSize, device->device);
89
90 VkPipelineShaderStageCreateInfo vertShaderStageInfo {};
91 vertShaderStageInfo.sType
92 = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
93 vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
94 vertShaderStageInfo.module = vertShaderModule;
95 vertShaderStageInfo.pName
96 = "main"; // start from main(vulkan can start from elsewhere also)
97
98 VkPipelineShaderStageCreateInfo fragShaderStageInfo {};
99 fragShaderStageInfo.sType
100 = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
101 fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
102 fragShaderStageInfo.module = fragShaderModule;
103 fragShaderStageInfo.pName = "main";
104
105 VkPipelineShaderStageCreateInfo shaderStages[]
106 = { vertShaderStageInfo, fragShaderStageInfo };
107
108 auto bindingDescription = pipelineAttributes.bindingDescriptions;
109 auto attributeDescriptions = pipelineAttributes.attributeDescriptions;
110
111 VkPipelineVertexInputStateCreateInfo vertexInputInfo {};
112 vertexInputInfo.sType
113 = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
114 vertexInputInfo.vertexBindingDescriptionCount
115 = static_cast<uint32_t>(bindingDescription.size());
116 vertexInputInfo.vertexAttributeDescriptionCount
117 = static_cast<uint32_t>(attributeDescriptions.size());
118 vertexInputInfo.pVertexBindingDescriptions = bindingDescription.data();
119 vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
120
121 VkPipelineInputAssemblyStateCreateInfo inputAssembly {};
122 inputAssembly.sType
123 = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
124 inputAssembly.topology
125 = pipelineAttributes.topology; // we are using indexed rendering so
126 // we need to use triangle list
127 inputAssembly.primitiveRestartEnable = VK_FALSE;
128
129 VkViewport viewport {};
130 viewport.x = 0.0f;
131 viewport.y = 0.0f;
132 viewport.width = (float)(*swapChain).swapChainExtent.width;
133 viewport.height = (float)(*swapChain).swapChainExtent.height;
134 viewport.minDepth = 0.0f;
135 viewport.maxDepth = 1.0f;
136
137 VkRect2D scissor {};
138 scissor.offset = { 0, 0 };
139 scissor.extent = (*swapChain).swapChainExtent;
140
141 VkPipelineViewportStateCreateInfo viewportState {};
142 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
143 viewportState.viewportCount = 1;
144 viewportState.pViewports = &viewport;
145 viewportState.scissorCount = 1;
146 viewportState.pScissors = &scissor;
147
148 VkPipelineRasterizationStateCreateInfo rasterizer {};
149 rasterizer.sType
150 = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
151 rasterizer.depthClampEnable = VK_FALSE;
152 rasterizer.rasterizerDiscardEnable = VK_FALSE;
153 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
154 rasterizer.lineWidth = 1.0f;
155 rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
156 rasterizer.frontFace = pipelineAttributes.frontFace; // counter clockwuise
157 rasterizer.depthBiasEnable = VK_FALSE;
158 rasterizer.depthBiasConstantFactor = 0.0f;
159 rasterizer.depthBiasClamp = 0.0f;
160 rasterizer.depthBiasSlopeFactor = 0.0f;
161
162 VkPipelineMultisampleStateCreateInfo multisampling {};
163 multisampling.sType
164 = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
165 multisampling.sampleShadingEnable = VK_FALSE;
166 multisampling.rasterizationSamples = device->msaaSamples;
167 multisampling.minSampleShading = 1.0f; // Optional
168 multisampling.pSampleMask = nullptr; // Optional
169 multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
170 multisampling.alphaToOneEnable = VK_FALSE;
171 multisampling.sampleShadingEnable = VK_TRUE;
172
173 VkPipelineColorBlendStateCreateInfo colorBlending {};
174 colorBlending.sType
175 = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
176 colorBlending.logicOpEnable = VK_FALSE;
177 colorBlending.logicOp = VK_LOGIC_OP_COPY;
178 colorBlending.attachmentCount = 1;
179 colorBlending.pAttachments = &pipelineAttributes.colorBlendAttachment;
180 colorBlending.blendConstants[0] = 0.0f;
181 colorBlending.blendConstants[1] = 0.0f;
182 colorBlending.blendConstants[2] = 0.0f;
183 colorBlending.blendConstants[3] = 0.0f;
184
185 std::vector<VkDynamicState> dynamicStates
186 = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
187 VkPipelineDynamicStateCreateInfo dynamicState {};
188 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
189 dynamicState.dynamicStateCount
190 = static_cast<uint32_t>(dynamicStates.size());
191 dynamicState.pDynamicStates = dynamicStates.data();
192
193 VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
194 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
195 pipelineLayoutInfo.setLayoutCount = 1; // Optional
196 pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; // Optional
197 pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
198 pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
199
200 if (vkCreatePipelineLayout(
201 device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout)
202 != VK_SUCCESS) {
203 throw std::runtime_error("failed to create pipeline layout!");
204 }
205
206 VkGraphicsPipelineCreateInfo pipelineInfo {};
207 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
208 pipelineInfo.stageCount = 2;
209 pipelineInfo.pStages = shaderStages;
210 pipelineInfo.pVertexInputState = &vertexInputInfo;
211 pipelineInfo.pInputAssemblyState = &inputAssembly;
212 pipelineInfo.pViewportState = &viewportState;
213 pipelineInfo.pRasterizationState = &rasterizer;
214 pipelineInfo.pMultisampleState = &multisampling;
215 pipelineInfo.pDepthStencilState = nullptr; // Optional
216 pipelineInfo.pColorBlendState = &colorBlending;
217 pipelineInfo.pDynamicState = &dynamicState;
218 pipelineInfo.layout = pipelineLayout;
219 pipelineInfo.renderPass = *renderPass;
220 pipelineInfo.subpass = 0;
221 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
222 pipelineInfo.basePipelineIndex = -1;
223
224 if (vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1,
225 &pipelineInfo, nullptr, &graphicsPipeline)
226 != VK_SUCCESS) {
227 throw std::runtime_error("failed to create graphics pipeline!");
228 }
229
230 // destory the shader modules
231 vkDestroyShaderModule(device->device, fragShaderModule, nullptr);
232 vkDestroyShaderModule(device->device, vertShaderModule, nullptr);
233}
234
236{
237 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
238 uniformBuffers[i].destroy();
239 }
240 vkDestroyDescriptorPool(device->device, descriptorPool, nullptr);
241 vkDestroyDescriptorSetLayout(device->device, descriptorSetLayout, nullptr);
242 vkDestroyPipeline(device->device, graphicsPipeline, nullptr);
243 vkDestroyPipelineLayout(device->device, pipelineLayout, nullptr);
244}
245
247{
248 std::vector<VkDescriptorType> descriptorTypes = getDescriptorTypes();
249
250 std::vector<VkDescriptorPoolSize> poolSizes { descriptorTypes.size() };
251
252 for (size_t i = 0; i < descriptorTypes.size(); i++) {
253 poolSizes[i].type = descriptorTypes[i];
254 poolSizes[i].descriptorCount
255 = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
256 }
257 VkDescriptorPoolCreateInfo poolInfo {};
258 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
259 poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
260 poolInfo.pPoolSizes = poolSizes.data();
261 poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
262 if (vkCreateDescriptorPool(
263 device->device, &poolInfo, nullptr, &descriptorPool)
264 != VK_SUCCESS) {
265 throw std::runtime_error("failed to create descriptor pool!");
266 }
267}
268
270{
271 std::vector<VkDescriptorType> descriptorTypes = getDescriptorTypes();
272 std::vector<VkShaderStageFlagBits> descriptorStages = getDescriptorStages();
273
274 if (descriptorTypes.size() != descriptorStages.size()) {
275 throw std::runtime_error(
276 "descriptorTypes and descriptorStages must be the same size");
277 }
278
279 std::vector<VkDescriptorSetLayoutBinding> bindings {
280 descriptorTypes.size()
281 };
282
283 for (size_t i = 0; i < descriptorTypes.size(); i++) {
284 bindings[i].binding = i;
285 bindings[i].descriptorType = descriptorTypes[i];
286 bindings[i].descriptorCount = 1;
287 bindings[i].stageFlags = descriptorStages[i];
288 bindings[i].pImmutableSamplers = nullptr;
289 }
290
291 VkDescriptorSetLayoutCreateInfo layoutInfo {};
292 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
293 layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
294 layoutInfo.pBindings = bindings.data();
295 if (vkCreateDescriptorSetLayout(
296 device->device, &layoutInfo, nullptr, &descriptorSetLayout)
297 != VK_SUCCESS) {
298 throw std::runtime_error("failed to create descriptor set layout!");
299 }
300}
301
303{
304 vkDestroyPipeline(device->device, graphicsPipeline, nullptr);
305 vkDestroyPipelineLayout(device->device, pipelineLayout, nullptr);
306 createGraphicsPipeline();
307}
This initializes, manages and destroys the logical and physical devices(GPU).
Definition device.hpp:47
void createDescriptorPool()
Creates the Vulkan descriptor pool for the object.
Definition object.cpp:246
virtual void destroy()=0
Destroys the object and releases associated resources.
Definition object.cpp:235
VkCommandPool commandPool
Definition object.hpp:143
Chronos::Engine::SwapChain * swapChain
Definition object.hpp:141
void recreateGraphicsPipeline()
Recreates the graphics pipeline for the object.
Definition object.cpp:302
unsigned char * vertShaderCode
Definition object.hpp:185
Chronos::Engine::Device * device
Definition object.hpp:140
std::vector< Chronos::Engine::UniformBuffer > uniformBuffers
Definition object.hpp:183
Chronos::Engine::ObjectType objectType
Definition object.hpp:137
void createDescriptorSetLayout()
Creates the Vulkan descriptor set layout for the object.
Definition object.cpp:269
void createGraphicsPipeline()
Creates the graphics pipeline for the object.
Definition object.cpp:80
void init(Chronos::Engine::Device *device, VkCommandPool commandPool, SwapChain *swapChain, VkSampler textureSampler, VkRenderPass *renderPass, ObjectType objectType, unsigned char *vertShaderCode, int vertShaderCodeSize, unsigned char *fragShaderCode, int fragShaderCodeSize)
Initializes the object.
Definition object.cpp:53
virtual void createDescriptorSets()=0
VkRenderPass * renderPass
Definition object.hpp:147
unsigned char * fragShaderCode
Definition object.hpp:187
void create()
Creates the swapchain image resources and chooses the optimal settings for given hardware.
static VkShaderModule createShaderModule(unsigned char *code, int code_size, VkDevice device)
Creates a shader module from given shader(SPIV) code.
Definition object.cpp:38
Contains the class for creating a generic object.
Structure defining attributes required for creating a graphics pipeline.
Definition object.hpp:43
VkPrimitiveTopology topology
Definition object.hpp:49
VkPipelineColorBlendAttachmentState colorBlendAttachment
Definition object.hpp:53
std::vector< VkVertexInputBindingDescription > bindingDescriptions
Definition object.hpp:45
std::vector< VkVertexInputAttributeDescription > attributeDescriptions
Definition object.hpp:47
#define MAX_FRAMES_IN_FLIGHT
The number of frames in flight.