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
This commit is contained in:
parent
14282e0b5d
commit
ed67934548
17 changed files with 122 additions and 12 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 GLFW_Width, GLFW_Height;
|
||||
|
||||
GLFWImageParser(int width, int height, ByteBuffer image) {
|
||||
this.image = image;
|
||||
this.GLFW_Height = height;
|
||||
this.GLFW_Width = width;
|
||||
}
|
||||
|
||||
public static GLFWImageParser LoadImage(String path) {
|
||||
ByteBuffer image;
|
||||
int Width, Height;
|
||||
try (MemoryStack MemStack = MemoryStack.stackPush()) {
|
||||
IntBuffer comp = MemStack.mallocInt(1);
|
||||
IntBuffer width = MemStack.mallocInt(1);
|
||||
IntBuffer height = MemStack.mallocInt(1);
|
||||
image = stbi_load(path, width, height, comp, 4);
|
||||
if (image == null) {
|
||||
System.out.println("Could not load or find image inputted.");
|
||||
}
|
||||
Width = width.get();
|
||||
Height = height.get();
|
||||
}
|
||||
return new GLFWImageParser(Width, Height, image);
|
||||
}
|
||||
|
||||
public ByteBuffer GetImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public int GetWidth() {
|
||||
return GLFW_Width;
|
||||
}
|
||||
|
||||
public int GetHeight() {
|
||||
return GLFW_Height;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Software_Title=Terrain4J Game Engine
|
||||
Software_Icon=ProgramIcon.png
|
||||
Software_Icon_Path=/WindowResources/Icon/
|
||||
BIN
src/main/resources/WindowResources/Icon/ProgramIcon.png
Normal file
BIN
src/main/resources/WindowResources/Icon/ProgramIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Loading…
Add table
Add a link
Reference in a new issue