From 0f73e8f83b89eb7eaed973dd8559511e1f9ccb93 Mon Sep 17 00:00:00 2001 From: Kyle Pelham Date: Sun, 15 Sep 2024 01:42:22 +0100 Subject: [PATCH] implement resizing + added delta time --- include/prism/window.h | 16 +++++++++---- src/prism.cpp | 9 ++++---- src/window.cpp | 51 +++++++++++++++++++++++++++++++++++------- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/include/prism/window.h b/include/prism/window.h index 9769b08..366e613 100644 --- a/include/prism/window.h +++ b/include/prism/window.h @@ -73,8 +73,6 @@ class PRISM_EXPORT Window private: GLFWwindow* windowHandle = nullptr; ///< Handle to the GLFW window. (NOT NATIVE HANDLE) - float lastFrameTime = 0.0f; ///< Time of the last frame. - float deltaTime = 0.0f; ///< Delta between frame end and start. public: /// Construct a new Window object. @@ -177,6 +175,16 @@ class PRISM_EXPORT Window */ void setDefaultTheme(); + // rebuildSwapchain + /** + * Rebuilds the swapchain for the window. + * + * This method is called when the swapchain needs to be rebuilt due to a window resize or other event. + * It will recreate the swapchain and associated resources. + * @note This method is called automatically inside the render() method. + */ + void rebuildSwapchain(); + /** * Renders ImGui's content to command buffers. * @param drawData The ImGui draw data to render. @@ -304,14 +312,14 @@ class PRISM_EXPORT Window * Override this method to implement custom update logic before rendering. * @note The ImGui context will be CORRECT during this callback. */ - virtual void onUpdate() {} + virtual void onUpdate(float deltaTime) {} /** * Called when the window is rendering. * Override this method to implement custom rendering logic. * @note The ImGui context will be CORRECT during this callback. */ - virtual void onRender() {} + virtual void onRender(float deltaTime) {} }; } // namespace Prism \ No newline at end of file diff --git a/src/prism.cpp b/src/prism.cpp index 346cc3f..5afe26b 100644 --- a/src/prism.cpp +++ b/src/prism.cpp @@ -27,9 +27,10 @@ Application::Application(std::string name) Application::~Application() { - stop(); // Stop the application - appWindows.clear(); // Destroy the windows - renderer.reset(); // Destroy the renderer + stop(); + for (auto& window : std::ranges::reverse_view(appWindows)) + window.reset(); + renderer.reset(); } void Application::run() @@ -62,7 +63,7 @@ void Application::cullClosedWindowsExitOnMainDeath() } // Remove the window - appWindows.erase(appWindows.begin() + i); + appWindows.erase(appWindows.begin() + (int64_t)i); } } } diff --git a/src/window.cpp b/src/window.cpp index 17bc50a..4526d09 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -159,7 +159,6 @@ Window::Window(WindowSettings settings) : ImGui_ImplVulkan_CreateFontsTexture(); // Restore the previous contexts - // TODO: Is this really doing what I'm expecting? I'll have to come back to this. if (backupImGuiContext) ImGui::SetCurrentContext(backupImGuiContext); } @@ -203,17 +202,22 @@ void Window::render() // Swap contexts ImGuiContext* backupContext = ImGui::GetCurrentContext(); ImGui::SetCurrentContext(imguiContext); - - // TODO: Resize swap chain + + // Update the swapchain if needed + if (swapchainNeedRebuild) + rebuildSwapchain(); // Start ImGui Frame ImGui_ImplVulkan_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); + // Get delta time from imgui + ImGuiIO& io = ImGui::GetIO(); + // Run update logic, then render ImGui - onUpdate(); - onRender(); + onUpdate(io.DeltaTime); + onRender(io.DeltaTime); // Render ImGui::Render(); @@ -232,8 +236,6 @@ void Window::render() else std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // TODO: Do delta time here - // Restore the previous context if (backupContext) ImGui::SetCurrentContext(backupContext); } @@ -395,6 +397,39 @@ void Window::installGlfwCallbacks() glfwSetMonitorCallback(MonitorCallback); } +void Window::rebuildSwapchain() +{ + // Get the new window size + int width, height; + glfwGetFramebufferSize(windowHandle, &width, &height); + + // If valid size, rebuild the swapchain + if (width > 0 && height > 0) { + // Wait for the device to be idle + auto renderer = Application::Get().getRenderer(); + vkDeviceWaitIdle(renderer->getDevice()); + + // Rebuild the swapchain + ImGui_ImplVulkan_SetMinImageCount(minImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow( + renderer->getInstance(), + renderer->getPhysicalDevice(), + renderer->getDevice(), + imguiWindow, + renderer->getQueueFamilyIndex(), + renderer->getAllocator(), + width, height, minImageCount + ); + + // Reallocate the command buffers + allocatedCommandBuffers.clear(); + allocatedCommandBuffers.resize(imguiWindow->ImageCount); + + // Reset the swapchain flag + swapchainNeedRebuild = false; + } +} + void Window::frameRender(ImDrawData* drawData) { VkResult err; @@ -430,7 +465,7 @@ void Window::frameRender(ImDrawData* drawData) auto& cmdBuf = allocatedCommandBuffers[imguiWindow->FrameIndex]; if (!cmdBuf.empty()) { - vkFreeCommandBuffers(renderer->getDevice(), fd->CommandPool, static_cast(cmdBuf.size()), cmdBuf.data()); + vkFreeCommandBuffers(renderer->getDevice(), fd->CommandPool, (uint32_t)cmdBuf.size(), cmdBuf.data()); cmdBuf.clear(); }