Chronos 0.0
A advanced 2D rendering and animation system
Loading...
Searching...
No Matches
Chronos::Engine::Engine Class Reference

#include <engine.hpp>

Collaboration diagram for Chronos::Engine::Engine:

Public Member Functions

 Engine ()
 Initlizes the engine.
 
void drawFrame ()
 Main draw call. Its responsible for drawing frames and resizing the window. To be added to the main game loop.
 
void resizeFrameBuffer ()
 Tells the engine that the window has to be resized. This is called by GLFW.
 
void setPresentMode (std::string mode)
 Changes the present mode of the swapchain.
 
 ~Engine ()
 This is the destructor of the engine.
 
void changeMSAA (std::string)
 
std::vector< std::string > getAvailableMSAAModes ()
 

Public Attributes

Chronos::Engine::ObjectManager objectManager
 
Chronos::Engine::TextureManager textureManager
 Used to create and manage textures.
 
int width = 800
 This is the initial width of the window. It can be changed later just by changing this directly.
 
int height = 600
 This is the initial width of the window. It can be changed later just by changing this directly.
 
GLFWwindow * window
 This is the GLFW window reference that is used by the engine.
 
float bgColor [3] = { 0.0f, 0.0f, 0.0f }
 This is the background color of the window.
 
Chronos::Engine::Device device = Chronos::Engine::Device()
 This is the object that manages the device.
 
Chronos::Engine::SwapChain swapChain = Chronos::Engine::SwapChain()
 This is the object that manages the swapchain.
 
VkCommandPool commandPool
 The command Pool.
 

Private Member Functions

void changeMSAASettings ()
 
void initWindow ()
 This function initializes the GLFW window.
 
void initVulkan ()
 The complicated process of initalizing the vulkan API is done here.
 
void cleanup ()
 Cleans up vulkan objects.
 
void createInstance ()
 Creates a vulkan instance.
 
void createSurface ()
 Creates the surface to render to.
 
void createSyncObjects ()
 Creates sync objects for rendering.
 
void changePresentMode ()
 

Private Attributes

bool changeMSAAFlag = false
 
VkSampleCountFlagBits newMSAAMode
 
bool framebufferResized = false
 Does the framebuffer need to be resized?
 
uint32_t currentFrame = 0
 The current frame to be rendered to.
 
VkInstance instance
 The Vulkan instance.
 
VkSurfaceKHR surface
 The surface to render to.
 
std::vector< VkSemaphore > imageAvailableSemaphores
 
std::vector< VkSemaphore > renderFinishedSemaphores
 
std::vector< VkFence > inFlightFences
 

Detailed Description

\brief This is the main vulkan backend for Chronos.
This is for use by the API only and should not be used for any other
purpose.

This is resposible for managing the object and shapes that related to
vulkan. It is also in charge of drawing frames and managing the window. It
automatically handles window resizing, creation and destruction of necessary
objects. Any shapes or text to be created is to be done throught the
shapeManager and textManager respectively.

In order to draw a frame, create a loop and call the drawFrame.

##Important
drawFrame will not handle inputs.
It will also draw only one frame per call.
Hence the inputs must be managed by the main loop.
This is done to allow flexibility in inputs and management of the frame
drawing.

## drawFrame() example
Suppose Engine class is initialized as engine
The following code snippet is an example of a basic rendering loop.
It also includes functionaility to close the window either when the escape
key is pressed or when the window is closed. For more on handling inputs,
please see the GLFW documentation.

