Better frame scheduling
This commit is contained in:
parent
a41037826c
commit
1de2b4c167
@ -242,8 +242,8 @@ fun main() {
|
|||||||
//client.camera.pos.y = ent.position.y.toFloat()
|
//client.camera.pos.y = ent.position.y.toFloat()
|
||||||
|
|
||||||
client.camera.pos += Vector2f(
|
client.camera.pos += Vector2f(
|
||||||
(if (client.input.KEY_LEFT_DOWN || client.input.KEY_A_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_RIGHT_DOWN || client.input.KEY_D_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f),
|
(if (client.input.KEY_LEFT_DOWN || client.input.KEY_A_DOWN) -Starbound.TICK_TIME_ADVANCE.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_RIGHT_DOWN || client.input.KEY_D_DOWN) Starbound.TICK_TIME_ADVANCE.toFloat() * 32f / client.settings.zoom else 0f),
|
||||||
(if (client.input.KEY_UP_DOWN || client.input.KEY_W_DOWN) client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_DOWN_DOWN || client.input.KEY_S_DOWN) -client.frameRenderTime.toFloat() * 32f / client.settings.zoom else 0f)
|
(if (client.input.KEY_UP_DOWN || client.input.KEY_W_DOWN) Starbound.TICK_TIME_ADVANCE.toFloat() * 32f / client.settings.zoom else 0f) + (if (client.input.KEY_DOWN_DOWN || client.input.KEY_S_DOWN) -Starbound.TICK_TIME_ADVANCE.toFloat() * 32f / client.settings.zoom else 0f)
|
||||||
)
|
)
|
||||||
|
|
||||||
//println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1)
|
//println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1)
|
||||||
|
@ -85,6 +85,8 @@ import ru.dbotthepony.kstarbound.util.set
|
|||||||
import ru.dbotthepony.kstarbound.util.traverseJsonPath
|
import ru.dbotthepony.kstarbound.util.traverseJsonPath
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.function.BiConsumer
|
import java.util.function.BiConsumer
|
||||||
import java.util.function.BinaryOperator
|
import java.util.function.BinaryOperator
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
@ -95,7 +97,8 @@ import kotlin.collections.ArrayList
|
|||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
object Starbound : ISBFileLocator {
|
object Starbound : ISBFileLocator {
|
||||||
const val TICK_TIME_ADVANCE = 1.0 / 60.0
|
const val TICK_TIME_ADVANCE = 0.01666666666666664
|
||||||
|
const val TICK_TIME_ADVANCE_NANOS = 16_666_666L
|
||||||
|
|
||||||
// currently it saves only 4 megabytes of ram on pretty big modpack
|
// currently it saves only 4 megabytes of ram on pretty big modpack
|
||||||
// Hrm.
|
// Hrm.
|
||||||
|
@ -49,7 +49,6 @@ import ru.dbotthepony.kstarbound.client.world.ClientWorld
|
|||||||
import ru.dbotthepony.kstarbound.defs.image.Image
|
import ru.dbotthepony.kstarbound.defs.image.Image
|
||||||
import ru.dbotthepony.kstarbound.math.roundTowardsNegativeInfinity
|
import ru.dbotthepony.kstarbound.math.roundTowardsNegativeInfinity
|
||||||
import ru.dbotthepony.kstarbound.math.roundTowardsPositiveInfinity
|
import ru.dbotthepony.kstarbound.math.roundTowardsPositiveInfinity
|
||||||
import ru.dbotthepony.kstarbound.util.JVMTimeSource
|
|
||||||
import ru.dbotthepony.kstarbound.util.formatBytesShort
|
import ru.dbotthepony.kstarbound.util.formatBytesShort
|
||||||
import ru.dbotthepony.kstarbound.world.LightCalculator
|
import ru.dbotthepony.kstarbound.world.LightCalculator
|
||||||
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
import ru.dbotthepony.kstarbound.world.api.ICellAccess
|
||||||
@ -742,26 +741,41 @@ class StarboundClient : Closeable {
|
|||||||
blendFunc = BlendFunc.MULTIPLY_WITH_ALPHA
|
blendFunc = BlendFunc.MULTIPLY_WITH_ALPHA
|
||||||
}
|
}
|
||||||
|
|
||||||
var frameRenderTime = 0.0
|
// nanoseconds
|
||||||
|
var frameRenderTime = 0L
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private var lastRender = JVMTimeSource.INSTANCE.seconds
|
private var nextRender = System.nanoTime()
|
||||||
val framesPerSecond get() = if (frameRenderTime == 0.0) 1.0 else 1.0 / frameRenderTime
|
private val frameRenderTimes = LongArray(60) { 1L }
|
||||||
|
|
||||||
private val frameRenderTimes = DoubleArray(60) { 1.0 }
|
|
||||||
private var frameRenderIndex = 0
|
private var frameRenderIndex = 0
|
||||||
|
private val renderWaitTimes = LongArray(60) { 1L }
|
||||||
|
private var renderWaitIndex = 0
|
||||||
|
private var lastRender = System.nanoTime()
|
||||||
|
|
||||||
val averageFramesPerSecond: Double get() {
|
val averageRenderWait: Double get() {
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
|
|
||||||
for (value in frameRenderTimes) {
|
for (value in renderWaitTimes)
|
||||||
sum += value
|
sum += value
|
||||||
}
|
|
||||||
|
|
||||||
if (sum == 0.0)
|
if (sum == 0.0)
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
return frameRenderTimes.size / sum
|
sum /= 1_000_000_000.0
|
||||||
|
return sum / renderWaitTimes.size
|
||||||
|
}
|
||||||
|
|
||||||
|
val averageRenderTime: Double get() {
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
for (value in frameRenderTimes)
|
||||||
|
sum += value
|
||||||
|
|
||||||
|
if (sum == 0.0)
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
sum /= 1_000_000_000.0
|
||||||
|
return sum / frameRenderTimes.size
|
||||||
}
|
}
|
||||||
|
|
||||||
val settings = ClientSettings()
|
val settings = ClientSettings()
|
||||||
@ -828,15 +842,24 @@ class StarboundClient : Closeable {
|
|||||||
fun renderFrame(): Boolean {
|
fun renderFrame(): Boolean {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
|
|
||||||
val diff = JVMTimeSource.INSTANCE.seconds - lastRender
|
var diff = nextRender - System.nanoTime()
|
||||||
|
var yields = 0
|
||||||
|
|
||||||
if (diff < Starbound.TICK_TIME_ADVANCE)
|
// try to sleep until next frame as precise as possible
|
||||||
LockSupport.parkNanos(((Starbound.TICK_TIME_ADVANCE - diff) * 1_000_000_000.0).toLong())
|
while (diff > 0L) {
|
||||||
|
if (diff >= 1_500_000L) {
|
||||||
|
LockSupport.parkNanos(1_000_000L)
|
||||||
|
} else {
|
||||||
|
Thread.yield()
|
||||||
|
yields++
|
||||||
|
}
|
||||||
|
|
||||||
frameRenderTime = JVMTimeSource.INSTANCE.seconds - lastRender
|
diff = nextRender - System.nanoTime()
|
||||||
frameRenderTimes[++frameRenderIndex % frameRenderTimes.size] = frameRenderTime
|
}
|
||||||
lastRender = JVMTimeSource.INSTANCE.seconds
|
|
||||||
|
|
||||||
|
val mark = System.nanoTime()
|
||||||
|
|
||||||
|
try {
|
||||||
if (GLFW.glfwWindowShouldClose(window)) {
|
if (GLFW.glfwWindowShouldClose(window)) {
|
||||||
close()
|
close()
|
||||||
return false
|
return false
|
||||||
@ -974,8 +997,9 @@ class StarboundClient : Closeable {
|
|||||||
|
|
||||||
val runtime = Runtime.getRuntime()
|
val runtime = Runtime.getRuntime()
|
||||||
|
|
||||||
font.render("FPS: ${(averageFramesPerSecond * 100f).toInt() / 100f}", scale = 0.4f)
|
font.render("Latency: ${(averageRenderWait * 1_00000.0).toInt() / 100f}ms", scale = 0.4f)
|
||||||
font.render("JVM Heap: ${formatBytesShort(runtime.totalMemory() - runtime.freeMemory())}", y = font.lineHeight * 0.5f, scale = 0.4f)
|
font.render("Frame: ${(averageRenderTime * 1_00000.0).toInt() / 100f}ms", y = font.lineHeight * 0.6f, scale = 0.4f)
|
||||||
|
font.render("JVM Heap: ${formatBytesShort(runtime.totalMemory() - runtime.freeMemory())}", y = font.lineHeight * 1.2f, scale = 0.4f)
|
||||||
|
|
||||||
GLFW.glfwSwapBuffers(window)
|
GLFW.glfwSwapBuffers(window)
|
||||||
GLFW.glfwPollEvents()
|
GLFW.glfwPollEvents()
|
||||||
@ -986,6 +1010,13 @@ class StarboundClient : Closeable {
|
|||||||
cleanup()
|
cleanup()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
} finally {
|
||||||
|
frameRenderTime = System.nanoTime() - mark
|
||||||
|
frameRenderTimes[++frameRenderIndex % frameRenderTimes.size] = frameRenderTime
|
||||||
|
renderWaitTimes[++renderWaitIndex % renderWaitTimes.size] = System.nanoTime() - lastRender
|
||||||
|
lastRender = System.nanoTime()
|
||||||
|
nextRender = mark + Starbound.TICK_TIME_ADVANCE_NANOS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTermination(lambda: () -> Unit) {
|
fun onTermination(lambda: () -> Unit) {
|
||||||
|
Loading…
Reference in New Issue
Block a user