diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2023-10-17 16:49:31 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2023-10-17 16:49:31 -0400 |
| commit | eff34c523b4816bb06ffbc19e6d368cac35f538c (patch) | |
| tree | 26678623a8b854c99598da149e14e183087e9670 /src | |
| parent | f5917baf1f3f7f1766ae3730727f83f7a708439c (diff) | |
large refactor for tick rate and handling vkPresentMode
Diffstat (limited to 'src')
| -rw-r--r-- | src/game-settings.hpp | 9 | ||||
| -rw-r--r-- | src/game.cpp | 13 | ||||
| -rw-r--r-- | src/main.cpp | 61 | ||||
| -rw-r--r-- | src/window.cpp | 55 | ||||
| -rw-r--r-- | src/window.hpp | 1 |
5 files changed, 96 insertions, 43 deletions
diff --git a/src/game-settings.hpp b/src/game-settings.hpp index a624bd6..cc20233 100644 --- a/src/game-settings.hpp +++ b/src/game-settings.hpp @@ -7,20 +7,23 @@ struct GameSettings { bool isGameRunning = true; bool isGamePaused = false; - bool isFramerateUnlocked = true; bool isShowingEditor = true; bool isRenderingDebug = false; std::chrono::steady_clock steadyClock; int64_t targetFPS = 144; int64_t minFPS = 20; - double deltaPerFrame = 1 / double(targetFPS); - double minimumDeltaPerFrame = 1 / double(minFPS); + double deltaPerFrame = 1.0 / double(targetFPS); + double minimumDeltaPerFrame = 1.0 / double(minFPS); struct { bool isShowingConsole = true; bool isShowingEntityList = true; bool isShowingSceneEditor = true; bool isShowingUBO = true; } editorSettings; + struct { + bool isFramerateUnlocked = false; + bool isWaitingForVsync = true; + } graphicsSettings; }; extern GameSettings pkeSettings; diff --git a/src/game.cpp b/src/game.cpp index 5863ecc..a0be182 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -387,6 +387,17 @@ void RecordImGuiEditorWrapper() { } if (ImGui::BeginMenu("Debug")) { ImGui::Checkbox("Show Debug Hitboxes", &pkeSettings.isRenderingDebug); + if (ImGui::Checkbox("Uncap Framerate", &pkeSettings.graphicsSettings.isFramerateUnlocked)) { + shouldRecreateSwapchain = true; + } + if (ImGui::Checkbox("wait for v-sync", &pkeSettings.graphicsSettings.isWaitingForVsync)) { + shouldRecreateSwapchain = true; + } + // ImGui::Checkbox("Uncap Tickrate", &pkeSettings.isTickrateUnlocked); + + ImGuiIO &io = ImGui::GetIO(); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::EndMenu(); } ImGui::EndMainMenuBar(); @@ -622,8 +633,6 @@ void RecordImGuiSceneEditor() { ImGui::End(); return; } - ImGuiIO &io = ImGui::GetIO(); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); if (ImGui::Button("Create Entity Type")) { ImGui::OpenPopup("CreateEntityType"); } diff --git a/src/main.cpp b/src/main.cpp index bd9dee0..fcddf80 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ #include "window.hpp" void signal_handler(int signal_num) { - printf("Received signal: %d - shutting down\n", signal_num); + fprintf(stdout, "Received signal: %d - shutting down\n", signal_num); pkeSettings.isGameRunning = false; } @@ -29,7 +29,7 @@ void Tick(double delta) { int main() { signal(SIGTERM, signal_handler); - printf("PKE ENTERING\n"); + fprintf(stdout, "PKE ENTERING\n"); try { AM_Init(); Game_Init(); @@ -49,8 +49,10 @@ int main() { glfwPollEvents(); + int64_t nsAheadHolder = 0.0; if (nsAhead > 0) { - std::this_thread::sleep_until(lastTimePoint + GameTimeDuration(nsAhead + 1)); + nsAheadHolder = nsAhead; + std::this_thread::sleep_for(GameTimeDuration(nsAhead)); nsAhead = 0; } if (vidMode.refreshRate != pkeSettings.targetFPS) { @@ -59,23 +61,23 @@ int main() { } GameTimePoint currentTimePoint = pkeSettings.steadyClock.now(); - double deltaThisTick = (currentTimePoint - lastTimePoint).count() / NANO_DENOM_DOUBLE; + double deltaThisTick = ((currentTimePoint - lastTimePoint).count() - nsAheadHolder) / NANO_DENOM_DOUBLE; deltaThisTick = std::min(deltaThisTick, pkeSettings.minimumDeltaPerFrame); - deltaTillNextRender -= deltaThisTick; - bool shouldRender = deltaTillNextRender < deltaThisTick; lastTimePoint = currentTimePoint; - if (shouldRender) { - if (deltaTillNextRender > 0.0 && deltaThisTick < pkeSettings.deltaPerFrame) { - /* - * We are ahead of schedule && the current tick is faster than our target FPS. - * Simulate the extra time we are ahead and prepare to sleep the difference - * before the next tick. - */ - nsAhead = std::ceil(deltaTillNextRender * NANO_DENOM_DOUBLE); - deltaThisTick += deltaTillNextRender; - } - deltaTillNextRender += pkeSettings.deltaPerFrame; + deltaTillNextRender -= deltaThisTick; + bool shouldRender = pkeSettings.graphicsSettings.isFramerateUnlocked || deltaTillNextRender <= 0.0; + + if (deltaTillNextRender > 0.0 && deltaTillNextRender - deltaThisTick <= 0.0) { + /* + * We are ahead of the render schedule + * && the current tick's speed would put us behind schedule next tick. + * Simulate the extra time we are ahead and prepare to sleep the difference + * before the next tick. + */ + nsAhead = std::ceil(deltaTillNextRender * NANO_DENOM_DOUBLE); + deltaThisTick += deltaTillNextRender; + shouldRender = true; } tickCount += 1; @@ -83,11 +85,22 @@ int main() { if (shouldRender) { Render(); + double msBehind = deltaTillNextRender * -1000; + int64_t behindCount = 0; + while (deltaTillNextRender < pkeSettings.deltaPerFrame) { + behindCount += 1; + deltaTillNextRender += pkeSettings.deltaPerFrame; + } + if (behindCount > 2) { + fprintf(stderr, "[PKE::main] late render - simulated ahead: %fms - delta behind: %fms - missed frames:%ld\n", nsAheadHolder / (NANO_DENOM_DOUBLE / 1000), msBehind, behindCount - 1); + fflush(stderr); + } } - if (shouldRender == false && (currentTimePoint - lastLogTimePoint).count() > std::chrono::nanoseconds::period::den) { + if ((currentTimePoint - lastLogTimePoint).count() > std::chrono::nanoseconds::period::den) { lastLogTimePoint = currentTimePoint; - printf("TPS: ~%ld - actual:%ld\n", int64_t(1 / deltaThisTick), tickCount); + fprintf(stdout, "TPS: ~%ld - actual:%ld\n", int64_t(1 / deltaThisTick), tickCount); + fflush(stdout); tickCount = 0; } @@ -97,13 +110,13 @@ int main() { vkDeviceWaitIdle(vkDevice); } catch (const std::exception &exc) { - printf("EXCEPTION: %s\n", exc.what()); + fprintf(stdout, "EXCEPTION: %s\n", exc.what()); } catch (const char *err) { - printf("UNHANDLED EXCEPTION: %s\n", err); + fprintf(stdout, "UNHANDLED EXCEPTION: %s\n", err); } catch (...) { - printf("UNHANDLED EXCEPTION\n"); + fprintf(stdout, "UNHANDLED EXCEPTION\n"); } - printf("PKE SHUTDOWN INITIATED\n"); + fprintf(stdout, "PKE SHUTDOWN INITIATED\n"); Game_Teardown(); Event_Teardown(); EntityType_Teardown(); @@ -112,6 +125,6 @@ int main() { AM_Teardown(); DestroyWindow(); Pke_DebugPrint(); - printf("PKE EXITING\n"); + fprintf(stdout, "PKE EXITING\n"); return 0; } diff --git a/src/window.cpp b/src/window.cpp index 2a1b905..6655c88 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -51,12 +51,11 @@ unsigned int transferFamilyIndex; bool shouldRecreateSwapchain = false; unsigned int CURRENT_FRAME = 0; unsigned int selectedSurfaceIndex = -1u; -unsigned int selectedPresentIndex = -1u; unsigned int swapchainLength = 0u; VkSwapchainKHR vkSwapchainKHR = VK_NULL_HANDLE; VkSurfaceFormatKHR vkSurfaceFormatKHR; VkFormat depthFormat; -VkPresentModeKHR vkPresentModeKHR; +VkPresentModeKHR vkPresentModeKHR = VK_PRESENT_MODE_FIFO_KHR; VkExtent2D extent; VkImage *swapchainImages = nullptr; VkImageView *swapchainImageViews = nullptr; @@ -604,22 +603,46 @@ void CreateSwapchain() { height = extent.height < surfaceCapabilities.minImageExtent.height ? surfaceCapabilities.minImageExtent.height : extent.height; extent.height = height > surfaceCapabilities.maxImageExtent.height ? surfaceCapabilities.maxImageExtent.height : height; - if (selectedPresentIndex == -1u) { + vkPresentModeKHR = VK_PRESENT_MODE_FIFO_KHR; + if (pkeSettings.graphicsSettings.isWaitingForVsync == false || pkeSettings.graphicsSettings.isFramerateUnlocked == true) { unsigned int presentModeCount = 0; vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vkSurfaceKHR, &presentModeCount, nullptr); VkPresentModeKHR *presentModes = Pke_New<VkPresentModeKHR>(presentModeCount); vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vkSurfaceKHR, &presentModeCount, presentModes); - unsigned long mailboxIndex = -1; - unsigned long fifoRelaxedIndex = -1; + uint32_t immediateIndex = -1; + uint32_t fifoRelaxedIndex = -1; + /* + uint32_t mailboxIndex = -1; + uint32_t fifoIndex = -1; + */ for (long i = 0; i < presentModeCount; ++i) { - if (presentModes[i] != VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR) { - mailboxIndex = i; - } else if (presentModes[i] != VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) { + if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR) { + immediateIndex = i; + } + else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) { fifoRelaxedIndex = i; } + /* + // TODO returns 5 swapchain images, which causes other unhandled issues + else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR) { + mailboxIndex = i; + } + else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR) { + fifoIndex = i; + } + */ + } + if (fifoRelaxedIndex != -1) { + vkPresentModeKHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } + /* + if (mailboxIndex != -1) { + vkPresentModeKHR = VK_PRESENT_MODE_MAILBOX_KHR; + } else + */ + if (immediateIndex != -1) { + vkPresentModeKHR = VK_PRESENT_MODE_IMMEDIATE_KHR; } - selectedPresentIndex = mailboxIndex != -1ul ? mailboxIndex : fifoRelaxedIndex; - vkPresentModeKHR = presentModes[selectedPresentIndex]; Pke_Delete<VkPresentModeKHR>(presentModes, presentModeCount); } @@ -654,7 +677,8 @@ void CreateSwapchain() { vkSwapchainCreateInfo.queueFamilyIndexCount = 0; } - vkCreateSwapchainKHR(vkDevice, &vkSwapchainCreateInfo, vkAllocator, &vkSwapchainKHR); + VkResult vkResult = vkCreateSwapchainKHR(vkDevice, &vkSwapchainCreateInfo, vkAllocator, &vkSwapchainKHR); + assert(vkResult == VK_SUCCESS); VkImageSubresourceRange vkImageSubresourceRange; vkImageSubresourceRange.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; @@ -686,13 +710,16 @@ void CreateSwapchain() { assert(depthImages == nullptr || depthImages == CAFE_BABE(VkImage)); assert(depthImageViews == nullptr || depthImageViews == CAFE_BABE(VkImageView)); - vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, nullptr); + vkResult = vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, nullptr); + assert(vkResult == VK_SUCCESS); swapchainImages = Pke_New<VkImage>(swapchainLength); - vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, swapchainImages); + vkResult = vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, swapchainImages); + assert(vkResult == VK_SUCCESS); swapchainImageViews = Pke_New<VkImageView>(swapchainLength); for (long i = 0; i < swapchainLength; ++i) { vkImageViewCreateInfo.image = swapchainImages[i]; - vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &swapchainImageViews[i]); + vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &swapchainImageViews[i]); + assert(vkResult == VK_SUCCESS); } // render target items diff --git a/src/window.hpp b/src/window.hpp index ab07a8b..e94598b 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -20,6 +20,7 @@ // TODO replace me with something more elegant const unsigned int MAX_FRAMES_IN_FLIGHT = 3; +extern bool shouldRecreateSwapchain; extern GLFWwindow *window; extern GLFWmonitor *monitor; extern GLFWvidmode vidMode; |