~~~~~~~~~~~~~~~{.cpp}
    while (!glfwWindowShouldClose(engine.window)) {

if esc is pressed, then ask GLFW to close the window if (glfwGetKey(engine.window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(engine.window, true); } draw the frame engine.drawFrame(); } ~~~~~~~~~~~~~~~

Definition at line 81 of file engine.hpp.

Constructor & Destructor Documentation

◆ Engine()

Chronos::Engine::Engine::Engine ( )

Initlizes the engine.

During initialization of the engine, all the processes and calls needed to intialize vulkan and GLFW are done. No other function needs to be called to initialize the engine. During initialization the following occurs:

If the editor is enabled, then the editor(EditorRenderer) settings are initialized The window is created The vulkan API is initialized along with all the necessary objects.

Definition at line 37 of file engine.cpp.

38{
39#ifdef ENABLE_EDITOR
41#endif
42 // initialize the window and vulkan
43 initWindow();
44 LOG(3, "GLFW initialized")
45 initVulkan();
46 LOG(3, "Vulkan initialized")
47}
void initVulkan()
The complicated process of initalizing the vulkan API is done here.
Definition engine.cpp:74
void initWindow()
This function initializes the GLFW window.
Definition engine.cpp:58
#define LOG(LEVEL, MESSAGE)
Definition logging.hpp:60

References initVulkan(), initWindow(), and LOG.

Here is the call graph for this function:

◆ ~Engine()

Chronos::Engine::Engine::~Engine ( )

This is the destructor of the engine.

It basically stops the device, and runs the cleanup function. This is so that it is guranteed that Vulkan objects will be cleaned up correctly.

Definition at line 49 of file engine.cpp.

50{
51 vkDeviceWaitIdle(device.device);
52 cleanup();
53 LOG(3, "Engine cleaned up")
54}
VkDevice device
This is the logical device that is used by Vulkan.
Definition device.hpp:52
Chronos::Engine::Device device
This is the object that manages the device.
Definition engine.hpp:233
void cleanup()
Cleans up vulkan objects.
Definition engine.cpp:104

References LOG.

Member Function Documentation

◆ changeMSAA()

void Chronos::Engine::Engine::changeMSAA ( std::string  mode)

Definition at line 495 of file engine.cpp.

496{
497 if (mode == "64") {
498 this->newMSAAMode = VK_SAMPLE_COUNT_64_BIT;
499 } else if (mode == "32") {
500 this->newMSAAMode = VK_SAMPLE_COUNT_32_BIT;
501 } else if (mode == "16") {
502 this->newMSAAMode = VK_SAMPLE_COUNT_16_BIT;
503 } else if (mode == "8") {
504 this->newMSAAMode = VK_SAMPLE_COUNT_8_BIT;
505 } else if (mode == "4") {
506 this->newMSAAMode = VK_SAMPLE_COUNT_4_BIT;
507 } else if (mode == "2") {
508 this->newMSAAMode = VK_SAMPLE_COUNT_2_BIT;
509 } else if (mode == "1") {
510 this->newMSAAMode = VK_SAMPLE_COUNT_1_BIT;
511 } else {
512 throw std::runtime_error("Invalid MSAA mode");
513 }
514 if (this->newMSAAMode > device.maxMsaaSamples) {
515 throw std::runtime_error("Invalid MSAA mode");
516 }
517 this->changeMSAAFlag = true;
518 LOG(3, "MSAA to be changed to " + mode)
519}
VkSampleCountFlagBits maxMsaaSamples
Definition device.hpp:82
VkSampleCountFlagBits newMSAAMode
Definition engine.hpp:255

References LOG.

Here is the caller graph for this function:

◆ changeMSAASettings()

void Chronos::Engine::Engine::changeMSAASettings ( )
private

Definition at line 521 of file engine.cpp.

522{
524 this->swapChain.changeMsaa();
526#ifdef ENABLE_EDITOR
527 this->gui.changeMsaa();
528#endif
529 LOG(3, "MSAA changed to " + std::to_string(device.msaaSamples))
530}
VkSampleCountFlagBits msaaSamples
This sets the MSAA samples count.
Definition device.hpp:80
Chronos::Engine::ObjectManager objectManager
Definition engine.hpp:99
Chronos::Engine::SwapChain swapChain
This is the object that manages the swapchain.
Definition engine.hpp:243
void changeMsaa()
Changes the MSAA count of the swapchain images.

References LOG.

◆ changePresentMode()

void Chronos::Engine::Engine::changePresentMode ( )
private

Definition at line 442 of file engine.cpp.

443{
444 vkDeviceWaitIdle(device.device);
447#ifdef ENABLE_EDITOR
448 gui.recreate();
449#endif
450}
void recreate()
When the swapchain is rendered invalid, recreate it.

◆ cleanup()

void Chronos::Engine::Engine::cleanup ( )
private

Cleans up vulkan objects.

When the engine is exited, we need to clean up the vulkan objects. If we do not do this, vulkan validation layers will throw errors. The following occurs during this function:

  • The device is stopped
  • The swapchain is cleaned up
  • The shape and text manager along with their objects are cleaned up
  • The sync objects are cleaned up
  • The command Pool is destroyed
  • The device, surface and instance are destroyed
  • Window is destroyed and GLFW is terminated

Definition at line 104 of file engine.cpp.

105{
106 // after we are done, we need to cleanup all the resources we created
108 LOG(3, "Swapchain cleaned up")
109 objectManager.destroy();
110 LOG(3, "Object manager cleaned up")
111 textureManager.destroy();
112 LOG(3, "Texture manager cleaned up")
113#ifdef ENABLE_EDITOR
114 gui.destroy();
115 LOG(3, "Editor cleaned up")
116#endif
117 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
118 vkDestroySemaphore(device.device, renderFinishedSemaphores[i], nullptr);
119 vkDestroySemaphore(device.device, imageAvailableSemaphores[i], nullptr);
120 vkDestroyFence(device.device, inFlightFences[i], nullptr);
121 }
122 vkDestroyCommandPool(device.device, commandPool, nullptr);
123 LOG(3, "Command pool cleaned up")
124#ifdef ENABLE_VULKAN_VALIDATION_LAYERS
125 DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
126 LOG(3, "Debug messenger cleaned up")
127#endif
128 device.destroy(); // destroy the logical device
129 LOG(3, "Device cleaned up")
130 vkDestroySurfaceKHR(instance, surface, nullptr);
131 vkDestroyInstance(instance, nullptr);
132 glfwDestroyWindow(window);
133 glfwTerminate();
134 LOG(3, "GLFW cleaned up")
135}
void destroy()
This is the function that destroys the device.
Definition device.cpp:36
VkCommandPool commandPool
The command Pool.
Definition engine.hpp:251
std::vector< VkSemaphore > imageAvailableSemaphores
Definition engine.hpp:306
VkInstance instance
The Vulkan instance.
Definition engine.hpp:284
std::vector< VkSemaphore > renderFinishedSemaphores
Definition engine.hpp:307
std::vector< VkFence > inFlightFences
Definition engine.hpp:308
GLFWwindow * window
This is the GLFW window reference that is used by the engine.
Definition engine.hpp:124
Chronos::Engine::TextureManager textureManager
Used to create and manage textures.
Definition engine.hpp:107
VkSurfaceKHR surface
The surface to render to.
Definition engine.hpp:304
void cleanup()
Cleans up the assets that are rendered invalid during MSAA changes or swapchain.
void destroy()
Destroys the texture manager.
#define MAX_FRAMES_IN_FLIGHT
The number of frames in flight.

