mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 11:24:56 -04:00
far improved experimental fps
This commit is contained in:
parent
8bf7246bb7
commit
390a7e7f99
@ -19,6 +19,6 @@ data class OtherGameConfig(
|
|||||||
@Json(name = "anti_moire_pattern") var antiMoirePattern: Boolean = true,
|
@Json(name = "anti_moire_pattern") var antiMoirePattern: Boolean = true,
|
||||||
@Json(name = "flower_random_offset") var flowerRandomOffset: Boolean = true,
|
@Json(name = "flower_random_offset") var flowerRandomOffset: Boolean = true,
|
||||||
@Json(name = "block_outline") var blockOutline: BlockOutline = BlockOutline(),
|
@Json(name = "block_outline") var blockOutline: BlockOutline = BlockOutline(),
|
||||||
@Json(name = "magic_fps") var magicFPS: Boolean = false,
|
@Json(name = "experimental_fps") var experimentalFPS: Boolean = false,
|
||||||
@Json(name = "super_dumb_advanced_setting_leave_at_1") var swapInterval: Int = 1,
|
@Json(name = "super_dumb_advanced_setting_leave_at_1") var swapInterval: Int = 1,
|
||||||
)
|
)
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minosoft
|
|
||||||
* Copyright (C) 2020 Moritz Zwerger
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
|
||||||
import de.bixilon.minosoft.util.SystemInformation
|
|
||||||
import java.util.concurrent.ThreadLocalRandom
|
|
||||||
|
|
||||||
class RenderStats {
|
|
||||||
var fpsLastSecond = -1
|
|
||||||
private set
|
|
||||||
var minFrameTime = Long.MAX_VALUE
|
|
||||||
private set
|
|
||||||
var maxFrameTime = 0L
|
|
||||||
private set
|
|
||||||
var avgFrameTime = 0L
|
|
||||||
private set
|
|
||||||
var frames = 0L
|
|
||||||
private set
|
|
||||||
|
|
||||||
private var lastFPSCalcTime = 0L
|
|
||||||
private var framesLastSecond = 0
|
|
||||||
private var frameTime = 0L
|
|
||||||
|
|
||||||
private var frameStartTime = 0L
|
|
||||||
|
|
||||||
fun startFrame() {
|
|
||||||
frameStartTime = System.nanoTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun endDraw() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun endFrame() {
|
|
||||||
val frameEndTime = System.nanoTime()
|
|
||||||
val frameTime = frameEndTime - frameStartTime
|
|
||||||
if (frameTime < minFrameTime) {
|
|
||||||
minFrameTime = frameTime
|
|
||||||
}
|
|
||||||
if (frameTime > maxFrameTime) {
|
|
||||||
maxFrameTime = frameTime
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameEndTime - lastFPSCalcTime > 1E9) {
|
|
||||||
// 1 second
|
|
||||||
fpsLastSecond = if (Minosoft.config.config.game.other.magicFPS) {
|
|
||||||
ThreadLocalRandom.current().nextInt(MAGIC_FPS - 10, MAGIC_FPS)
|
|
||||||
} else {
|
|
||||||
framesLastSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
framesLastSecond = 0
|
|
||||||
lastFPSCalcTime = frameEndTime
|
|
||||||
this.frameTime = 0
|
|
||||||
}
|
|
||||||
frames++
|
|
||||||
framesLastSecond++
|
|
||||||
|
|
||||||
this.frameTime += frameTime
|
|
||||||
this.avgFrameTime = this.frameTime / framesLastSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private var MAGIC_FPS = ThreadLocalRandom.current().nextLong(SystemInformation.PROCESSOR_SPEED / 10000000 - 100, SystemInformation.PROCESSOR_SPEED / 10000000 + 100).toInt()
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,6 +22,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLike
|
|||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLikeTexture
|
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLikeTexture
|
||||||
import de.bixilon.minosoft.gui.rendering.input.key.RenderWindowInputHandler
|
import de.bixilon.minosoft.gui.rendering.input.key.RenderWindowInputHandler
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.*
|
import de.bixilon.minosoft.gui.rendering.modding.events.*
|
||||||
|
import de.bixilon.minosoft.gui.rendering.stats.AbstractRenderStats
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.IntegratedBufferTypes
|
import de.bixilon.minosoft.gui.rendering.system.base.IntegratedBufferTypes
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.PolygonModes
|
import de.bixilon.minosoft.gui.rendering.system.base.PolygonModes
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
||||||
@ -37,6 +38,7 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
|||||||
import de.bixilon.minosoft.util.CountUpAndDownLatch
|
import de.bixilon.minosoft.util.CountUpAndDownLatch
|
||||||
import de.bixilon.minosoft.util.KUtil.decide
|
import de.bixilon.minosoft.util.KUtil.decide
|
||||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||||
|
import de.bixilon.minosoft.util.MMath.round10
|
||||||
import de.bixilon.minosoft.util.Queue
|
import de.bixilon.minosoft.util.Queue
|
||||||
import de.bixilon.minosoft.util.Stopwatch
|
import de.bixilon.minosoft.util.Stopwatch
|
||||||
import de.bixilon.minosoft.util.logging.Log
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
@ -53,7 +55,7 @@ class RenderWindow(
|
|||||||
var initialized = false
|
var initialized = false
|
||||||
private set
|
private set
|
||||||
private lateinit var renderThread: Thread
|
private lateinit var renderThread: Thread
|
||||||
val renderStats = RenderStats()
|
val renderStats: AbstractRenderStats = AbstractRenderStats.createInstance()
|
||||||
|
|
||||||
val inputHandler = RenderWindowInputHandler(this)
|
val inputHandler = RenderWindowInputHandler(this)
|
||||||
|
|
||||||
@ -293,7 +295,7 @@ class RenderWindow(
|
|||||||
renderStats.endFrame()
|
renderStats.endFrame()
|
||||||
|
|
||||||
if (RenderConstants.SHOW_FPS_IN_WINDOW_TITLE) {
|
if (RenderConstants.SHOW_FPS_IN_WINDOW_TITLE) {
|
||||||
window.title = "Minosoft | FPS: ${renderStats.fpsLastSecond}"
|
window.title = "Minosoft | FPS: ${renderStats.smoothAvgFPS.round10}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.stats
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.Minosoft
|
||||||
|
import de.bixilon.minosoft.util.avg.Average
|
||||||
|
|
||||||
|
interface AbstractRenderStats {
|
||||||
|
val avgFrameTime: Average<Long>
|
||||||
|
val smoothAvgFPS: Double
|
||||||
|
|
||||||
|
val avgFPS: Double
|
||||||
|
val totalFrames: Long
|
||||||
|
|
||||||
|
|
||||||
|
fun startFrame() {}
|
||||||
|
fun endDraw() {}
|
||||||
|
fun endFrame() {}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun createInstance(): AbstractRenderStats {
|
||||||
|
if (Minosoft.config.config.game.other.experimentalFPS) {
|
||||||
|
return ExperimentalRenderStats()
|
||||||
|
}
|
||||||
|
|
||||||
|
return RenderStats()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.stats
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.KUtil.nextFloat
|
||||||
|
import de.bixilon.minosoft.util.avg.Average
|
||||||
|
import de.bixilon.minosoft.util.avg.LongAverage
|
||||||
|
import glm_.func.common.clamp
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
class ExperimentalRenderStats : AbstractRenderStats {
|
||||||
|
private val renderStats = RenderStats()
|
||||||
|
|
||||||
|
private val baseMultiplier = Random.nextFloat(1.0f, 1.5f)
|
||||||
|
private val baseJitter = Random.nextInt(0, 20)
|
||||||
|
|
||||||
|
override val avgFrameTime: Average<Long> = LongAverage(Long.MAX_VALUE)
|
||||||
|
|
||||||
|
private var lastSmoothFPSCalculationTime = 0L
|
||||||
|
override var smoothAvgFPS: Double = 0.0
|
||||||
|
get() {
|
||||||
|
val time = System.currentTimeMillis()
|
||||||
|
if (time - lastSmoothFPSCalculationTime > 100) {
|
||||||
|
field = avgFPS
|
||||||
|
lastSmoothFPSCalculationTime = time
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
private set
|
||||||
|
|
||||||
|
override val avgFPS: Double
|
||||||
|
get() {
|
||||||
|
val avgFPS = renderStats.avgFPS
|
||||||
|
|
||||||
|
val multiplier = 3.0f * baseMultiplier * Random.nextFloat(0.9f, 1.1f)
|
||||||
|
|
||||||
|
var fps = avgFPS * multiplier
|
||||||
|
|
||||||
|
fps += baseJitter
|
||||||
|
|
||||||
|
fps += Random.nextInt(-10, 10)
|
||||||
|
|
||||||
|
return fps.clamp(0.0, 10000.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
avgFrameTime.add(5000000L) // ToDo: Add real stats
|
||||||
|
}
|
||||||
|
|
||||||
|
override val totalFrames: Long
|
||||||
|
get() = renderStats.totalFrames
|
||||||
|
|
||||||
|
override fun startFrame() {
|
||||||
|
renderStats.startFrame()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endDraw() {
|
||||||
|
renderStats.endDraw()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endFrame() {
|
||||||
|
renderStats.endFrame()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.stats
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.avg.LongAverage
|
||||||
|
|
||||||
|
class RenderStats : AbstractRenderStats {
|
||||||
|
override val avgFrameTime: LongAverage = LongAverage(1L * 1000000000L) // 1 second * SECOND_SCALE
|
||||||
|
override var totalFrames: Long = 0L
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var lastFrameStartTime = -1L
|
||||||
|
|
||||||
|
private var lastSmoothFPSCalculationTime = 0L
|
||||||
|
|
||||||
|
override var smoothAvgFPS: Double = 0.0
|
||||||
|
get() {
|
||||||
|
val time = System.currentTimeMillis()
|
||||||
|
if (time - lastSmoothFPSCalculationTime > 100) {
|
||||||
|
field = avgFPS
|
||||||
|
lastSmoothFPSCalculationTime = time
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
private set
|
||||||
|
|
||||||
|
override val avgFPS: Double
|
||||||
|
get() {
|
||||||
|
val avgFrameTime = avgFrameTime.avg
|
||||||
|
|
||||||
|
return 1000000000L / avgFrameTime.toDouble() // SECOND_SCALE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun startFrame() {
|
||||||
|
lastFrameStartTime = System.nanoTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endFrame() {
|
||||||
|
val time = System.nanoTime()
|
||||||
|
|
||||||
|
val delta = time - lastFrameStartTime
|
||||||
|
|
||||||
|
avgFrameTime += delta
|
||||||
|
|
||||||
|
|
||||||
|
totalFrames++
|
||||||
|
}
|
||||||
|
}
|
@ -76,6 +76,8 @@ object MMath {
|
|||||||
|
|
||||||
val Float.round10: Float get() = (this * 10).toInt().toFloat() / 10f
|
val Float.round10: Float get() = (this * 10).toInt().toFloat() / 10f
|
||||||
|
|
||||||
|
val Double.round10: Double get() = (this * 10).toInt().toDouble() / 10.0
|
||||||
|
|
||||||
fun round10Up(value: Float): Int {
|
fun round10Up(value: Float): Int {
|
||||||
val intValue = value.toInt()
|
val intValue = value.toInt()
|
||||||
val rest = value / intValue
|
val rest = value / intValue
|
||||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.util
|
|||||||
import de.bixilon.minosoft.util.UnitFormatter.formatBytes
|
import de.bixilon.minosoft.util.UnitFormatter.formatBytes
|
||||||
import oshi.SystemInfo
|
import oshi.SystemInfo
|
||||||
|
|
||||||
|
@Deprecated(message = "Will be refactored")
|
||||||
object SystemInformation {
|
object SystemInformation {
|
||||||
val RUNTIME = Runtime.getRuntime()
|
val RUNTIME = Runtime.getRuntime()
|
||||||
val SYSTEM_INFO = SystemInfo()
|
val SYSTEM_INFO = SystemInfo()
|
||||||
|
28
src/main/java/de/bixilon/minosoft/util/avg/Average.kt
Normal file
28
src/main/java/de/bixilon/minosoft/util/avg/Average.kt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.util.avg
|
||||||
|
|
||||||
|
interface Average<T> {
|
||||||
|
val nanos: Long
|
||||||
|
|
||||||
|
val avg: T
|
||||||
|
|
||||||
|
fun cleanup()
|
||||||
|
|
||||||
|
fun add(value: T)
|
||||||
|
|
||||||
|
operator fun plusAssign(value: T) {
|
||||||
|
add(value)
|
||||||
|
}
|
||||||
|
}
|
69
src/main/java/de/bixilon/minosoft/util/avg/LongAverage.kt
Normal file
69
src/main/java/de/bixilon/minosoft/util/avg/LongAverage.kt
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.util.avg
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.KUtil.synchronizedListOf
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
||||||
|
|
||||||
|
class LongAverage(override val nanos: Long) : Average<Long> {
|
||||||
|
/**
|
||||||
|
* List of <Add Time (nanos), Value>
|
||||||
|
*/
|
||||||
|
private val data: MutableList<Pair<Long, Long>> = synchronizedListOf()
|
||||||
|
private var updated = false
|
||||||
|
private var lastAVG = 0L
|
||||||
|
|
||||||
|
override val avg: Long
|
||||||
|
@Synchronized get() {
|
||||||
|
if (!updated) {
|
||||||
|
return lastAVG
|
||||||
|
}
|
||||||
|
cleanup()
|
||||||
|
val data = data.toSynchronizedList()
|
||||||
|
|
||||||
|
var total = 0L
|
||||||
|
for ((_, value) in data) {
|
||||||
|
total += value
|
||||||
|
}
|
||||||
|
|
||||||
|
lastAVG = total / data.size
|
||||||
|
updated = false
|
||||||
|
return lastAVG
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cleanup() {
|
||||||
|
val time = System.nanoTime()
|
||||||
|
|
||||||
|
var indexOffset = 0
|
||||||
|
for ((index, pair) in data.toSynchronizedList().withIndex()) {
|
||||||
|
val (addTime, _) = pair
|
||||||
|
val addDelta = time - addTime
|
||||||
|
if (addDelta - nanos >= 0L) {
|
||||||
|
// remove
|
||||||
|
data.removeAt(index - indexOffset)
|
||||||
|
indexOffset++
|
||||||
|
updated = true
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(value: Long) {
|
||||||
|
cleanup()
|
||||||
|
val time = System.nanoTime()
|
||||||
|
data += Pair(time, value)
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user