From afbc46bffb71b46c374bfbf8bdad819d0cfd02b3 Mon Sep 17 00:00:00 2001 From: Halbear Date: Fri, 23 Jan 2026 09:26:29 +0000 Subject: [PATCH] Thread shutdown is now more stable, extensive logging of engine startup and shut down, Icon to be displayed in the software, path must be in resources but can be configured in properties file --- .../java/net/halbear/Executable/Init.java | 3 +- .../EngineCore/Display/GLFWImageParser.java | 49 ++++++++++++++++++ .../Terrain4J/EngineCore/Display/Window.java | 21 ++++++++ .../terrain4JlogoFullBlocks.png | Bin 0 -> 3343 bytes .../terrain4JlogoNoBlocks.png | Bin 0 -> 2164 bytes .../terrain4JlogoNoBlocksCompressed.png | Bin 0 -> 2203 bytes .../EngineCore/Logic/EngineConfig.java | 12 +++++ .../EngineCore/Logic/VulkanContext.java | 3 ++ .../EngineCore/Main/PrimaryRuntime.java | 22 +++++--- .../EngineCore/Threads/MainThread.java | 5 +- .../EngineCore/Threads/RenderThread.java | 7 ++- .../GPUSynchronisation/Fence.java | 2 + .../GPUSynchronisation/Semaphore.java | 2 + .../Structure/DisplayToScreen/ImageView.java | 2 + .../resources/DefaultEngineConfig.properties | 4 +- .../WindowResources/Icon/ProgramIcon.png | Bin 0 -> 3343 bytes terrain4j.properties | 2 + 17 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoFullBlocks.png create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoNoBlocks.png create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoNoBlocksCompressed.png create mode 100644 src/main/resources/WindowResources/Icon/ProgramIcon.png diff --git a/src/main/java/net/halbear/Executable/Init.java b/src/main/java/net/halbear/Executable/Init.java index 5568a6c..51f8818 100644 --- a/src/main/java/net/halbear/Executable/Init.java +++ b/src/main/java/net/halbear/Executable/Init.java @@ -1,5 +1,6 @@ package net.halbear.Executable; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import org.tinylog.Logger; @@ -7,7 +8,7 @@ import org.tinylog.Logger; public class Init { public static void main(String[] args){ Logger.info("\nLaunching New Terrain4J Powered Software!"); - var GameEngine = new PrimaryRuntime("Terrain4J", new GameCore()); + var GameEngine = new PrimaryRuntime(EngineConfig.getInstance().GetSoftwareName(), new GameCore()); Logger.info("Launched Terrain4J Engine"); GameEngine.run(); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java new file mode 100644 index 0000000..44ba1bf --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java @@ -0,0 +1,49 @@ +package net.halbear.Terrain4J.EngineCore.Display; + +import org.lwjgl.system.MemoryStack; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import static org.lwjgl.stb.STBImage.stbi_load; + +public class GLFWImageParser { + + private ByteBuffer image; + private int width, height; + + GLFWImageParser(int width, int height, ByteBuffer image) { + this.image = image; + this.height = height; + this.width = width; + } + + public static GLFWImageParser LoadImage(String path) { + ByteBuffer image; + int width, height; + try (MemoryStack stack = MemoryStack.stackPush()) { + IntBuffer comp = stack.mallocInt(1); + IntBuffer w = stack.mallocInt(1); + IntBuffer h = stack.mallocInt(1); + image = stbi_load(path, w, h, comp, 4); + if (image == null) { + System.out.println("Could not load or find image inputted."); + } + width = w.get(); + height = h.get(); + } + return new GLFWImageParser(width, height, image); + } + + public ByteBuffer GetImage() { + return image; + } + + public int GetWidth() { + return width; + } + + public int GetHeight() { + return height; + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java index 3522d51..643fab6 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java @@ -3,10 +3,13 @@ package net.halbear.Terrain4J.EngineCore.Display; import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; import net.halbear.Terrain4J.EngineCore.Input.MouseListener; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import org.lwjgl.glfw.GLFWImage; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.system.MemoryUtil; import org.tinylog.Logger; +import java.io.File; + import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported; @@ -48,6 +51,24 @@ public class Window { height = h; }); + File IconLocation = new File("src/main/resources" + EngineConfig.getInstance().FetchIcon()); + GLFWImage Icon = GLFWImage.malloc(); + GLFWImage.Buffer IconBuffer = GLFWImage.malloc(1); + String IconPath = "src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoFullBlocks.png"; + if (IconLocation.exists()){ + IconPath =IconLocation.getPath(); + Logger.debug("Loading Icon From Location [{}]",IconPath); + } else Logger.warn("Icon specified in config at Location [{}] does not exist, resorting to Engine Icon", IconLocation.getPath()); + Icon.set(GLFWImageParser.LoadImage(IconPath).GetWidth(), + GLFWImageParser.LoadImage(IconPath).GetHeight(), + GLFWImageParser.LoadImage(IconPath).GetImage()); + IconBuffer.put(0,Icon); + + glfwSetWindowIcon(handle, IconBuffer); + + IconBuffer.free(); //free the buffer once icon is set so when the program closes there isn't memory still floating around + Logger.debug("Freeing icon Buffer"); + glfwMakeContextCurrent(handle); if (EngineConfig.VSYNC) glfwSwapInterval(1); else glfwSwapInterval(0); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoFullBlocks.png b/src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoFullBlocks.png new file mode 100644 index 0000000000000000000000000000000000000000..264b793ca4a9d4b5f7a52aa8c0e8a9481d1a49cd GIT binary patch literal 3343 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 Czn$U$ literal 0 HcmV?d00001 diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoNoBlocks.png b/src/main/java/net/halbear/Terrain4J/EngineCore/EngineSpecificAssets/terrain4JlogoNoBlocks.png new file mode 100644 index 0000000000000000000000000000000000000000..847a4909dd033d1008852e7450be86113228e25b GIT binary patch literal 2164 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 literal 0 HcmV?d00001 diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java index b2afd57..b3afaa1 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -33,6 +33,8 @@ public class EngineConfig { private boolean vkValidated; private String PhysicalDeviceName; private int RequestedImages; + private String IconPath = "/WindowResources/Icon/"; + private String IconName = "ProgramIcon.png"; public int GetRequestedImages(){ return RequestedImages; @@ -79,6 +81,8 @@ public class EngineConfig { } } if(SuccessfulLoad) { + IconName = (EngineConfigVar.getOrDefault("Software_Icon", "ProgramIcon.png").toString()); + IconPath = (EngineConfigVar.getOrDefault("Software_Icon_Path", "/WindowResources/Icon/").toString()); CapMainToTickRate = Boolean.parseBoolean(EngineConfigVar.getOrDefault("cap_main_to_tickrate", "false").toString()); MainTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("main_thread_tickrate", "120").toString()); FastTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("fast_thread_tickrate", "240").toString()); @@ -95,6 +99,8 @@ public class EngineConfig { } else if(!ConfigFile.exists()){ try { + EngineConfigVar.setProperty("Software_Icon","ProgramIcon.png"); + EngineConfigVar.setProperty("Software_Icon_Path","/WindowResources/Icon/"); EngineConfigVar.setProperty("cap_main_to_tickrate","false"); EngineConfigVar.setProperty("main_thread_tickrate","120"); EngineConfigVar.setProperty("fast_thread_tickrate","240"); @@ -145,4 +151,10 @@ public class EngineConfig { public String GetPhysicalDeviceName(){ return PhysicalDeviceName; } + public String GetSoftwareName(){ + return SOFTWARE_TITLE; + } + public String FetchIcon(){ + return IconPath + IconName; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java index ce7124f..973c7b4 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/VulkanContext.java @@ -6,6 +6,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDe import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; +import org.tinylog.Logger; public class VulkanContext { public static int VulkanLayersOpen = 0; @@ -31,6 +32,8 @@ public class VulkanContext { device.cleanup(); PhysDevice.cleanup(); Instance.cleanup(); + Logger.debug("Render Thread Finished ending Vulkan Processes\nVulkan Layers Open:[{}]", VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen); + VulkanLayersOpen--; } public Device GetDevice(){ return device; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java index 7a6b345..e796e40 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -19,12 +19,15 @@ public class PrimaryRuntime { private static Window window; private static EngineInstance engineInstance; public static int ThreadsOpen = 0; + public static boolean CanClose = false; + public static long ShutDownStart; public PrimaryRuntime(String windowTitle, GameLogic appLogic) { window = new Window(windowTitle); engineInstance = new EngineInstance(window, new Scene(window)); PrimaryThread = new MainThread(engineInstance, appLogic); DrawingThread = new RenderThread(window, engineInstance); + Thread.currentThread().setName("Terrain4J Primary Runtime Thread"); } public void UpdateTickRate(){ @@ -42,7 +45,7 @@ public class PrimaryRuntime { TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate(); long FrameAccuracy = EngineConfig.getInstance().getAccuracy(); Logger.debug("Primary Thread Started"); - while (!window.shouldClose()){ + while (!window.shouldClose() && running){ long now = System.nanoTime(); cycleDiff = now - InitialTime; FrameDiff += cycleDiff; @@ -71,14 +74,11 @@ public class PrimaryRuntime { } InitialTime = now; } + ShutDownStart = System.nanoTime(); + Logger.debug("Closing Software of name [{}]",EngineConfig.getInstance().GetSoftwareName()); PrimaryThread.KillThread(); DrawingThread.KillThread(); cleanup(); - Logger.debug("Waiting to close Primary Thread, making sure vulkan has shut down properly first and Engine Threads are closed\nThreads Open:[{}]\nVulkan Layers Open:[{}]",ThreadsOpen, VulkanContext.VulkanLayersOpen); - while(ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > 0){ - - } - Logger.debug("Closing Primary Thread"); } @@ -91,5 +91,15 @@ public class PrimaryRuntime { private void cleanup() { engineInstance.cleanup(); window.cleanup(); + Logger.debug("Process still running: [{}]",Thread.getAllStackTraces().keySet().toString()); + if (ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > -1) { + Logger.debug("Waiting to close Primary Thread, making sure vulkan has shut down properly first and Engine Threads are closed\nThreads Open:[{}]\nVulkan Layers Open:[{}]", ThreadsOpen, VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen); + while ((ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > 0) && VulkanContext.VulkanLayersOpen > -1 && !CanClose) { + + } + } + Logger.debug("Closing Primary Thread, Thread: [{}]",Thread.currentThread().toString()); + double ShutDownTime = Math.floor(((double)(System.nanoTime() - ShutDownStart)/1000000.0)*1000.0)/1000.0; + Logger.info("Successful stable Shut Down of Terrain4J in [{}] MilliSeconds", ShutDownTime); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java index 1c32894..90346b7 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java @@ -23,7 +23,8 @@ public class MainThread implements Runnable { } public void cleanup(){ gameLogic.cleanup(); - Logger.debug("Closing Main Thread"); + PrimaryRuntime.ThreadsOpen--; + Logger.debug("Closing Main Thread, Thread: [{}]",Thread.currentThread().toString()); } public Thread FetchMainThread(){ return mainThread; @@ -37,6 +38,7 @@ public class MainThread implements Runnable { Logger.debug("Starting Main Thread"); UpdateTickRateThreshold(); mainThread = new Thread(this); + mainThread.setName("Terrain4J Main Engine Thread"); } public void UpdateTickRateThreshold(){ CappedToTickRate = EngineConfig.getInstance().GetMainTickCap(); @@ -86,6 +88,5 @@ public class MainThread implements Runnable { InitialTime = now; } cleanup(); - PrimaryRuntime.ThreadsOpen--; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java index 0ff7a28..399a277 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Display.Render; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import org.tinylog.Logger; @@ -18,6 +19,7 @@ public class RenderThread implements Runnable { //this.window = window; render = new Render(engineInstance); renderThread = new Thread(this); + renderThread.setName("Terrain4J Vulkan Render Thread"); } public void KillThread(){ @@ -31,7 +33,9 @@ public class RenderThread implements Runnable { } private void cleanup() { render.cleanup(); - Logger.debug("Closing Render Thread"); + PrimaryRuntime.ThreadsOpen--; + Logger.debug("Closing Render Thread, Thread: [{}]",Thread.currentThread().toString()); + if (PrimaryRuntime.ThreadsOpen <= 0 && VulkanContext.VulkanLayersOpen < 0) PrimaryRuntime.CanClose = true; } @Override public void run() { @@ -62,6 +66,5 @@ public class RenderThread implements Runnable { } //PrimaryRuntime.CloseRuntime(); cleanup(); - PrimaryRuntime.ThreadsOpen--; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java index 372e411..51b2259 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Fence.java @@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchr import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkFenceCreateInfo; +import org.tinylog.Logger; import java.nio.LongBuffer; @@ -27,6 +28,7 @@ public class Fence { } public void cleanup(VulkanContext vulkanContext){ + Logger.debug("Destroying Vulkan Fence"); vkDestroyFence(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanFence, null); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java index 49cbc39..2039eb2 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/Semaphore.java @@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchr import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkSemaphoreCreateInfo; +import org.tinylog.Logger; import java.nio.LongBuffer; @@ -22,6 +23,7 @@ public class Semaphore { } public void cleanup(VulkanContext vulkanContext){ + Logger.debug("Destroying Vulkan Semaphore"); vkDestroySemaphore(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanSemaphore, null); } public long GetSemaphore(){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java index 611d0b9..3cc9e78 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/ImageView.java @@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkImageViewCreateInfo; +import org.tinylog.Logger; import java.nio.LongBuffer; @@ -39,6 +40,7 @@ public class ImageView { } public void cleanup(Device device){ + Logger.debug("Destroying Image View"); vkDestroyImageView(device.FetchVulkanDevice(), VulkanImageView, null); } diff --git a/src/main/resources/DefaultEngineConfig.properties b/src/main/resources/DefaultEngineConfig.properties index c3dae9c..d0c23ea 100644 --- a/src/main/resources/DefaultEngineConfig.properties +++ b/src/main/resources/DefaultEngineConfig.properties @@ -15,4 +15,6 @@ vsync=true #This is the name of the GPU you want the engine to use PhysicalDeviceName= #Title that shows up on app window -Software_Title=Terrain4J Game Engine \ No newline at end of file +Software_Title=Terrain4J Game Engine +Software_Icon=ProgramIcon.png +Software_Icon_Path=/WindowResources/Icon/ \ No newline at end of file diff --git a/src/main/resources/WindowResources/Icon/ProgramIcon.png b/src/main/resources/WindowResources/Icon/ProgramIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..264b793ca4a9d4b5f7a52aa8c0e8a9481d1a49cd GIT binary patch literal 3343 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 Czn$U$ literal 0 HcmV?d00001 diff --git a/terrain4j.properties b/terrain4j.properties index f95993b..3928f01 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -17,4 +17,6 @@ RequestedImages=3 PhysicalDeviceName= #Title that shows up on app window Software_Title=Terrain4J Game Engine +Software_Icon=ProgramIcon.png +Software_Icon_Path=/WindowResources/Icon/