References LOG, and MAX_FRAMES_IN_FLIGHT.

◆ createInstance()

void Chronos::Engine::Engine::createInstance ( )
private

Creates a vulkan instance.

This function sets some of the information about our app. It enables all the extensions and validation layers.

Definition at line 319 of file engine.cpp.

320{
321 VkApplicationInfo appInfo {};
322 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
323 appInfo.pApplicationName = GAME_NAME;
324 appInfo.applicationVersion = VK_MAKE_VERSION(
325 GAME_VERSION_MAJOR, GAME_VERSION_MINOR, GAME_VERSION_PATCH);
326 appInfo.pEngineName = "Chronos";
327 appInfo.engineVersion = VK_MAKE_VERSION(
328 CHRONOS_VERSION_MAJOR, CHRONOS_VERSION_MINOR, CHRONOS_VERSION_PATCH);
329 // using vulkan 1.3 as we need shader printf support
330 appInfo.apiVersion = VK_API_VERSION_1_0;
331 LOG(3,
332 "engine version: " + std::to_string(CHRONOS_VERSION_MAJOR) + "."
333 + std::to_string(CHRONOS_VERSION_MINOR) + "."
334 + std::to_string(CHRONOS_VERSION_PATCH))
335 LOG(3,
336 "game version: " + std::to_string(GAME_VERSION_MAJOR) + "."
337 + std::to_string(GAME_VERSION_MINOR) + "."
338 + std::to_string(GAME_VERSION_PATCH))
339 LOG(3, "game name: " + std::string(GAME_NAME))
340
341 VkInstanceCreateInfo createInfo {};
342 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
343 createInfo.pApplicationInfo = &appInfo;
344
345 // uint32_t glfwExtensionCount = 0;
346 // const char** glfwExtensions;
347 // glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
348
349 auto extensions = getRequiredExtensions();
350 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
351 createInfo.ppEnabledExtensionNames = extensions.data();
352
353#ifdef ENABLE_VULKAN_VALIDATION_LAYERS
354 if (!checkValidationLayerSupport()) {
355 LOG(1, "Validation layers requested, but not available")
356 throw std::runtime_error(
357 "Validation layers requested, but not available");
358 }
359#endif
360
361 createInfo.enabledLayerCount = 0;
362 createInfo.pNext = nullptr;
363
364#ifdef ENABLE_VULKAN_VALIDATION_LAYERS
365 createInfo.enabledLayerCount
366 = static_cast<uint32_t>(validationLayers.size());
367 createInfo.ppEnabledLayerNames = validationLayers.data();
368 // uncomment below if u need fine details. It just creates extra verbose
369 // generally not needed
370 // VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
371 // populateDebugMessengerCreateInfo(debugCreateInfo);
372 // createInfo.pNext =
373 // (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
374#endif
375 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
376 LOG(1, "Failed to create instance")
377 throw std::runtime_error("Failed to create instance");
378 }
379}
static std::vector< const char * > getRequiredExtensions()
Gets the required extensions to be enabled.
Definition engine.cpp:305

