forked from StarOpenSource/Engine
Move continuous render loop to interface (now class)
This commit is contained in:
parent
7f324090c1
commit
9c48c3c756
2 changed files with 72 additions and 49 deletions
|
@ -22,9 +22,7 @@ package de.staropensource.sosengine.graphics.glfw.classes;
|
||||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||||
import de.staropensource.sosengine.base.types.CodePart;
|
import de.staropensource.sosengine.base.types.CodePart;
|
||||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||||
import de.staropensource.sosengine.base.utility.Math;
|
|
||||||
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||||
import de.staropensource.sosengine.graphics.GraphicsSubsystemConfiguration;
|
|
||||||
import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
|
import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
|
||||||
import de.staropensource.sosengine.graphics.classes.Window;
|
import de.staropensource.sosengine.graphics.classes.Window;
|
||||||
import de.staropensource.sosengine.graphics.glfw.exceptions.NotOnMainThreadException;
|
import de.staropensource.sosengine.graphics.glfw.exceptions.NotOnMainThreadException;
|
||||||
|
@ -32,12 +30,11 @@ import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public abstract class GlfwManagementClass implements ApiManagementClass {
|
public abstract class GlfwManagementClass extends ApiManagementClass {
|
||||||
/**
|
/**
|
||||||
* Contains the {@link LoggerInstance} for this class.
|
* Contains the {@link LoggerInstance} for this class.
|
||||||
*
|
*
|
||||||
|
@ -83,44 +80,6 @@ public abstract class GlfwManagementClass implements ApiManagementClass {
|
||||||
if (!Miscellaneous.onMainThread())
|
if (!Miscellaneous.onMainThread())
|
||||||
throw new NotOnMainThreadException();
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
AtomicReference<LinkedHashMap<@NotNull Window, @NotNull Throwable>> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output
|
return super.runRenderLoopContinuously(frameCode);
|
||||||
long renderTime; // Amount of time spent rendering
|
|
||||||
long sleepDuration; // Time spent sleeping the thread
|
|
||||||
LinkedList<Long> splitDeltaTime = new LinkedList<>(); // Used for calculating the delta time (render time average over one second)
|
|
||||||
long reportDuration = System.currentTimeMillis(); // Used for determining when to report frame count and delta time
|
|
||||||
double deltaTime; // Contains the average render time over one second (delta time)
|
|
||||||
|
|
||||||
// Run while the 'output' is empty
|
|
||||||
while (output.get().isEmpty()) {
|
|
||||||
renderTime = Miscellaneous.measureExecutionTime(() -> {
|
|
||||||
output.set(runRenderLoop());
|
|
||||||
frameCode.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO v-sync is currently broken, monitor api needs to be implemented first
|
|
||||||
|
|
||||||
// Calculate amount of time the thread should spend sleeping
|
|
||||||
sleepDuration = (long) (1d / GraphicsSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d) - renderTime;
|
|
||||||
// Add render and sleep time to list used for calculating the delta time value
|
|
||||||
splitDeltaTime.add(renderTime + sleepDuration);
|
|
||||||
|
|
||||||
try {
|
|
||||||
//noinspection BusyWait // true, true
|
|
||||||
Thread.sleep(sleepDuration);
|
|
||||||
} catch (InterruptedException exception) {
|
|
||||||
logger.crash("Rendering loop got interrupted. This is unsupported behaviour.", exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate delta time and frame count every second
|
|
||||||
if (System.currentTimeMillis() >= reportDuration + 1000) {
|
|
||||||
deltaTime = Math.getMeanLong(splitDeltaTime); // Calculate delta time
|
|
||||||
logger.info("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console
|
|
||||||
|
|
||||||
reportDuration = System.currentTimeMillis(); // Update 'reportDuration'
|
|
||||||
splitDeltaTime.clear(); // Clear 'splitDeltaTime' list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,33 +19,57 @@
|
||||||
|
|
||||||
package de.staropensource.sosengine.graphics.classes;
|
package de.staropensource.sosengine.graphics.classes;
|
||||||
|
|
||||||
|
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||||
|
import de.staropensource.sosengine.base.types.CodePart;
|
||||||
|
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||||
|
import de.staropensource.sosengine.base.utility.Math;
|
||||||
|
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||||
|
import de.staropensource.sosengine.graphics.GraphicsSubsystemConfiguration;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface for Graphics API management classes.
|
* The interface for Graphics API management classes.
|
||||||
*
|
*
|
||||||
* @since v1-alpha0
|
* @since v1-alpha0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unused" })
|
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
|
||||||
public interface ApiManagementClass {
|
public abstract class ApiManagementClass {
|
||||||
|
/**
|
||||||
|
* Contains the logger instance for this class.
|
||||||
|
*
|
||||||
|
* @since v1-alpha2
|
||||||
|
*
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the logger instance for this class.
|
||||||
|
*
|
||||||
|
* @return logger instance
|
||||||
|
* @since v1-alpha2
|
||||||
|
*/
|
||||||
|
@Getter(value = AccessLevel.PROTECTED)
|
||||||
|
private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass(), CodePart.ENGINE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if this Graphics API must be interacted with on the main thread.
|
* Returns if this Graphics API must be interacted with on the main thread.
|
||||||
*
|
*
|
||||||
* @return {@code true} if Graphics API must be interacted with on the main thread, {@code false} otherwise
|
* @return {@code true} if Graphics API must be interacted with on the main thread, {@code false} otherwise
|
||||||
* @since v1-alpha2
|
* @since v1-alpha2
|
||||||
*/
|
*/
|
||||||
boolean mustRunOnMainThread();
|
public abstract boolean mustRunOnMainThread();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the render loop <b>once</b>.
|
* Runs the render loop <b>once</b>.
|
||||||
* To run the render loop continuously, see {@link #runRenderLoopContinuously()}.
|
* To run the render loop continuously, see {@link #runRenderLoopContinuously(Runnable)}.
|
||||||
*
|
*
|
||||||
* @return map of windows and their thrown throwables
|
* @return map of windows and their thrown throwables
|
||||||
* @since v1-alpha2
|
* @since v1-alpha2
|
||||||
*/
|
*/
|
||||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop();
|
public abstract LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the render loop <b>for ever</b>.
|
* Runs the render loop <b>for ever</b>.
|
||||||
|
@ -57,5 +81,45 @@ public interface ApiManagementClass {
|
||||||
* @return see {@link #runRenderLoop()}
|
* @return see {@link #runRenderLoop()}
|
||||||
* @since v1-alpha2
|
* @since v1-alpha2
|
||||||
*/
|
*/
|
||||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoopContinuously(@NotNull Runnable frameCode);
|
public LinkedHashMap<@NotNull Window, @NotNull Throwable> runRenderLoopContinuously(@NotNull Runnable frameCode) {
|
||||||
|
AtomicReference<LinkedHashMap<@NotNull Window, @NotNull Throwable>> output = new AtomicReference<>(new LinkedHashMap<>()); // runRenderLoop output
|
||||||
|
long renderTime; // Amount of time spent rendering
|
||||||
|
long sleepDuration; // Time spent sleeping the thread
|
||||||
|
LinkedList<Long> splitDeltaTime = new LinkedList<>(); // Used for calculating the delta time (render time average over one second)
|
||||||
|
long reportDuration = System.currentTimeMillis(); // Used for determining when to report frame count and delta time
|
||||||
|
double deltaTime; // Contains the average render time over one second (delta time)
|
||||||
|
|
||||||
|
// Run while the 'output' is empty
|
||||||
|
while (output.get().isEmpty()) {
|
||||||
|
renderTime = Miscellaneous.measureExecutionTime(() -> {
|
||||||
|
output.set(runRenderLoop());
|
||||||
|
frameCode.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO v-sync is currently broken, monitor api needs to be implemented first
|
||||||
|
|
||||||
|
// Calculate amount of time the thread should spend sleeping
|
||||||
|
sleepDuration = (long) (1d / GraphicsSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d) - renderTime;
|
||||||
|
// Add render and sleep time to list used for calculating the delta time value
|
||||||
|
splitDeltaTime.add(renderTime + sleepDuration);
|
||||||
|
|
||||||
|
try {
|
||||||
|
//noinspection BusyWait // true, true
|
||||||
|
Thread.sleep(sleepDuration);
|
||||||
|
} catch (InterruptedException exception) {
|
||||||
|
logger.crash("Rendering loop got interrupted. This is unsupported behaviour.", exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate delta time and frame count every second
|
||||||
|
if (System.currentTimeMillis() >= reportDuration + 1000) {
|
||||||
|
deltaTime = Math.getMeanLong(splitDeltaTime); // Calculate delta time
|
||||||
|
logger.info("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console
|
||||||
|
|
||||||
|
reportDuration = System.currentTimeMillis(); // Update 'reportDuration'
|
||||||
|
splitDeltaTime.clear(); // Clear 'splitDeltaTime' list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue