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")
115 LOG(3,
"Editor cleaned up")
118 vkDestroySemaphore(device.device, renderFinishedSemaphores[i],
nullptr);
119 vkDestroySemaphore(device.device, imageAvailableSemaphores[i],
nullptr);
120 vkDestroyFence(device.device, inFlightFences[i],
nullptr);
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")
129 LOG(3,
"Device cleaned up")
130 vkDestroySurfaceKHR(instance, surface,
nullptr);
131 vkDestroyInstance(instance,
nullptr);
132 glfwDestroyWindow(window);
134 LOG(3,
"GLFW cleaned up")
139 if (swapChain.changePresentMode) {
141 swapChain.changePresentMode =
false;
142 LOG(3,
"Present mode changed")
144 if (this->changeMSAAFlag) {
145 vkDeviceWaitIdle(device.device);
146 changeMSAASettings();
147 this->changeMSAAFlag =
false;
148 LOG(3,
"MSAA changed")
153#ifdef CHRONOS_PROFILING
154 std::chrono::steady_clock::time_point start
155 = std::chrono::steady_clock::now();
159 device.device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
161#ifdef CHRONOS_PROFILING
162 this->waitTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
163 std::chrono::steady_clock::now() - start)
169 VkResult result = vkAcquireNextImageKHR(device.device, swapChain.swapChain,
170 UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE,
175 if (result == VK_ERROR_OUT_OF_DATE_KHR) {
176 swapChain.recreate();
177 LOG(3,
"Swapchain recreated")
178 objectManager.recreate();
179 LOG(3,
"Object manager recreated")
182 LOG(3,
"Editor recreated")
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");
189#ifdef CHRONOS_PROFILING
190 auto startUpdate = std::chrono::steady_clock::now();
193 objectManager.update(currentFrame);
198#ifdef CHRONOS_PROFILING
199 this->updateTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
200 std::chrono::steady_clock::now() - startUpdate)
203 LOG(4,
"Managers updated")
206 vkResetFences(device.device, 1, &inFlightFences[currentFrame]);
209 objectManager.render(currentFrame, imageIndex, bgColor);
211 gui.render(currentFrame, imageIndex, bgColor);
213 LOG(4,
"Managers command buffers recorded")
216 VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
217 VkPipelineStageFlags waitStages[]
218 = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
219 VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
222 std::vector<VkCommandBuffer> submitCommandBuffers
223 = { objectManager.commandBuffers[currentFrame] };
226 submitCommandBuffers.push_back(gui.commandBuffers[currentFrame]);
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;
240 device.graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame])
242 LOG(1,
"Failed to submit draw command buffer")
243 throw std::runtime_error(
"failed to submit draw command buffer!");
245 LOG(4,
"Command buffers submitted")
248 gui.renderAdditionalViewports();
251#ifdef CHRONOS_PROFILING
252 this->cpuTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
253 std::chrono::steady_clock::now() - start)
255 auto startPresent = std::chrono::steady_clock::now();
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
270 || framebufferResized) {
271 framebufferResized =
false;
272 swapChain.recreate();
273 LOG(3,
"Swapchain recreated")
274 objectManager.recreate();
275 LOG(3,
"Object Manager recreated")
278 LOG(3,
"Editor recreated")
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");
284#ifdef CHRONOS_PROFILING
285 this->presentTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
286 std::chrono::steady_clock::now() - startPresent)
288 this->totalTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
289 std::chrono::steady_clock::now() - start)
294 LOG(4,
"Current frame is " + std::to_string(currentFrame))
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);
330 appInfo.apiVersion = VK_API_VERSION_1_0;
332 "engine version: " + std::to_string(CHRONOS_VERSION_MAJOR) +
"."
333 + std::to_string(CHRONOS_VERSION_MINOR) +
"."
334 + std::to_string(CHRONOS_VERSION_PATCH))
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))
341 VkInstanceCreateInfo createInfo {};
342 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
343 createInfo.pApplicationInfo = &appInfo;
350 createInfo.enabledExtensionCount =
static_cast<uint32_t
>(extensions.size());
351 createInfo.ppEnabledExtensionNames = extensions.data();
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");
361 createInfo.enabledLayerCount = 0;
362 createInfo.pNext =
nullptr;
364#ifdef ENABLE_VULKAN_VALIDATION_LAYERS
365 createInfo.enabledLayerCount
366 =
static_cast<uint32_t
>(validationLayers.size());
367 createInfo.ppEnabledLayerNames = validationLayers.data();
375 if (vkCreateInstance(&createInfo,
nullptr, &instance) != VK_SUCCESS) {
376 LOG(1,
"Failed to create instance")
377 throw std::runtime_error(
"Failed to create instance");
410 VkSemaphoreCreateInfo semaphoreInfo {};
411 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
413 VkFenceCreateInfo fenceInfo {};
414 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
415 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
418 if (vkCreateSemaphore(device.device, &semaphoreInfo,
nullptr,
419 &imageAvailableSemaphores[i])
421 || vkCreateSemaphore(device.device, &semaphoreInfo,
nullptr,
422 &renderFinishedSemaphores[i])
425 device.device, &fenceInfo,
nullptr, &inFlightFences[i])
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!");