References getRequiredExtensions(), and LOG.

Here is the call graph for this function:

◆ createSurface()

void Chronos::Engine::Engine::createSurface ( )
private

Creates the surface to render to.

Definition at line 395 of file engine.cpp.

396{
397 if (glfwCreateWindowSurface(instance, window, nullptr, &surface)
398 != VK_SUCCESS) {
399 LOG(1, "Failed to create window surface")
400 throw std::runtime_error("Failed to create window surface");
401 }
402}

References LOG.

◆ createSyncObjects()

void Chronos::Engine::Engine::createSyncObjects ( )
private

Creates sync objects for rendering.

Since Vulkan uses explict sync, we need sync objects such as fences and semaphores to maintain synchronization.

Since there are multiple frames in flight, we need multiple copies for each sync object. In particular, we need:

  • A semaphore to signal that an image is available for rendering
  • A semaphore to signal that rendering has finished for a frame
  • In Flight fences to ensure that the renderer is synchronized with the GPU

Definition at line 404 of file engine.cpp.

405{
409
410 VkSemaphoreCreateInfo semaphoreInfo {};
411 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
412
413 VkFenceCreateInfo fenceInfo {};
414 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
415 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
416
417 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
418 if (vkCreateSemaphore(device.device, &semaphoreInfo, nullptr,
420 != VK_SUCCESS
421 || vkCreateSemaphore(device.device, &semaphoreInfo, nullptr,
423 != VK_SUCCESS
424 || vkCreateFence(
425 device.device, &fenceInfo, nullptr, &inFlightFences[i])
426 != VK_SUCCESS) {
427 LOG(1, "Failed to create synchronization objects for a frame")
428 throw std::runtime_error(
429 "failed to create synchronization objects for a frame!");
430 }
431 }
432}

References LOG, and MAX_FRAMES_IN_FLIGHT.

◆ drawFrame()

void Chronos::Engine::Engine::drawFrame ( )

Main draw call. Its responsible for drawing frames and resizing the window. To be added to the main game loop.

During this function the following occurs:

  • It waits for the previous frame to be drawn and presented
  • It acquires the next image from the swapchain
  • If the window is resized, then the swapchain and any framebuffers and renderpasses are recreated
  • It updates the values of the shapes and text
  • Resets the sync objects
  • It records the command buffers
  • Configures the sync objects
  • Submits the command buffers. Note: Only after vkQueueSubmit is called, the command buffers are executed and the frame is rendered.
  • Presents the image to the screen

Definition at line 137 of file engine.cpp.

138{
142 LOG(3, "Present mode changed")
143 }
144 if (this->changeMSAAFlag) {
145 vkDeviceWaitIdle(device.device);
147 this->changeMSAAFlag = false;
148 LOG(3, "MSAA changed")
149 }
150 // wait for the previous frame to finish
151 glfwPollEvents();
152
153#ifdef CHRONOS_PROFILING
154 std::chrono::steady_clock::time_point start
155 = std::chrono::steady_clock::now();
156#endif
157
158 vkWaitForFences(
159 device.device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
160
161#ifdef CHRONOS_PROFILING
162 this->waitTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
163 std::chrono::steady_clock::now() - start)
164 .count();
165#endif
166
167 // get the index of the next image to render to
168 uint32_t imageIndex;
169 VkResult result = vkAcquireNextImageKHR(device.device, swapChain.swapChain,
170 UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE,
171 &imageIndex);
172
173 // if window has been minimized, then recreate the swap chain and other
174 // things
175 if (result == VK_ERROR_OUT_OF_DATE_KHR) {
177 LOG(3, "Swapchain recreated")
178 objectManager.recreate();
179 LOG(3, "Object manager recreated")
180#ifdef ENABLE_EDITOR
181 gui.recreate();
182 LOG(3, "Editor recreated")
183#endif
184 return;
185 } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
186 LOG(1, "Failed to acquire swap chain image")
187 throw std::runtime_error("Failed to acquire swap chain image");
188 }
189#ifdef CHRONOS_PROFILING
190 auto startUpdate = std::chrono::steady_clock::now();
191#endif
192 // update the shapes and text
194
195#ifdef ENABLE_EDITOR
196 gui.update();
197#endif
198#ifdef CHRONOS_PROFILING
199 this->updateTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
200 std::chrono::steady_clock::now() - startUpdate)
201 .count();
202#endif
203 LOG(4, "Managers updated")
204
205 // reset the fences
206 vkResetFences(device.device, 1, &inFlightFences[currentFrame]);
207
208 // record the command buffers
209 objectManager.render(currentFrame, imageIndex, bgColor);
210#ifdef ENABLE_EDITOR
211 gui.render(currentFrame, imageIndex, bgColor);
212#endif
213 LOG(4, "Managers command buffers recorded")
214
215 // configure the semaphores
216 VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
217 VkPipelineStageFlags waitStages[]
218 = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
219 VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
220
221 // submit the command buffers
222 std::vector<VkCommandBuffer> submitCommandBuffers
224
225#ifdef ENABLE_EDITOR
226 submitCommandBuffers.push_back(gui.commandBuffers[currentFrame]);
227#endif
228 VkSubmitInfo submitInfo {};
229 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
230 submitInfo.waitSemaphoreCount = 1;
231 submitInfo.pWaitSemaphores = waitSemaphores;
232 submitInfo.pWaitDstStageMask = waitStages;
233 submitInfo.commandBufferCount
234 = static_cast<uint32_t>(submitCommandBuffers.size());
235 submitInfo.pCommandBuffers = submitCommandBuffers.data();
236 submitInfo.signalSemaphoreCount = 1;
237 submitInfo.pSignalSemaphores = signalSemaphores;
238
239 if (vkQueueSubmit(
241 != VK_SUCCESS) {
242 LOG(1, "Failed to submit draw command buffer")
243 throw std::runtime_error("failed to submit draw command buffer!");
244 }
245 LOG(4, "Command buffers submitted")
246
247#ifdef ENABLE_EDITOR
248 gui.renderAdditionalViewports();
249#endif
250
251#ifdef CHRONOS_PROFILING
252 this->cpuTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
253 std::chrono::steady_clock::now() - start)
254 .count();
255 auto startPresent = std::chrono::steady_clock::now();
256#endif
257
258 // present the image
259 VkPresentInfoKHR presentInfo {};
260 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
261 presentInfo.waitSemaphoreCount = 1;
262 presentInfo.pWaitSemaphores = signalSemaphores;
263 VkSwapchainKHR swapChains[] = { swapChain.swapChain };
264 presentInfo.swapchainCount = 1;
265 presentInfo.pSwapchains = swapChains;
266 presentInfo.pImageIndices = &imageIndex;
267 presentInfo.pResults = nullptr;
268 result = vkQueuePresentKHR(device.presentQueue, &presentInfo);
269 if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR
271 framebufferResized = false;
273 LOG(3, "Swapchain recreated")
274 objectManager.recreate();
275 LOG(3, "Object Manager recreated")
276#ifdef ENABLE_EDITOR
277 gui.recreate();
278 LOG(3, "Editor recreated")
279#endif
280 } else if (result != VK_SUCCESS) {
281 LOG(1, "Failed to present swap chain image")
282 throw std::runtime_error("Failed to present swap chain image");
283 }
284#ifdef CHRONOS_PROFILING
285 this->presentTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
286 std::chrono::steady_clock::now() - startPresent)
287 .count();
288 this->totalTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
289 std::chrono::steady_clock::now() - start)
290 .count();
291#endif
292 // update the current frame
294 LOG(4, "Current frame is " + std::to_string(currentFrame))
295}
VkQueue presentQueue
This is the queue that is used for presentation of the rendered frames.
Definition device.hpp:71
VkQueue graphicsQueue
This is the queue that is used for graphics rendering.
Definition device.hpp:65
uint32_t currentFrame
The current frame to be rendered to.
Definition engine.hpp:276
float bgColor[3]
This is the background color of the window.
Definition engine.hpp:132
bool framebufferResized
Does the framebuffer need to be resized?
Definition engine.hpp:268
void render(uint32_t currentFrame, uint32_t imageIndex, float bgColor[3])
std::vector< VkCommandBuffer > commandBuffers
void update(uint32_t currentFrame)
VkSwapchainKHR swapChain
Vulkan swapchain object.

References LOG, and MAX_FRAMES_IN_FLIGHT.

◆ getAvailableMSAAModes()

std::vector< std::string > Chronos::Engine::Engine::getAvailableMSAAModes ( )

Definition at line 469 of file engine.cpp.

470{
471 VkSampleCountFlagBits maxSample = device.maxMsaaSamples;
472 std::vector<std::string> modes;
473 if (VK_SAMPLE_COUNT_64_BIT <= maxSample) {
474 modes.push_back("64");
475 }
476 if (VK_SAMPLE_COUNT_32_BIT <= maxSample) {
477 modes.push_back("32");
478 }
479 if (VK_SAMPLE_COUNT_16_BIT <= maxSample) {
480 modes.push_back("16");
481 }
482 if (VK_SAMPLE_COUNT_8_BIT <= maxSample) {
483 modes.push_back("8");
484 }
485 if (VK_SAMPLE_COUNT_4_BIT <= maxSample) {
486 modes.push_back("4");
487 }
488 if (VK_SAMPLE_COUNT_2_BIT <= maxSample) {
489 modes.push_back("2");
490 }
491 modes.push_back("1");
492 return modes;
493}
Here is the caller graph for this function:

◆ initVulkan()

void Chronos::Engine::Engine::initVulkan ( )
private

