#include "detail/graphics.h" namespace deerith { namespace graphics { void drawFrame(); } // namespace graphics void graphics::vulkan_test_loop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); drawFrame(); } } void graphics::create_vulkan_sync_objects() { image_available_semaphores.resize(MAX_FRAMES_IN_FLIGHT); render_finished_semaphores.resize(MAX_FRAMES_IN_FLIGHT); in_flight_fences.resize(MAX_FRAMES_IN_FLIGHT); VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VkFenceCreateInfo fenceInfo{}; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &image_available_semaphores[i]) != VK_SUCCESS || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &render_finished_semaphores[i]) != VK_SUCCESS || vkCreateFence(device, &fenceInfo, nullptr, &in_flight_fences[i]) != VK_SUCCESS) { deerith_graphics_error("failed to create synchronization objects for a frame!"); } } } void graphics::drawFrame() { vkWaitForFences(device, 1, &in_flight_fences[current_frame], VK_TRUE, UINT64_MAX); uint32_t image_index; VkResult result = vkAcquireNextImageKHR(device, swap_chain, UINT64_MAX, image_available_semaphores[current_frame], VK_NULL_HANDLE, &image_index); if (result == VK_ERROR_OUT_OF_DATE_KHR) { frame_buffer_resize = false; vulkan_recreate_swap_chain(); return; } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { deerith_graphics_error("failed to acquire swap chain image!"); } vkResetFences(device, 1, &in_flight_fences[current_frame]); vkResetCommandBuffer(command_buffers[current_frame], 0); record_command_buffer(command_buffers[current_frame], image_index); VkSubmitInfo submit_info{}; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; VkSemaphore waitSemaphores[] = {image_available_semaphores[current_frame]}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = waitSemaphores; submit_info.pWaitDstStageMask = waitStages; submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = &command_buffers[current_frame]; VkSemaphore signalSemaphores[] = {render_finished_semaphores[current_frame]}; submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = signalSemaphores; if (vkQueueSubmit(graphics_queue, 1, &submit_info, in_flight_fences[current_frame]) != VK_SUCCESS) { deerith_graphics_error("failed to submit draw command buffer!"); } VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.srcAccessMask = 0; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; VkSwapchainKHR swapChains[] = {swap_chain}; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &image_index; presentInfo.pResults = nullptr; result = vkQueuePresentKHR(pressent_queue, &presentInfo); if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || frame_buffer_resize) { vulkan_recreate_swap_chain(); frame_buffer_resize = false; } else if (result != VK_SUCCESS) { deerith_graphics_error("failed to present swap chain image!"); } current_frame = (current_frame + 1) % MAX_FRAMES_IN_FLIGHT; } } // namespace deerith