Added throttling outside of window focus and update Engine threads to extend a generic thread
This commit is contained in:
parent
2f626ba00f
commit
71d3cd400b
11 changed files with 325 additions and 155 deletions
|
|
@ -3,8 +3,10 @@ package net.halbear.Terrain4J.EngineCore.Display;
|
||||||
import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
|
import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
|
||||||
import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
|
import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
||||||
import org.lwjgl.glfw.GLFWImage;
|
import org.lwjgl.glfw.GLFWImage;
|
||||||
import org.lwjgl.glfw.GLFWVidMode;
|
import org.lwjgl.glfw.GLFWVidMode;
|
||||||
|
import org.lwjgl.glfw.GLFWWindowFocusCallback;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
|
|
@ -68,7 +70,19 @@ public class Window {
|
||||||
|
|
||||||
IconBuffer.free(); //free the buffer once icon is set so when the program closes there isn't memory still floating around
|
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");
|
Logger.debug("Freeing icon Buffer");
|
||||||
|
glfwSetWindowFocusCallback(handle, new GLFWWindowFocusCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(long window, boolean focused) {
|
||||||
|
if(EngineConfig.getInstance().IsEngineThrottledOnUnfocus()) {
|
||||||
|
if (focused) {
|
||||||
|
EngineConfig.getInstance().SetEngineThrottle(false);
|
||||||
|
} else {
|
||||||
|
EngineConfig.getInstance().SetEngineThrottle(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrimaryRuntime.UpdateFrameAccuracy();
|
||||||
|
}
|
||||||
|
});
|
||||||
glfwMakeContextCurrent(handle);
|
glfwMakeContextCurrent(handle);
|
||||||
if (EngineConfig.VSYNC) glfwSwapInterval(1);
|
if (EngineConfig.VSYNC) glfwSwapInterval(1);
|
||||||
else glfwSwapInterval(0);
|
else glfwSwapInterval(0);
|
||||||
|
|
|
||||||
|
|
@ -21,35 +21,29 @@ public class EngineConfig {
|
||||||
private int MainTickRate;
|
private int MainTickRate;
|
||||||
private int FastTickRate;
|
private int FastTickRate;
|
||||||
private boolean CapMainToTickRate;
|
private boolean CapMainToTickRate;
|
||||||
|
private boolean CapFastToTickRate;
|
||||||
|
private boolean CapPrimaryToTickRate;
|
||||||
private int Width;
|
private int Width;
|
||||||
private int Height;
|
private int Height;
|
||||||
public static int FrameRate_PRIMARYTHREAD =0;
|
public static int FrameRate_PRIMARYTHREAD =0;
|
||||||
public static int TPS =0;
|
public static int TPS =0;
|
||||||
public static int FrameRate_MAINENGINETHREAD =0;
|
public static int FrameRate_MAINENGINETHREAD =0;
|
||||||
|
public static int FrameRate_FASTENGINETHREAD =0;
|
||||||
public static int FrameRate_RENDERTHREAD =0;
|
public static int FrameRate_RENDERTHREAD =0;
|
||||||
public static int FrameRate_WINDOW =0;
|
public static int FrameRate_WINDOW =0;
|
||||||
public static int RENDERFRAMES =0;
|
public static int RENDERFRAMES =0;
|
||||||
public static boolean VSYNC = false;
|
public static boolean VSYNC = false;
|
||||||
public static boolean ShaderDebug = false;
|
public static boolean ShaderDebug = false;
|
||||||
public static boolean RecompileShaders = false;
|
public static boolean RecompileShaders = false;
|
||||||
|
private static long ThrottleAccuracy = 100000;
|
||||||
|
private static boolean ThrottleEngine = false;
|
||||||
|
private static boolean ThrottleEngineOnUnfocus = true;
|
||||||
private boolean vkValidated;
|
private boolean vkValidated;
|
||||||
private String PhysicalDeviceName;
|
private String PhysicalDeviceName;
|
||||||
private int RequestedImages;
|
private int RequestedImages;
|
||||||
private String IconPath = "/WindowResources/Icon/";
|
private String IconPath = "/WindowResources/Icon/";
|
||||||
private String IconName = "ProgramIcon.png";
|
private String IconName = "ProgramIcon.png";
|
||||||
|
|
||||||
public int GetRequestedImages(){
|
|
||||||
return RequestedImages;
|
|
||||||
}
|
|
||||||
public boolean GetVSYNC(){
|
|
||||||
return VSYNC;
|
|
||||||
}
|
|
||||||
public boolean DebugShaders(){
|
|
||||||
return ShaderDebug;
|
|
||||||
}
|
|
||||||
public boolean RecompileShaders(){
|
|
||||||
return RecompileShaders;
|
|
||||||
}
|
|
||||||
private EngineConfig() {
|
private EngineConfig() {
|
||||||
var EngineConfigVar = new Properties();
|
var EngineConfigVar = new Properties();
|
||||||
Path path = Paths.get("");
|
Path path = Paths.get("");
|
||||||
|
|
@ -90,12 +84,16 @@ public class EngineConfig {
|
||||||
if(SuccessfulLoad) {
|
if(SuccessfulLoad) {
|
||||||
IconName = (EngineConfigVar.getOrDefault("Software_Icon", "ProgramIcon.png").toString());
|
IconName = (EngineConfigVar.getOrDefault("Software_Icon", "ProgramIcon.png").toString());
|
||||||
IconPath = (EngineConfigVar.getOrDefault("Software_Icon_Path", "/WindowResources/Icon/").toString());
|
IconPath = (EngineConfigVar.getOrDefault("Software_Icon_Path", "/WindowResources/Icon/").toString());
|
||||||
CapMainToTickRate = Boolean.parseBoolean(EngineConfigVar.getOrDefault("cap_main_to_tickrate", "false").toString());
|
CapMainToTickRate = Boolean.parseBoolean(EngineConfigVar.getOrDefault("cap_main_to_tickrate", true).toString());
|
||||||
|
CapFastToTickRate = Boolean.parseBoolean(EngineConfigVar.getOrDefault("cap_fast_to_tickrate", true).toString());
|
||||||
|
CapPrimaryToTickRate = Boolean.parseBoolean(EngineConfigVar.getOrDefault("cap_master_to_tickrate", false).toString());
|
||||||
MainTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("main_thread_tickrate", "120").toString());
|
MainTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("main_thread_tickrate", "120").toString());
|
||||||
FastTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("fast_thread_tickrate", "240").toString());
|
FastTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("fast_thread_tickrate", "240").toString());
|
||||||
SOFTWARE_TITLE = EngineConfigVar.getOrDefault("Software_Title", "Terrain4J").toString();
|
SOFTWARE_TITLE = EngineConfigVar.getOrDefault("Software_Title", "Terrain4J").toString();
|
||||||
PhysicalDeviceName = EngineConfigVar.getOrDefault("PhysicalDeviceName", "").toString();
|
PhysicalDeviceName = EngineConfigVar.getOrDefault("PhysicalDeviceName", "").toString();
|
||||||
accuracy = Long.parseLong(EngineConfigVar.getOrDefault("frame_accuracy", DEFAULT_ACCURACY).toString());
|
accuracy = Long.parseLong(EngineConfigVar.getOrDefault("frame_accuracy", DEFAULT_ACCURACY).toString());
|
||||||
|
ThrottleAccuracy = Long.parseLong(EngineConfigVar.getOrDefault("throttle_accuracy", DEFAULT_ACCURACY).toString());
|
||||||
|
ThrottleEngineOnUnfocus = Boolean.parseBoolean(EngineConfigVar.getOrDefault("throttle_on_unfocus", true).toString());
|
||||||
TickRate = Integer.parseInt(EngineConfigVar.getOrDefault("master_tick_rate", DEFAULT_TICKRATE).toString());
|
TickRate = Integer.parseInt(EngineConfigVar.getOrDefault("master_tick_rate", DEFAULT_TICKRATE).toString());
|
||||||
Width = Integer.parseInt(EngineConfigVar.getOrDefault("display_width", "1280").toString());
|
Width = Integer.parseInt(EngineConfigVar.getOrDefault("display_width", "1280").toString());
|
||||||
Height = Integer.parseInt(EngineConfigVar.getOrDefault("display_height", "720").toString());
|
Height = Integer.parseInt(EngineConfigVar.getOrDefault("display_height", "720").toString());
|
||||||
|
|
@ -110,7 +108,9 @@ public class EngineConfig {
|
||||||
try {
|
try {
|
||||||
EngineConfigVar.setProperty("Software_Icon","ProgramIcon.png");
|
EngineConfigVar.setProperty("Software_Icon","ProgramIcon.png");
|
||||||
EngineConfigVar.setProperty("Software_Icon_Path","/WindowResources/Icon/");
|
EngineConfigVar.setProperty("Software_Icon_Path","/WindowResources/Icon/");
|
||||||
EngineConfigVar.setProperty("cap_main_to_tickrate","false");
|
EngineConfigVar.setProperty("cap_master_to_tickrate","false");
|
||||||
|
EngineConfigVar.setProperty("cap_main_to_tickrate","true");
|
||||||
|
EngineConfigVar.setProperty("cap_fast_to_tickrate","true");
|
||||||
EngineConfigVar.setProperty("main_thread_tickrate","120");
|
EngineConfigVar.setProperty("main_thread_tickrate","120");
|
||||||
EngineConfigVar.setProperty("fast_thread_tickrate","240");
|
EngineConfigVar.setProperty("fast_thread_tickrate","240");
|
||||||
EngineConfigVar.setProperty("Software_Title","Terrain4J Software");
|
EngineConfigVar.setProperty("Software_Title","Terrain4J Software");
|
||||||
|
|
@ -123,6 +123,8 @@ public class EngineConfig {
|
||||||
EngineConfigVar.setProperty("vkValidated","false");
|
EngineConfigVar.setProperty("vkValidated","false");
|
||||||
EngineConfigVar.setProperty("Debug_Shaders","false");
|
EngineConfigVar.setProperty("Debug_Shaders","false");
|
||||||
EngineConfigVar.setProperty("ShaderRecompiling","true");
|
EngineConfigVar.setProperty("ShaderRecompiling","true");
|
||||||
|
EngineConfigVar.setProperty("throttle_accuracy","100000");
|
||||||
|
EngineConfigVar.setProperty("throttle_on_unfocus","true");
|
||||||
EngineConfigVar.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file");
|
EngineConfigVar.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file");
|
||||||
Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath());
|
Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath());
|
||||||
} catch (IOException excp2) {
|
} catch (IOException excp2) {
|
||||||
|
|
@ -133,17 +135,33 @@ public class EngineConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean VkValidated(){
|
|
||||||
return vkValidated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized EngineConfig getInstance() {
|
public static synchronized EngineConfig getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {instance = new EngineConfig();}
|
||||||
|
|
||||||
instance = new EngineConfig();
|
|
||||||
}
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetEngineThrottle(boolean isThrottling){ThrottleEngine = isThrottling; }
|
||||||
|
public boolean IsEngineThrottled(){return ThrottleEngine;}
|
||||||
|
public boolean IsEngineThrottledOnUnfocus(){return ThrottleEngineOnUnfocus;}
|
||||||
|
public long GetThrottleAccuracy(){return ThrottleAccuracy;}
|
||||||
|
public int GetRequestedImages(){
|
||||||
|
return RequestedImages;
|
||||||
|
}
|
||||||
|
public boolean GetVSYNC(){
|
||||||
|
return VSYNC;
|
||||||
|
}
|
||||||
|
public boolean DebugShaders(){
|
||||||
|
return ShaderDebug;
|
||||||
|
}
|
||||||
|
public boolean RecompileShaders(){
|
||||||
|
return RecompileShaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean VkValidated(){
|
||||||
|
return vkValidated;
|
||||||
|
}
|
||||||
public int getWidth(){
|
public int getWidth(){
|
||||||
return Width;
|
return Width;
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +169,8 @@ public class EngineConfig {
|
||||||
return Height;
|
return Height;
|
||||||
}
|
}
|
||||||
public boolean GetMainTickCap(){return CapMainToTickRate;}
|
public boolean GetMainTickCap(){return CapMainToTickRate;}
|
||||||
|
public boolean GetFastTickCap(){return CapFastToTickRate;}
|
||||||
|
public boolean GetPrimaryTickCap(){return CapPrimaryToTickRate;}
|
||||||
public int GetMainTickrate(){return MainTickRate;}
|
public int GetMainTickrate(){return MainTickRate;}
|
||||||
public int GetFastTickrate(){return FastTickRate;}
|
public int GetFastTickrate(){return FastTickRate;}
|
||||||
public long getAccuracy() {
|
public long getAccuracy() {
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,5 @@ public interface GameLogic {
|
||||||
InitData Initialise(EngineInstance engineInstance);
|
InitData Initialise(EngineInstance engineInstance);
|
||||||
void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds);
|
void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds);
|
||||||
void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds);
|
void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds);
|
||||||
|
void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,18 @@ public class GameCore implements GameLogic {
|
||||||
@Override
|
@Override
|
||||||
public InitData Initialise(EngineInstance engineInstance) {
|
public InitData Initialise(EngineInstance engineInstance) {
|
||||||
var ModelID = "TriangleModel";
|
var ModelID = "TriangleModel";
|
||||||
MeshData meshData = new MeshData("triangle-mesh", new float[]{
|
|
||||||
-0.5f, -0.5f, 0.0f,
|
|
||||||
0.0f, 0.5f, 0.0f,
|
|
||||||
0.5f, -0.5f, 0.0f},
|
|
||||||
new int[]{0, 1, 2});
|
|
||||||
List<MeshData> MeshDataList = new ArrayList<>();
|
List<MeshData> MeshDataList = new ArrayList<>();
|
||||||
MeshDataList.add(meshData);
|
for(int i = 0; i < 5; i++){
|
||||||
|
float PosXOffset = -1 + (float)Math.random() * 2;
|
||||||
|
float PosYOffset = -1 + (float)Math.random() * 2;
|
||||||
|
MeshDataList.add(
|
||||||
|
new MeshData("triangle-mesh" + i, new float[]{
|
||||||
|
PosXOffset, PosYOffset, 0.00f,
|
||||||
|
PosXOffset + 0.05f,PosYOffset + 0.15f, 0.0f,
|
||||||
|
PosXOffset + 0.1f, PosYOffset, 0.0f},
|
||||||
|
new int[]{0, 1, 2})
|
||||||
|
);
|
||||||
|
}
|
||||||
ModelData modelData = new ModelData(ModelID, MeshDataList);
|
ModelData modelData = new ModelData(ModelID, MeshDataList);
|
||||||
List<ModelData> models = new ArrayList<>();
|
List<ModelData> models = new ArrayList<>();
|
||||||
models.add(modelData);
|
models.add(modelData);
|
||||||
|
|
@ -40,4 +45,9 @@ public class GameCore implements GameLogic {
|
||||||
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
|
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.Main;
|
||||||
|
|
||||||
import net.halbear.Terrain4J.EngineCore.Display.Window;
|
import net.halbear.Terrain4J.EngineCore.Display.Window;
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.*;
|
import net.halbear.Terrain4J.EngineCore.Logic.*;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread;
|
||||||
import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
|
import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
|
||||||
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
|
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
|
@ -12,36 +13,60 @@ public class PrimaryRuntime {
|
||||||
private double TickRate = 0;
|
private double TickRate = 0;
|
||||||
private static MainThread PrimaryThread;
|
private static MainThread PrimaryThread;
|
||||||
private static RenderThread DrawingThread;
|
private static RenderThread DrawingThread;
|
||||||
|
private static FastTickThread FastThread;
|
||||||
private static boolean running = true;
|
private static boolean running = true;
|
||||||
private static Window window;
|
private static Window window;
|
||||||
private static EngineInstance engineInstance;
|
private static EngineInstance engineInstance;
|
||||||
public static int ThreadsOpen = 0;
|
public static int ThreadsOpen = 0;
|
||||||
public static boolean CanClose = false;
|
public static boolean CanClose = false;
|
||||||
public static long ShutDownStart;
|
public static long ShutDownStart;
|
||||||
|
private static long FrameAccuracy;
|
||||||
|
private static long OriginalFrameAccuracy;
|
||||||
|
private static boolean CappedToTickRate = false;
|
||||||
|
|
||||||
public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
|
public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
|
||||||
window = new Window(windowTitle);
|
window = new Window(windowTitle);
|
||||||
InitData initData = appLogic.Initialise(engineInstance);
|
InitData initData = appLogic.Initialise(engineInstance);
|
||||||
engineInstance = new EngineInstance(window, new Scene(window));
|
engineInstance = new EngineInstance(window, new Scene(window));
|
||||||
PrimaryThread = new MainThread(engineInstance, appLogic);
|
PrimaryThread = new MainThread(engineInstance, appLogic);
|
||||||
DrawingThread = new RenderThread(window, engineInstance, initData);
|
FastThread = new FastTickThread(engineInstance, appLogic);
|
||||||
|
DrawingThread = new RenderThread(window, engineInstance, initData, appLogic);
|
||||||
Thread.currentThread().setName("Terrain4J Primary Runtime Thread");
|
Thread.currentThread().setName("Terrain4J Primary Runtime Thread");
|
||||||
}
|
}
|
||||||
|
public static void UpdateFrameAccuracy(){
|
||||||
public void UpdateTickRate(){
|
if(EngineConfig.getInstance().IsEngineThrottled()){
|
||||||
TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate();
|
Logger.debug("ThrottlingEngine");
|
||||||
|
FrameAccuracy = EngineConfig.getInstance().GetThrottleAccuracy();
|
||||||
|
} else{
|
||||||
|
Logger.debug("UnThrottlingEngine");
|
||||||
|
FrameAccuracy= OriginalFrameAccuracy;
|
||||||
|
}
|
||||||
|
PrimaryThread.UpdateFrameAccuracy();
|
||||||
|
DrawingThread.UpdateFrameAccuracy();
|
||||||
|
FastThread.UpdateFrameAccuracy();
|
||||||
}
|
}
|
||||||
|
public void UpdateTickRateThreshold(){
|
||||||
|
CappedToTickRate = EngineConfig.getInstance().GetPrimaryTickCap();
|
||||||
|
if (CappedToTickRate){
|
||||||
|
TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate();
|
||||||
|
} else{
|
||||||
|
TickRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void run(){
|
public void run(){
|
||||||
|
UpdateTickRateThreshold();
|
||||||
long InitialTime = System.nanoTime();
|
long InitialTime = System.nanoTime();
|
||||||
long updateTime = InitialTime;
|
long updateTime = InitialTime;
|
||||||
double FrameDiff =0;
|
double FrameDiff =0;
|
||||||
double TickDiff =0;
|
double TickDiff =0;
|
||||||
double SecondCounter =0;
|
double SecondCounter =0;
|
||||||
double cycleDiff = 0;
|
double cycleDiff = 0;
|
||||||
PrimaryThread.StartMainThread();
|
PrimaryThread.StartThread();
|
||||||
DrawingThread.StartRenderThread();
|
DrawingThread.StartThread();
|
||||||
TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate();
|
FastThread.StartThread();
|
||||||
long FrameAccuracy = EngineConfig.getInstance().getAccuracy();
|
FrameAccuracy = EngineConfig.getInstance().getAccuracy();
|
||||||
|
OriginalFrameAccuracy = FrameAccuracy;
|
||||||
Logger.debug("Primary Thread Started");
|
Logger.debug("Primary Thread Started");
|
||||||
while (!window.shouldClose() && running){
|
while (!window.shouldClose() && running){
|
||||||
long now = System.nanoTime();
|
long now = System.nanoTime();
|
||||||
|
|
@ -93,7 +118,7 @@ public class PrimaryRuntime {
|
||||||
if (ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > -1) {
|
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);
|
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) {
|
while ((ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > 0) && VulkanContext.VulkanLayersOpen > -1 && !CanClose) {
|
||||||
if (!DrawingThread.FetchRenderThread().isAlive() && !PrimaryThread.FetchMainThread().isAlive() && ThreadsOpen >0){
|
if (!DrawingThread.FetchThread().isAlive() && !PrimaryThread.FetchThread().isAlive() && ThreadsOpen >0){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package net.halbear.Terrain4J.EngineCore.Threads;
|
||||||
|
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
||||||
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
|
public class EngineThread implements Runnable{
|
||||||
|
public boolean CappedToTickRate;
|
||||||
|
public int TickRate;
|
||||||
|
public double TickThreshold = 0;
|
||||||
|
public static boolean running = true;
|
||||||
|
public final GameLogic gameLogic;
|
||||||
|
public int Frames = 0;
|
||||||
|
public int TickFrames = 0;
|
||||||
|
public final Thread EngineThread;
|
||||||
|
public long EngineAccuracy;
|
||||||
|
public long OriginalAccuracy;
|
||||||
|
public boolean Throttle;
|
||||||
|
public String ThreadName;
|
||||||
|
|
||||||
|
public void KillThread(){
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(){
|
||||||
|
gameLogic.cleanup();
|
||||||
|
PrimaryRuntime.ThreadsOpen--;
|
||||||
|
Logger.debug("Closing "+ThreadName+" Thread, Thread: [{}]",Thread.currentThread().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread FetchThread(){
|
||||||
|
return EngineThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartThread(){
|
||||||
|
EngineThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EngineThread(EngineInstance engineInstance, GameLogic appLogic, String ThreadName){
|
||||||
|
this.ThreadName = ThreadName;
|
||||||
|
this.gameLogic = appLogic;
|
||||||
|
Logger.debug("Starting {} Thread",ThreadName);
|
||||||
|
EngineThread = new Thread(this);
|
||||||
|
EngineThread.setName("Terrain4J "+ThreadName+" Engine Thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateFrameAccuracy(){
|
||||||
|
Throttle = EngineConfig.getInstance().IsEngineThrottled();
|
||||||
|
if(Throttle){
|
||||||
|
EngineAccuracy = EngineConfig.getInstance().GetThrottleAccuracy();
|
||||||
|
} else{
|
||||||
|
EngineAccuracy= OriginalAccuracy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickEvent(long nsTimeDiff){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void FrameEvent(long now, long InitialTime){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void CycleEvent(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void SecondEvent(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PrimaryRuntime.ThreadsOpen++;
|
||||||
|
long InitialTime = System.nanoTime();
|
||||||
|
long updateTime = InitialTime;
|
||||||
|
double[] FrameTimes = new double[]{0,0,0,0};
|
||||||
|
Logger.debug("{} Thread Started",ThreadName);
|
||||||
|
EngineAccuracy = EngineConfig.getInstance().getAccuracy();
|
||||||
|
OriginalAccuracy = EngineAccuracy;
|
||||||
|
while (running){
|
||||||
|
long now = System.nanoTime();
|
||||||
|
FrameTimes[0] = now - InitialTime;
|
||||||
|
FrameTimes[1] += FrameTimes[0];
|
||||||
|
FrameTimes[2] += FrameTimes[0];
|
||||||
|
FrameTimes[3] += FrameTimes[0];
|
||||||
|
if (FrameTimes[1] >= EngineAccuracy){
|
||||||
|
FrameEvent(now, InitialTime);
|
||||||
|
Frames++;
|
||||||
|
if (FrameTimes[2] >= TickThreshold) {
|
||||||
|
TickFrames++;
|
||||||
|
long nsTimeDiff = now - updateTime;
|
||||||
|
TickEvent(nsTimeDiff);
|
||||||
|
updateTime = now;
|
||||||
|
FrameTimes[2] = 0;
|
||||||
|
}
|
||||||
|
if (FrameTimes[3] >= 1000000000L){
|
||||||
|
FrameTimes[3] = 0;
|
||||||
|
SecondEvent();
|
||||||
|
Frames = 0;
|
||||||
|
TickFrames = 0;
|
||||||
|
}
|
||||||
|
FrameTimes[1] = 0;
|
||||||
|
}
|
||||||
|
if(Throttle) {
|
||||||
|
long endTime = System.nanoTime();
|
||||||
|
long LoopFrameDiff = endTime - now;
|
||||||
|
long sleepTime = ((EngineAccuracy - LoopFrameDiff) / 1000000);
|
||||||
|
|
||||||
|
if (sleepTime > 0) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleepTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Logger.error("Thread Sleep Exception [{}]", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InitialTime = now;
|
||||||
|
}
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,45 @@
|
||||||
package net.halbear.Terrain4J.EngineCore.Threads;
|
package net.halbear.Terrain4J.EngineCore.Threads;
|
||||||
|
|
||||||
public class FastTickThread {
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
||||||
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
|
public class FastTickThread extends EngineThread {
|
||||||
|
|
||||||
|
public FastTickThread(EngineInstance engineInstance, GameLogic appLogic){
|
||||||
|
super(engineInstance, appLogic, "Fast");
|
||||||
|
UpdateTickRateThreshold();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void TickEvent(long nsTimeDiff){
|
||||||
|
gameLogic.UpdateFastThread(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void FrameEvent(long now, long InitialTime){
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void CycleEvent(){
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void SecondEvent(){
|
||||||
|
EngineConfig.FrameRate_FASTENGINETHREAD = Frames;
|
||||||
|
Logger.info(ThreadName + " Thread FPS: " + EngineConfig.FrameRate_FASTENGINETHREAD + " TPS: " + TickFrames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateTickRateThreshold(){
|
||||||
|
CappedToTickRate = EngineConfig.getInstance().GetFastTickCap();
|
||||||
|
TickRate = EngineConfig.getInstance().GetFastTickrate();
|
||||||
|
if (CappedToTickRate){
|
||||||
|
TickThreshold = (double) 1000000000 / (double) TickRate;
|
||||||
|
} else{
|
||||||
|
TickThreshold = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,36 +9,24 @@ import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
||||||
import net.halbear.Terrain4J.EngineCore.Main.Scene;
|
import net.halbear.Terrain4J.EngineCore.Main.Scene;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
public class MainThread implements Runnable {
|
public class MainThread extends EngineThread {
|
||||||
private static boolean CappedToTickRate;
|
|
||||||
private static int TickRate;
|
|
||||||
private static double TickThreshold;
|
|
||||||
private static boolean running = true;
|
|
||||||
private final GameLogic gameLogic;
|
|
||||||
private int Frames = 0;
|
|
||||||
private int TickFrames = 0;
|
|
||||||
private final Thread mainThread;
|
|
||||||
|
|
||||||
public void KillThread(){
|
@Override
|
||||||
running = false;
|
public void TickEvent(long nsTimeDiff){
|
||||||
|
gameLogic.Update(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
|
||||||
}
|
}
|
||||||
public void cleanup(){
|
@Override
|
||||||
gameLogic.cleanup();
|
public void FrameEvent(long now, long InitialTime){
|
||||||
PrimaryRuntime.ThreadsOpen--;
|
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
|
||||||
Logger.debug("Closing Main Thread, Thread: [{}]",Thread.currentThread().toString());
|
|
||||||
}
|
}
|
||||||
public Thread FetchMainThread(){
|
@Override
|
||||||
return mainThread;
|
public void CycleEvent(){
|
||||||
|
|
||||||
}
|
}
|
||||||
public void StartMainThread(){
|
@Override
|
||||||
mainThread.start();
|
public void SecondEvent(){
|
||||||
}
|
EngineConfig.FrameRate_MAINENGINETHREAD = Frames;
|
||||||
public MainThread(EngineInstance engineInstance, GameLogic appLogic){
|
Logger.info(ThreadName + " Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + " TPS: " + TickFrames);
|
||||||
this.gameLogic = appLogic;
|
|
||||||
Logger.debug("Starting Main Thread");
|
|
||||||
UpdateTickRateThreshold();
|
|
||||||
mainThread = new Thread(this);
|
|
||||||
mainThread.setName("Terrain4J Main Engine Thread");
|
|
||||||
}
|
}
|
||||||
public void UpdateTickRateThreshold(){
|
public void UpdateTickRateThreshold(){
|
||||||
CappedToTickRate = EngineConfig.getInstance().GetMainTickCap();
|
CappedToTickRate = EngineConfig.getInstance().GetMainTickCap();
|
||||||
|
|
@ -49,44 +37,9 @@ public class MainThread implements Runnable {
|
||||||
TickThreshold = 0;
|
TickThreshold = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
public MainThread(EngineInstance engineInstance, GameLogic appLogic){
|
||||||
public void run() {
|
super(engineInstance, appLogic, "Main");
|
||||||
PrimaryRuntime.ThreadsOpen++;
|
UpdateTickRateThreshold();
|
||||||
long InitialTime = System.nanoTime();
|
|
||||||
long updateTime = InitialTime;
|
|
||||||
double FrameDiff =0;
|
|
||||||
double TickDiff =0;
|
|
||||||
double SecondCounter =0;
|
|
||||||
double cycleDiff = 0;
|
|
||||||
Logger.debug("Main Thread Started");
|
|
||||||
long EngineAccuracy = EngineConfig.getInstance().getAccuracy();
|
|
||||||
while (running){
|
|
||||||
long now = System.nanoTime();
|
|
||||||
cycleDiff = now - InitialTime;
|
|
||||||
FrameDiff += cycleDiff;
|
|
||||||
TickDiff += cycleDiff;
|
|
||||||
SecondCounter += cycleDiff;
|
|
||||||
if (FrameDiff >= EngineAccuracy){
|
|
||||||
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
|
|
||||||
Frames++;
|
|
||||||
if (TickDiff >= TickThreshold) {
|
|
||||||
TickFrames++;
|
|
||||||
long nsTimeDiff = now - updateTime;
|
|
||||||
gameLogic.Update(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
|
|
||||||
updateTime = now;
|
|
||||||
TickDiff = 0;
|
|
||||||
}
|
|
||||||
if (SecondCounter >= 1000000000L){
|
|
||||||
SecondCounter = 0;
|
|
||||||
EngineConfig.FrameRate_MAINENGINETHREAD = Frames;
|
|
||||||
Logger.info("Main Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + " TPS: " + TickFrames);
|
|
||||||
Frames = 0;
|
|
||||||
TickFrames = 0;
|
|
||||||
}
|
|
||||||
FrameDiff = 0;
|
|
||||||
}
|
|
||||||
InitialTime = now;
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,73 +2,44 @@ package net.halbear.Terrain4J.EngineCore.Threads;
|
||||||
|
|
||||||
import net.halbear.Terrain4J.EngineCore.Display.Render;
|
import net.halbear.Terrain4J.EngineCore.Display.Render;
|
||||||
import net.halbear.Terrain4J.EngineCore.Display.Window;
|
import net.halbear.Terrain4J.EngineCore.Display.Window;
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
import net.halbear.Terrain4J.EngineCore.Logic.*;
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
|
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.InitData;
|
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext;
|
|
||||||
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
public class RenderThread implements Runnable {
|
public class RenderThread extends EngineThread {
|
||||||
private static boolean running = true;
|
|
||||||
private int Frames = 0;
|
|
||||||
private final Thread renderThread;
|
|
||||||
private final Render render;
|
private final Render render;
|
||||||
private Window window;
|
private Window window;
|
||||||
|
|
||||||
public RenderThread(Window window, EngineInstance engineInstance, InitData initData) {
|
public RenderThread(Window window, EngineInstance engineInstance, InitData initData, GameLogic appLogic) {
|
||||||
//this.window = window;
|
//this.window = window;
|
||||||
render = new Render(engineInstance);
|
render = new Render(engineInstance);
|
||||||
|
super(engineInstance,appLogic,"Render");
|
||||||
render.Initialise(initData);
|
render.Initialise(initData);
|
||||||
renderThread = new Thread(this);
|
|
||||||
renderThread.setName("Terrain4J Vulkan Render Thread");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KillThread(){
|
@Override
|
||||||
running = false;
|
public void TickEvent(long nsTimeDiff){
|
||||||
|
|
||||||
}
|
}
|
||||||
public Thread FetchRenderThread(){
|
@Override
|
||||||
return renderThread;
|
public void FrameEvent(long now, long InitialTime){
|
||||||
|
render.render(PrimaryRuntime.GetEngineInstance());
|
||||||
}
|
}
|
||||||
public void StartRenderThread(){
|
@Override
|
||||||
renderThread.start();
|
public void CycleEvent(){
|
||||||
|
|
||||||
}
|
}
|
||||||
private void cleanup() {
|
@Override
|
||||||
|
public void SecondEvent(){
|
||||||
|
Logger.info("Render FPS: " + Frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
render.cleanup();
|
render.cleanup();
|
||||||
PrimaryRuntime.ThreadsOpen--;
|
PrimaryRuntime.ThreadsOpen--;
|
||||||
Logger.debug("Closing Render Thread, Thread: [{}]",Thread.currentThread().toString());
|
Logger.debug("Closing Render Thread, Thread: [{}]",Thread.currentThread().toString());
|
||||||
if (PrimaryRuntime.ThreadsOpen <= 0 && VulkanContext.VulkanLayersOpen < 0) PrimaryRuntime.CanClose = true;
|
if (PrimaryRuntime.ThreadsOpen <= 0 && VulkanContext.VulkanLayersOpen < 0) PrimaryRuntime.CanClose = true;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int TotalFrames = 0;
|
|
||||||
PrimaryRuntime.ThreadsOpen++;
|
|
||||||
long InitialTime = System.nanoTime();
|
|
||||||
double FrameDiff =0;
|
|
||||||
double SecondCounter =0;
|
|
||||||
double cycleDiff = 0;
|
|
||||||
long FrameAccuracy = EngineConfig.getInstance().getAccuracy();
|
|
||||||
Logger.debug("Render Thread Started");
|
|
||||||
while (running){
|
|
||||||
long now = System.nanoTime();
|
|
||||||
cycleDiff = now - InitialTime;
|
|
||||||
FrameDiff += cycleDiff;
|
|
||||||
SecondCounter += cycleDiff;
|
|
||||||
if (FrameDiff >= FrameAccuracy){
|
|
||||||
Frames++;
|
|
||||||
if (SecondCounter >= 1000000000L){
|
|
||||||
SecondCounter = 0;
|
|
||||||
//EngineConfig.FrameRate_RENDERTHREAD = Frames;
|
|
||||||
Logger.info("Render FPS: " + Frames);
|
|
||||||
Frames = 0;
|
|
||||||
}
|
|
||||||
render.render(PrimaryRuntime.GetEngineInstance());
|
|
||||||
TotalFrames++;
|
|
||||||
FrameDiff = 0;
|
|
||||||
}
|
|
||||||
InitialTime = now;
|
|
||||||
}
|
|
||||||
//PrimaryRuntime.CloseRuntime();
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering;
|
||||||
|
|
||||||
|
public class Image {
|
||||||
|
|
||||||
|
public static class ImageData{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,13 +8,17 @@ display_height=480
|
||||||
display_width=640
|
display_width=640
|
||||||
|
|
||||||
#Engine Core Settings
|
#Engine Core Settings
|
||||||
#the precision of frames, set this to 16000 and it will limit the whole engine to 64FPS
|
#the precision of frames, set this to 16000000 and it will limit the whole engine to 64FPS
|
||||||
frame_accuracy=0
|
frame_accuracy=0
|
||||||
|
throttle_on_unfocus=true
|
||||||
|
throttle_accuracy=500000000
|
||||||
#event tick rate for game process
|
#event tick rate for game process
|
||||||
master_tick_rate=120
|
master_tick_rate=120
|
||||||
main_thread_tickrate=120
|
main_thread_tickrate=120
|
||||||
fast_thread_tickrate=240
|
fast_thread_tickrate=240
|
||||||
cap_main_to_tickrate=false
|
cap_master_to_tickrate=false
|
||||||
|
cap_main_to_tickrate=true
|
||||||
|
cap_fast_to_tickrate=true
|
||||||
|
|
||||||
#Renderer Properties
|
#Renderer Properties
|
||||||
Debug_Shaders = false
|
Debug_Shaders = false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue