SimpleJavaEngine/src/main/java/speiger/src/coreengine/application/ApplicationExecutor.java

144 lines
4.6 KiB
Java

package speiger.src.coreengine.application;
import java.text.DecimalFormat;
import org.lwjgl.opengl.GL11;
import speiger.src.collections.objects.queues.ObjectArrayFIFOQueue;
import speiger.src.collections.objects.queues.ObjectPriorityQueue;
import speiger.src.coreengine.rendering.input.window.Window;
import speiger.src.coreengine.rendering.utils.AllocationTracker;
import speiger.src.coreengine.rendering.utils.GLStamper;
import speiger.src.coreengine.rendering.utils.GLStamper.GLStamp;
import speiger.src.coreengine.rendering.utils.GLUtils;
import speiger.src.coreengine.utils.counters.averager.TimeAverager;
import speiger.src.coreengine.utils.counters.timers.FPSTimer;
import speiger.src.coreengine.utils.counters.timers.FrameSyncer;
import speiger.src.coreengine.utils.counters.timers.TimerTarget;
import speiger.src.coreengine.utils.helpers.FileUtils;
import speiger.src.coreengine.utils.helpers.TextUtil;
import speiger.src.coreengine.utils.io.GameLog;
import speiger.src.coreengine.utils.io.GameLog.LogLevel;
import speiger.src.coreengine.utils.profiler.IProfiler;
public class ApplicationExecutor
{
public static final DecimalFormat FORMATTER = new DecimalFormat("###");
FPSTimer timer = new FPSTimer();
TimerTarget fps = timer.getFPS();
TimerTarget ups = timer.getUPS();
FrameSyncer sync = new FrameSyncer();
TimeAverager gpuTime = new TimeAverager();
ObjectPriorityQueue<GLStamp> stamps = new ObjectArrayFIFOQueue<>();
StringBuilder builder = new StringBuilder();
long frame = 0L;
Application owner;
public ApplicationExecutor(Application owner)
{
this.owner = owner;
owner.timer = timer;
}
private IProfiler gpu()
{
return owner.gpuProfiler;
}
public void start(Window window)
{
createTimeHacker();
timer.init();
try
{
while(window.shouldRun()) loop(window);
}
catch(Exception e)
{
GameLog.error("Client Has Crashed", e, LogLevel.ERROR);
}
}
private void loop(Window window)
{
GLStamp stamp = GLStamper.INSTANCE.createStamp("MainStamp").start();
stamps.enqueue(stamp);
gpu().start("Client").start("Update");
window.update();
for(long f = timer.getDelta();f >= ups.getTargetNS();f = timer.consumeDelta())
{
ups.tick();
owner.updateInternal();
builder.setLength(0);
builder.append(owner.getMainWindowName());
if(owner.showProfilingInfo) addDebugInfo(builder);
window.setTitle(builder.toString());
}
gpu().next("Render");
render(timer.getParticalTime());
gpu().next("Trackers");
boolean end = timer.update();
stamp.stop();
AllocationTracker.INSTANCE.update();
GLUtils.onFrameEnded();
gpu().next("Window").start("V-Sync");
window.finishFrame();
if(window.isCPULimited()) sync.sync(fps.getTargetTicks());
gpu().next("Input");
window.gatherInputs();
gpu().stop().stop().stop().onFrameEnded(end);
while(!stamps.isEmpty() && stamps.first().isFinished())
{
stamp = stamps.dequeue();
gpuTime.addEntry(stamp.getResult());
stamp.release();
}
frame++;
}
private void render(float particalTicks)
{
gpu().start("Prep");
fps.tick();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
gpu().stop();
owner.renderInternal(particalTicks);
}
public void createTimeHacker()
{
Thread thread = new Thread(() -> {
while (true){
try {Thread.sleep(2147483647L);}
catch (InterruptedException e){}
}
}, "Time Fixer Thread");
thread.setDaemon(true);
thread.start();
}
protected void addDebugInfo(StringBuilder builder)
{
builder.append("(");
builder.append(fps.getTicks()).append(":").append(ups.getTicks());
owner.addExtraTickRates(T -> builder.append(":").append(T));
builder.append(",").append(getMemoryUsage());
builder.append(",").append("CPU-A: "+FileUtils.convertBytes(AllocationTracker.INSTANCE.getCPUAllocatedBytes()));
builder.append(",").append("GPU-A: "+FileUtils.convertBytes(AllocationTracker.INSTANCE.getGPUAllocatedBytes()));
builder.append(",").append(TextUtil.convertTime(timer.getUsage(), "Client:", FORMATTER));
builder.append(",").append(TextUtil.convertTime(gpuTime.getAverage(), "GPU:", FORMATTER));
owner.addExtraTimers((N, T) -> builder.append(",").append(TextUtil.convertTime(T, N, FORMATTER)));
builder.append(")");
}
private String getMemoryUsage()
{
Runtime time = Runtime.getRuntime();
long aviable = time.totalMemory();
return "Memory:"+((aviable - time.freeMemory()) >> 20)+"MB/"+(aviable >> 20)+"MB";
}
}