improve some memory stuff

This commit is contained in:
Bixilon 2021-11-15 16:23:05 +01:00
parent 69bd39bd45
commit f5c9afebae
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 192 additions and 73 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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
}
}