Added throttling outside of window focus and update Engine threads to extend a generic thread

This commit is contained in:
Halbear 2026-05-16 18:03:20 +01:00
parent 2f626ba00f
commit 71d3cd400b
11 changed files with 325 additions and 155 deletions

View file

@ -3,8 +3,10 @@ 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 net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowFocusCallback;
import org.lwjgl.system.MemoryUtil;
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
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);
if (EngineConfig.VSYNC) glfwSwapInterval(1);
else glfwSwapInterval(0);

View file

@ -21,35 +21,29 @@ public class EngineConfig {
private int MainTickRate;
private int FastTickRate;
private boolean CapMainToTickRate;
private boolean CapFastToTickRate;
private boolean CapPrimaryToTickRate;
private int Width;
private int Height;
public static int FrameRate_PRIMARYTHREAD =0;
public static int TPS =0;
public static int FrameRate_MAINENGINETHREAD =0;
public static int FrameRate_FASTENGINETHREAD =0;
public static int FrameRate_RENDERTHREAD =0;
public static int FrameRate_WINDOW =0;
public static int RENDERFRAMES =0;
public static boolean VSYNC = false;
public static boolean ShaderDebug = 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 String PhysicalDeviceName;
private int RequestedImages;
private String IconPath = "/WindowResources/Icon/";
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() {
var EngineConfigVar = new Properties();
Path path = Paths.get("");
@ -90,12 +84,16 @@ 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());
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());
FastTickRate = Integer.parseInt(EngineConfigVar.getOrDefault("fast_thread_tickrate", "240").toString());
SOFTWARE_TITLE = EngineConfigVar.getOrDefault("Software_Title", "Terrain4J").toString();
PhysicalDeviceName = EngineConfigVar.getOrDefault("PhysicalDeviceName", "").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());
Width = Integer.parseInt(EngineConfigVar.getOrDefault("display_width", "1280").toString());
Height = Integer.parseInt(EngineConfigVar.getOrDefault("display_height", "720").toString());
@ -110,7 +108,9 @@ public class EngineConfig {
try {
EngineConfigVar.setProperty("Software_Icon","ProgramIcon.png");
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("fast_thread_tickrate","240");
EngineConfigVar.setProperty("Software_Title","Terrain4J Software");
@ -123,6 +123,8 @@ public class EngineConfig {
EngineConfigVar.setProperty("vkValidated","false");
EngineConfigVar.setProperty("Debug_Shaders","false");
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");
Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath());
} catch (IOException excp2) {
@ -133,17 +135,33 @@ public class EngineConfig {
}
}
public boolean VkValidated(){
return vkValidated;
}
public static synchronized EngineConfig getInstance() {
if (instance == null) {
instance = new EngineConfig();
}
if (instance == null) {instance = new EngineConfig();}
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(){
return Width;
}
@ -151,6 +169,8 @@ public class EngineConfig {
return Height;
}
public boolean GetMainTickCap(){return CapMainToTickRate;}
public boolean GetFastTickCap(){return CapFastToTickRate;}
public boolean GetPrimaryTickCap(){return CapPrimaryToTickRate;}
public int GetMainTickrate(){return MainTickRate;}
public int GetFastTickrate(){return FastTickRate;}
public long getAccuracy() {

View file

@ -5,4 +5,5 @@ public interface GameLogic {
InitData Initialise(EngineInstance engineInstance);
void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds);
void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds);
void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds);
}

View file

@ -18,13 +18,18 @@ public class GameCore implements GameLogic {
@Override
public InitData Initialise(EngineInstance engineInstance) {
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<>();
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);
List<ModelData> models = new ArrayList<>();
models.add(modelData);
@ -38,6 +43,11 @@ public class GameCore implements GameLogic {
@Override
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
}
@Override
public void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
}
}

View file