The complicated process of initalizing the vulkan API is done here.

The following occurs during this function:

  • The vulkan instance is created
  • The validation layers are setup
  • The surface is created
  • The device is initialized
  • The swapchain is initialized
  • The command pool is created
  • The shape and text managers are initialized

Also the objects needed for the editor are also created here

Definition at line 74 of file engine.cpp.

75{
76 // create the basic objects
78
79#ifdef ENABLE_VULKAN_VALIDATION_LAYERS
80 setupDebugMessenger();
81#endif
84 LOG(3, "Device initialized")
86 LOG(3, "Swapchain initialized")
88 LOG(3, "Command pool initialized")
89
90 // initalize the object manager
92
94 LOG(3, "Texture manager initialized")
95
97
98#ifdef ENABLE_EDITOR
100 LOG(3, "Editor initialized")
101#endif
102}
void init(VkInstance instance, VkSurfaceKHR surface)
This is the function that initializes the devices and queues.
Definition device.cpp:28
void createSurface()
Creates the surface to render to.
Definition engine.cpp:395
void createSyncObjects()
Creates sync objects for rendering.
Definition engine.cpp:404
void createInstance()
Creates a vulkan instance.
Definition engine.cpp:319
void init(Chronos::Engine::Device *device, VkCommandPool commandPool)
Initializes the texture manager.
VkCommandPool createCommandPool(Chronos::Engine::Device device, VkSurfaceKHR surface)
Creates a command pool for a given device and surface.
Definition helper.cpp:157

