From 5428ee5cf082eb6ccd20e1c679211e8065be2220 Mon Sep 17 00:00:00 2001 From: knokko Date: Mon, 21 Oct 2024 22:01:19 +0200 Subject: [PATCH] Improve error handling of WindowRenderLoop and WindowEventLoop --- .../window/SwapchainMaintenanceCleaner.java | 2 +- .../knokko/boiler/window/VkbWindow.java | 18 ++--- .../boiler/window/WindowRenderLoop.java | 68 +++++++++++-------- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/github/knokko/boiler/window/SwapchainMaintenanceCleaner.java b/src/main/java/com/github/knokko/boiler/window/SwapchainMaintenanceCleaner.java index fde288e..c3b3d87 100644 --- a/src/main/java/com/github/knokko/boiler/window/SwapchainMaintenanceCleaner.java +++ b/src/main/java/com/github/knokko/boiler/window/SwapchainMaintenanceCleaner.java @@ -42,6 +42,6 @@ public void beforePresent(MemoryStack stack, VkPresentInfoKHR presentInfo, Acqui @Override void waitUntilStateCanBeDestroyed(State state) { - for (var image : state.acquiredImages()) image.presentFence.awaitSignal(); + for (var image : state.acquiredImages()) image.presentFence.waitIfSubmitted(); } } diff --git a/src/main/java/com/github/knokko/boiler/window/VkbWindow.java b/src/main/java/com/github/knokko/boiler/window/VkbWindow.java index 89385b5..5edbe69 100644 --- a/src/main/java/com/github/knokko/boiler/window/VkbWindow.java +++ b/src/main/java/com/github/knokko/boiler/window/VkbWindow.java @@ -340,13 +340,15 @@ public void presentSwapchainImage(AcquiredImage image, AwaitableSubmission rende public synchronized void destroy() { if (hasBeenDestroyed) return; - cleaner.destroyEverything(); - vkDestroySurfaceKHR(instance.vkInstance(), vkSurface, null); - surfaceCapabilities.free(); - - if (windowLoop != null) windowLoop.destroy(this); - else glfwDestroyWindow(glfwWindow); - - hasBeenDestroyed = true; + try { + cleaner.destroyEverything(); + vkDestroySurfaceKHR(instance.vkInstance(), vkSurface, null); + surfaceCapabilities.free(); + } finally { + if (windowLoop != null) windowLoop.destroy(this); + else glfwDestroyWindow(glfwWindow); + + hasBeenDestroyed = true; + } } } diff --git a/src/main/java/com/github/knokko/boiler/window/WindowRenderLoop.java b/src/main/java/com/github/knokko/boiler/window/WindowRenderLoop.java index 8b55665..6117e7a 100644 --- a/src/main/java/com/github/knokko/boiler/window/WindowRenderLoop.java +++ b/src/main/java/com/github/knokko/boiler/window/WindowRenderLoop.java @@ -43,39 +43,45 @@ public WindowRenderLoop( private void run() { try (var stack = stackPush()) { setup(window.instance, stack); + } catch (Throwable setupFailed) { + window.destroy(); + throw setupFailed; } - long currentFrame = 0; - while (!glfwWindowShouldClose(window.glfwWindow)) { - if (window.windowLoop == null) glfwPollEvents(); - - int frameIndex = (int) (currentFrame % numFramesInFlight); - - try (var stack = stackPush()) { - AcquiredImage acquiredImage; - if (acquireSwapchainImageWithFence) acquiredImage = window.acquireSwapchainImageWithFence(presentMode); - else acquiredImage = window.acquireSwapchainImageWithSemaphore(presentMode); - if (acquiredImage == null) { - //noinspection BusyWait - sleep(100); - continue; + try { + long currentFrame = 0; + while (!glfwWindowShouldClose(window.glfwWindow)) { + if (window.windowLoop == null) glfwPollEvents(); + + int frameIndex = (int) (currentFrame % numFramesInFlight); + + try (var stack = stackPush()) { + AcquiredImage acquiredImage; + if (acquireSwapchainImageWithFence) + acquiredImage = window.acquireSwapchainImageWithFence(presentMode); + else acquiredImage = window.acquireSwapchainImageWithSemaphore(presentMode); + if (acquiredImage == null) { + //noinspection BusyWait + sleep(100); + continue; + } + + if (acquireSwapchainImageWithFence) acquiredImage.acquireFence.awaitSignal(); + + var renderSubmission = renderFrame(stack, frameIndex, acquiredImage, window.instance); + if (renderSubmission == null) throw new RuntimeException( + "Submission must not be null, make sure to submit a fence or timeline signal semaphore" + ); + window.presentSwapchainImage(acquiredImage, renderSubmission); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - - if (acquireSwapchainImageWithFence) acquiredImage.acquireFence.awaitSignal(); - - var renderSubmission = renderFrame(stack, frameIndex, acquiredImage, window.instance); - if (renderSubmission == null) throw new RuntimeException( - "Submission must not be null, make sure to submit a fence or timeline signal semaphore" - ); - window.presentSwapchainImage(acquiredImage, renderSubmission); - } catch (InterruptedException e) { - throw new RuntimeException(e); + currentFrame += 1; } - currentFrame += 1; + } finally { + cleanUp(window.instance); + window.destroy(); } - - cleanUp(window.instance); - window.destroy(); } /** @@ -91,7 +97,11 @@ public void start() { didStart = true; if (window.windowLoop == null) this.run(); - else new Thread(this::run).start(); + else { + var thread = new Thread(this::run); + thread.setDaemon(true); // Ensure that the render thread dies when the main thread dies (unexpectedly) + thread.start(); + } } /**