@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.Main;
import net.halbear.Terrain4J.EngineCore.Display.Window;
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.RenderThread;
import org.tinylog.Logger;
@ -12,36 +13,60 @@ public class PrimaryRuntime {
private double TickRate = 0;
private static MainThread PrimaryThread;
private static RenderThread DrawingThread;
private static FastTickThread FastThread;
private static boolean running = true;
private static Window window;
private static EngineInstance engineInstance;
public static int ThreadsOpen = 0;
public static boolean CanClose = false;
public static long ShutDownStart;
private static long FrameAccuracy;
private static long OriginalFrameAccuracy;
private static boolean CappedToTickRate = false;
public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
window = new Window(windowTitle);
InitData initData = appLogic.Initialise(engineInstance);
engineInstance = new EngineInstance(window, new Scene(window));
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");
}
public void UpdateTickRate(){
TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate();
public static void UpdateFrameAccuracy(){
if(EngineConfig.getInstance().IsEngineThrottled()){
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(){
UpdateTickRateThreshold();
long InitialTime = System.nanoTime();
long updateTime = InitialTime;
double FrameDiff =0;
double TickDiff =0;
double SecondCounter =0;
double cycleDiff = 0;
PrimaryThread.StartMainThread();
DrawingThread.StartRenderThread();
TickRate = (double) 1000000000 / (double) EngineConfig.getInstance().getTickRate();
long FrameAccuracy = EngineConfig.getInstance().getAccuracy();
PrimaryThread.StartThread();
DrawingThread.StartThread();
FastThread.StartThread();
FrameAccuracy = EngineConfig.getInstance().getAccuracy();
OriginalFrameAccuracy = FrameAccuracy;
Logger.debug("Primary Thread Started");
while (!window.shouldClose() && running){
long now = System.nanoTime();
@ -93,7 +118,7 @@ public class PrimaryRuntime {
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) {
if (!DrawingThread.FetchRenderThread().isAlive() && !PrimaryThread.FetchMainThread().isAlive() && ThreadsOpen >0){
if (!DrawingThread.FetchThread().isAlive() && !PrimaryThread.FetchThread().isAlive() && ThreadsOpen >0){
break;
}
}

View file

@ -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();
}
}

View file

@ -1,4 +1,45 @@
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;
}
}
}

View file

@ -9,36 +9,24 @@ import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.tinylog.Logger;
public class MainThread implements Runnable {
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 class MainThread extends EngineThread {
public void KillThread(){
running = false;
@Override
public void TickEvent(long nsTimeDiff){
gameLogic.Update(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
}
public void cleanup(){
gameLogic.cleanup();
PrimaryRuntime.ThreadsOpen--;
Logger.debug("Closing Main Thread, Thread: [{}]",Thread.currentThread().toString());
@Override
public void FrameEvent(long now, long InitialTime){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
}
public Thread FetchMainThread(){
return mainThread;
@Override
public void CycleEvent(){
}
public void StartMainThread(){
mainThread.start();
}
public MainThread(EngineInstance engineInstance, GameLogic appLogic){
this.gameLogic = appLogic;
Logger.debug("Starting Main Thread");
UpdateTickRateThreshold();
mainThread = new Thread(this);
mainThread.setName("Terrain4J Main Engine Thread");
@Override
public void SecondEvent(){
EngineConfig.FrameRate_MAINENGINETHREAD = Frames;
Logger.info(ThreadName + " Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + " TPS: " + TickFrames);
}
public void UpdateTickRateThreshold(){
CappedToTickRate = EngineConfig.getInstance().GetMainTickCap();
@ -49,44 +37,9 @@ public class MainThread implements Runnable {
TickThreshold = 0;
}
}
@Override
public void run() {
PrimaryRuntime.ThreadsOpen++;
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();
public MainThread(EngineInstance engineInstance, GameLogic appLogic){
super(engineInstance, appLogic, "Main");
UpdateTickRateThreshold();
}
}

View file

@ -2,73 +2,44 @@ package net.halbear.Terrain4J.EngineCore.Threads;
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.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Logic.*;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import org.tinylog.Logger;
public class RenderThread implements Runnable {
private static boolean running = true;
private int Frames = 0;
private final Thread renderThread;
public class RenderThread extends EngineThread {
private final Render render;
private Window window;
public RenderThread(Window window, EngineInstance engineInstance, InitData initData) {
public RenderThread(Window window, EngineInstance engineInstance, InitData initData, GameLogic appLogic) {
//this.window = window;
render = new Render(engineInstance);
super(engineInstance,appLogic,"Render");
render.Initialise(initData);
renderThread = new Thread(this);
renderThread.setName("Terrain4J Vulkan Render Thread");
}
public void KillThread(){
running = false;
@Override
public void TickEvent(long nsTimeDiff){
}
public Thread FetchRenderThread(){
return renderThread;
@Override
public void FrameEvent(long now, long InitialTime){
render.render(PrimaryRuntime.GetEngineInstance());
}
public void StartRenderThread(){
renderThread.start();
@Override
public void CycleEvent(){
}
private void cleanup() {
@Override
public void SecondEvent(){
Logger.info("Render FPS: " + Frames);
}
@Override
public void cleanup() {
render.cleanup();
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() {
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();
}
}

View file

@ -0,0 +1,8 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering;
public class Image {
public static class ImageData{
}
}

View file

@ -8,13 +8,17 @@ display_height=480
display_width=640
#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
throttle_on_unfocus=true
throttle_accuracy=500000000
#event tick rate for game process
master_tick_rate=120
main_thread_tickrate=120
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
Debug_Shaders = false