diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/vertex/FloatOpenGLVertexBuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/vertex/FloatOpenGLVertexBuffer.kt
index bb97d7197..6739d5cef 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/vertex/FloatOpenGLVertexBuffer.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/vertex/FloatOpenGLVertexBuffer.kt
@@ -5,7 +5,6 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.FloatVertexBu
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes
import de.bixilon.minosoft.gui.rendering.system.opengl.buffer.FloatOpenGLBuffer
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
-import de.bixilon.minosoft.util.KUtil.clean
import org.lwjgl.opengl.ARBVertexArrayObject.glBindVertexArray
import org.lwjgl.opengl.ARBVertexArrayObject.glGenVertexArrays
import org.lwjgl.opengl.GL11.*
@@ -33,7 +32,6 @@ class FloatOpenGLVertexBuffer(override val structure: MeshStruct, data: FloatBuf
glBufferData(type.gl, buffer, drawTypes.gl)
state = RenderBufferStates.UPLOADED
- buffer.clean()
_data = null
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/Mesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/Mesh.kt
index 2a329046a..10e42befe 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/Mesh.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/Mesh.kt
@@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.util.mesh
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.FloatVertexBuffer
import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes
-import de.bixilon.minosoft.util.collections.ArrayFloatList
+import de.bixilon.minosoft.util.collections.DirectArrayFloatList
import glm_.vec2.Vec2
import glm_.vec3.Vec3
@@ -27,8 +27,8 @@ abstract class Mesh(
initialCacheSize: Int = 10000,
) {
val order = renderWindow.renderSystem.primitiveMeshOrder
- private var _data: ArrayFloatList? = ArrayFloatList(initialCacheSize)
- var data: ArrayFloatList
+ private var _data: DirectArrayFloatList? = DirectArrayFloatList(initialCacheSize)
+ var data: DirectArrayFloatList
get() = _data!!
set(value) {
_data = value
@@ -45,8 +45,9 @@ abstract class Mesh(
fun load() {
buffer = renderWindow.renderSystem.createVertexBuffer(struct, data.buffer, primitiveType)
- _data = null
buffer.init()
+ data.unload()
+ _data = null
vertices = buffer.vertices
}
diff --git a/src/main/java/de/bixilon/minosoft/util/KUtil.kt b/src/main/java/de/bixilon/minosoft/util/KUtil.kt
index f0f781afa..53b046608 100644
--- a/src/main/java/de/bixilon/minosoft/util/KUtil.kt
+++ b/src/main/java/de/bixilon/minosoft/util/KUtil.kt
@@ -33,7 +33,6 @@ import glm_.vec2.Vec2t
import glm_.vec3.Vec3t
import glm_.vec4.Vec4t
import okio.Buffer
-import org.lwjgl.system.MemoryUtil.memFree
import sun.misc.Unsafe
import java.io.PrintWriter
import java.io.StringWriter
@@ -506,8 +505,4 @@ object KUtil {
this.get(array)
return array
}
-
- fun java.nio.Buffer.clean() {
- memFree(this)
- }
}
diff --git a/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt b/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt
index 73a6fabfa..5d763e886 100644
--- a/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt
+++ b/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt
@@ -1,34 +1,27 @@
/*
- * 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 .
- *
- * This software is not affiliated with Mojang AB, the original developer of Minecraft.
- */
-
+* 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 .
+*
+* This software is not affiliated with Mojang AB, the original developer of Minecraft.
+*/
package de.bixilon.minosoft.util.collections
-import de.bixilon.minosoft.util.KUtil
-import de.bixilon.minosoft.util.KUtil.clean
-import org.lwjgl.system.MemoryUtil.memAllocFloat
-import java.nio.FloatBuffer
-
class ArrayFloatList(
initialSize: Int = DEFAULT_INITIAL_SIZE,
) {
- var buffer: FloatBuffer = memAllocFloat(initialSize) // ToDo: Clear when disconnected
- private set
+ private var data: FloatArray = FloatArray(initialSize)
var finalized: Boolean = false
private set
- val capacity: Int
- get() = buffer.capacity()
- val size: Int
- get() = buffer.position()
+ val limit: Int
+ get() = data.size
+ var size = 0
+ private set
val isEmpty: Boolean
get() = size == 0
@@ -49,66 +42,55 @@ class ArrayFloatList(
fun clear() {
checkFinalized()
- buffer.clean()
+ size = 0
outputUpToDate = false
output = FloatArray(0)
}
private fun ensureSize(needed: Int) {
checkFinalized()
- if (capacity - size >= needed) {
+ if (limit - size >= needed) {
return
}
- var newSize = capacity
+ var newSize = data.size
while (newSize - size < needed) {
newSize += nextGrowStep
}
- val oldBuffer = buffer
- buffer = memAllocFloat(newSize)
- if (FLOAT_PUT_METHOD == null) { // Java < 16
- for (i in 0 until oldBuffer.position()) {
- buffer.put(oldBuffer.get(i))
- }
- } else {
- FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
- buffer.position(oldBuffer.position())
- }
- oldBuffer.clean()
+ val oldData = data
+ data = FloatArray(newSize)
+ System.arraycopy(oldData, 0, data, 0, oldData.size)
}
fun add(float: Float) {
ensureSize(1)
- buffer.put(float)
+ data[size++] = float
outputUpToDate = false
}
fun addAll(floats: FloatArray) {
ensureSize(floats.size)
- buffer.put(floats)
+ System.arraycopy(floats, 0, data, size, floats.size)
+ size += floats.size
outputUpToDate = false
}
fun addAll(floatList: ArrayFloatList) {
ensureSize(floatList.size)
- if (FLOAT_PUT_METHOD == null) { // Java < 16
- for (i in 0 until floatList.buffer.position()) {
- buffer.put(floatList.buffer.get(i))
- }
+ val source = if (floatList.finalized) {
+ floatList.output
} else {
- FLOAT_PUT_METHOD.invoke(buffer, buffer.position(), floatList.buffer, 0, floatList.buffer.position())
- buffer.position(buffer.position() + floatList.buffer.position())
+ floatList.data
}
+ System.arraycopy(source, 0, data, size, floatList.size)
+ size += floatList.size
}
private fun checkOutputArray() {
if (outputUpToDate) {
return
}
- val position = buffer.position()
- output = FloatArray(position)
- buffer.position(0)
- buffer.get(output, 0, position)
- buffer.position(position)
+ output = FloatArray(size)
+ System.arraycopy(data, 0, output, 0, size)
outputUpToDate = true
}
@@ -119,22 +101,12 @@ class ArrayFloatList(
fun finish() {
finalized = true
- val oldBuffer = buffer
- buffer = memAllocFloat(oldBuffer.position())
- if (FLOAT_PUT_METHOD == null) { // Java < 16
- for (i in 0 until oldBuffer.position()) {
- buffer.put(oldBuffer.get(i))
- }
- } else {
- FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
- buffer.position(buffer.limit())
- }
- oldBuffer.clean()
+ checkOutputArray()
+ data = FloatArray(0)
}
private companion object {
- private val FLOAT_PUT_METHOD = KUtil.tryCatch { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) }
private const val DEFAULT_INITIAL_SIZE = 1000
}
}
diff --git a/src/main/java/de/bixilon/minosoft/util/collections/DirectArrayFloatList.kt b/src/main/java/de/bixilon/minosoft/util/collections/DirectArrayFloatList.kt
new file mode 100644
index 000000000..e9772b392
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/util/collections/DirectArrayFloatList.kt
@@ -0,0 +1,153 @@
+/*
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.util.collections
+
+import de.bixilon.minosoft.util.KUtil
+import org.lwjgl.system.MemoryUtil.memAllocFloat
+import org.lwjgl.system.MemoryUtil.memFree
+import java.nio.FloatBuffer
+
+class DirectArrayFloatList(
+ initialSize: Int = DEFAULT_INITIAL_SIZE,
+) {
+ var buffer: FloatBuffer = memAllocFloat(initialSize) // ToDo: Clear when disconnected
+ private set
+ var finalized: Boolean = false
+ private set
+ val capacity: Int
+ get() = buffer.capacity()
+ val size: Int
+ get() = buffer.position()
+ val isEmpty: Boolean
+ get() = size == 0
+ private var unloaded = false
+
+ private val nextGrowStep = when {
+ initialSize <= 0 -> DEFAULT_INITIAL_SIZE
+ initialSize <= 50 -> 50
+ else -> initialSize
+ }
+
+ private var output: FloatArray = FloatArray(0)
+ private var outputUpToDate = false
+
+ private fun checkFinalized() {
+ if (finalized) {
+ throw IllegalStateException("ArrayFloatList is already finalized!")
+ }
+ }
+
+ private fun ensureSize(needed: Int) {
+ checkFinalized()
+ if (capacity - size >= needed) {
+ return
+ }
+ var newSize = capacity
+ while (newSize - size < needed) {
+ newSize += nextGrowStep
+ }
+ val oldBuffer = buffer
+ buffer = memAllocFloat(newSize)
+ if (FLOAT_PUT_METHOD == null) { // Java < 16
+ for (i in 0 until oldBuffer.position()) {
+ buffer.put(oldBuffer.get(i))
+ }
+ } else {
+ FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
+ buffer.position(oldBuffer.position())
+ }
+ memFree(oldBuffer)
+ }
+
+ fun add(float: Float) {
+ ensureSize(1)
+ buffer.put(float)
+ outputUpToDate = false
+ }
+
+ fun addAll(floats: FloatArray) {
+ ensureSize(floats.size)
+ buffer.put(floats)
+ outputUpToDate = false
+ }
+
+ fun addAll(floatList: DirectArrayFloatList) {
+ ensureSize(floatList.size)
+ if (FLOAT_PUT_METHOD == null) { // Java < 16
+ for (i in 0 until floatList.buffer.position()) {
+ buffer.put(floatList.buffer.get(i))
+ }
+ } else {
+ FLOAT_PUT_METHOD.invoke(buffer, buffer.position(), floatList.buffer, 0, floatList.buffer.position())
+ buffer.position(buffer.position() + floatList.buffer.position())
+ }
+ }
+
+ fun addAll(floatList: ArrayFloatList) {
+ ensureSize(floatList.size)
+ buffer.put(floatList.toArray())
+ }
+
+ private fun checkOutputArray() {
+ if (outputUpToDate) {
+ return
+ }
+ val position = buffer.position()
+ output = FloatArray(position)
+ buffer.position(0)
+ buffer.get(output, 0, position)
+ buffer.position(position)
+ outputUpToDate = true
+ }
+
+ fun toArray(): FloatArray {
+ checkOutputArray()
+ return output
+ }
+
+ fun unload() {
+ check(!unloaded) { "Already unloaded!" }
+ unloaded = true
+ finalized = true // Is unloaded
+ memFree(buffer)
+ }
+
+ fun finish() {
+ finalized = true
+ val oldBuffer = buffer
+ buffer = memAllocFloat(oldBuffer.position())
+ if (FLOAT_PUT_METHOD == null) { // Java < 16
+ for (i in 0 until oldBuffer.position()) {
+ buffer.put(oldBuffer.get(i))
+ }
+ } else {
+ FLOAT_PUT_METHOD.invoke(buffer, 0, oldBuffer, 0, oldBuffer.position())
+ buffer.position(buffer.limit())
+ }
+ memFree(oldBuffer)
+ }
+
+ protected fun finalize() {
+ if (unloaded) {
+ return
+ }
+ memFree(buffer)
+ }
+
+
+ private companion object {
+ private val FLOAT_PUT_METHOD = KUtil.tryCatch { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) }
+ private const val DEFAULT_INITIAL_SIZE = 1000
+ }
+}