References Chronos::Engine::createCommandPool(), and LOG.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initWindow()

void Chronos::Engine::Engine::initWindow ( )
private

This function initializes the GLFW window.

It creates a GLFWwindow* and stores it in the window variable. It also sets the window hints sets the framebuffer callback.

Definition at line 58 of file engine.cpp.

59{
60 // initialize glfw with a resizeable window
61 glfwInit();
62 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
63
64 window = glfwCreateWindow(width, height, GAME_NAME, nullptr, nullptr);
65 if (window == nullptr) {
66 LOG(1, "Failed to create GLFW window")
67 throw std::runtime_error("Failed to create GLFW window");
68 }
69 glfwMakeContextCurrent(window);
70 glfwSetWindowUserPointer(window, this);
71 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
72}
int height
This is the initial width of the window. It can be changed later just by changing this directly.
Definition engine.hpp:119
int width
This is the initial width of the window. It can be changed later just by changing this directly.
Definition engine.hpp:113
static void framebuffer_size_callback(GLFWwindow *window, int width, int height)
Definition engine.cpp:30

References framebuffer_size_callback(), and LOG.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resizeFrameBuffer()

void Chronos::Engine::Engine::resizeFrameBuffer ( )

Tells the engine that the window has to be resized. This is called by GLFW.

It sets the flag that window has to be resized. Later during the drawFrame function, the swapchain is recreated and resets the flag. This tells Vulkan that the swapChain has to be recreated.

Definition at line 56 of file engine.cpp.

56{ framebufferResized = true; }
Here is the caller graph for this function:

◆ setPresentMode()

void Chronos::Engine::Engine::setPresentMode ( std::string  mode)

Changes the present mode of the swapchain.

The present mode is the mode in which the images are presented to the screen. There are various methods available. this can be used to cap or unlock the framerate, control tearing etc. Some of the presentation modes available are:

  • immediate: Images submitted by your application are transferred to the screen right away, which may result in tearing.
  • fifo : The swap chain is a queue where the display takes an image from the front of the queue when the display is refreshed and the program inserts rendered images at the back of the queue.If the queue is full then the program has to wait. This is most similar to vertical sync as found in modern games.The moment that the display is refreshed is known as "vertical blank".
  • fifo_relaxed : This mode only differs from the previous one if the application is late and the queue was empty at the last vertical blank. Instead of waiting for the next vertical blank, the image is transferred right away when it finally arrives.This may result in visible tearing.
  • mailbox : This is another variation of the second mode.Instead of blocking the application when the queue is full, the images that are already queued are simply replaced with the newer ones.This mode can be used to render frames as fast as possible while still avoiding tearing, resulting in fewer latency issues than standard vertical sync.This is commonly known as "triple buffering", although the existence of three buffers alone does not necessarily mean that the framerate
Parameters
modeThe mode to change to. It can be one of the following:
  • immediate
  • fifo
  • fifo_relaxed
  • mailbox

Definition at line 452 of file engine.cpp.

453{
454 if (mode == "immediate") {
455 this->swapChain.preferredPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
456 } else if (mode == "fifo") {
457 this->swapChain.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
458 } else if (mode == "fifo_relaxed") {
459 this->swapChain.preferredPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
460 } else if (mode == "mailbox") {
461 this->swapChain.preferredPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
462 } else {
463 throw std::runtime_error("Invalid present mode");
464 }
465 this->swapChain.changePresentMode = true;
466 LOG(3, "Present mode set to " + mode)
467}
VkPresentModeKHR preferredPresentMode
Preferred present mode for the swapchain.

References LOG.

Here is the caller graph for this function:

Member Data Documentation

◆ bgColor

float Chronos::Engine::Engine::bgColor[3] = { 0.0f, 0.0f, 0.0f }

This is the background color of the window.

It can be changed by changing the values inside this float. The values should be in the range of 0 to 1.

Definition at line 132 of file engine.hpp.

132{ 0.0f, 0.0f, 0.0f };

◆ changeMSAAFlag

bool Chronos::Engine::Engine::changeMSAAFlag = false
private

Definition at line 254 of file engine.hpp.

◆ commandPool

VkCommandPool Chronos::Engine::Engine::commandPool

The command Pool.

All command buffers are allocated from a command pool. This is where the command pool is stored.

Definition at line 251 of file engine.hpp.

◆ currentFrame

uint32_t Chronos::Engine::Engine::currentFrame = 0
private

The current frame to be rendered to.

Since there will be multiple frames in flight, we need to keep track of which frame is currently being rendered.

Definition at line 276 of file engine.hpp.

◆ device

Chronos::Engine::Device Chronos::Engine::Engine::device = Chronos::Engine::Device()

This is the object that manages the device.

This is due to the fact that device initialization and management is a complicated process. Also there are multiple variables that are needed for this. Hence for simplicity, a class was created for this purpose.

Definition at line 233 of file engine.hpp.

◆ framebufferResized

bool Chronos::Engine::Engine::framebufferResized = false
private

Does the framebuffer need to be resized?

When the window is resized, or minimized, the swapchain needs to be recreated. GLFW will tell us that this needs to happen, and when it does, this flag is set to true. The next time the drawFrame function is called, the swapchain will be recreated. During that time, this flag will be set to false.

Definition at line 268 of file engine.hpp.

◆ height

int Chronos::Engine::Engine::height = 600

This is the initial width of the window. It can be changed later just by changing this directly.

Definition at line 119 of file engine.hpp.

◆ imageAvailableSemaphores

std::vector<VkSemaphore> Chronos::Engine::Engine::imageAvailableSemaphores
private

Definition at line 306 of file engine.hpp.

◆ inFlightFences

std::vector<VkFence> Chronos::Engine::Engine::inFlightFences
private

Definition at line 308 of file engine.hpp.

◆ instance

VkInstance Chronos::Engine::Engine::instance
private

The Vulkan instance.

When initializing Vulkan, the first thing we create is an instance. This is where is it stored. We need this during cleanup

Definition at line 284 of file engine.hpp.

◆ newMSAAMode

VkSampleCountFlagBits Chronos::Engine::Engine::newMSAAMode
private

Definition at line 255 of file engine.hpp.

◆ objectManager

Chronos::Engine::ObjectManager Chronos::Engine::Engine::objectManager

Definition at line 99 of file engine.hpp.

◆ renderFinishedSemaphores

std::vector<VkSemaphore> Chronos::Engine::Engine::renderFinishedSemaphores
private

Definition at line 307 of file engine.hpp.

◆ surface

VkSurfaceKHR Chronos::Engine::Engine::surface
private

The surface to render to.

For rendering to the window from the Vulkan framebuffer, we need a surface.

Definition at line 304 of file engine.hpp.

◆ swapChain

Chronos::Engine::SwapChain Chronos::Engine::Engine::swapChain = Chronos::Engine::SwapChain()

This is the object that manages the swapchain.

All the swapchain related functions are handled by this object. This is due to the fact that swapChain needs to be constantly mananged and recreated due to various conditions.

Definition at line 243 of file engine.hpp.

◆ textureManager

Chronos::Engine::TextureManager Chronos::Engine::Engine::textureManager

Used to create and manage textures.

To add or remove textures, one may call the necessary methods in this class.

Definition at line 107 of file engine.hpp.

◆ width

int Chronos::Engine::Engine::width = 800

This is the initial width of the window. It can be changed later just by changing this directly.

Definition at line 113 of file engine.hpp.

◆ window

GLFWwindow* Chronos::Engine::Engine::window

This is the GLFW window reference that is used by the engine.

Definition at line 124 of file engine.hpp.


The documentation for this class was generated from the following files: