make render system safer, detect gpu memory leaks

This commit is contained in:
Bixilon 2022-09-26 13:52:09 +02:00
parent 0eee704cdf
commit 2c76371578
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 91 additions and 6 deletions

View File

@ -301,6 +301,7 @@ class RenderWindow(
Log.log(LogMessageType.RENDERING_LOADING) { "Destroying render window..." }
renderingState = RenderingStates.STOPPED
renderSystem.destroy()
window.destroy()
Log.log(LogMessageType.RENDERING_LOADING) { "Render window destroyed!" }
// disconnect

View File

@ -37,7 +37,10 @@ interface RenderSystem {
var shader: Shader?
var framebuffer: Framebuffer?
val active: Boolean
fun init()
fun destroy()
fun reset(
depthTest: Boolean = true,

View File

@ -18,6 +18,7 @@ import de.bixilon.kotlinglm.vec2.Vec2i
interface Renderbuffer {
val mode: RenderbufferModes
val size: Vec2i
val state: RenderbufferStates
fun init()
fun unload()

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.system.base.buffer.render
enum class RenderbufferStates {
PREPARING,
GENERATED,
UNLOADED,
;
}

View File

@ -0,0 +1,16 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.system.opengl
class MemoryLeakException(message: String? = null) : Exception(message)

View File

@ -55,6 +55,8 @@ class OpenGLRenderSystem(
private val capabilities: MutableSet<RenderingCapabilities> = synchronizedSetOf()
override lateinit var vendor: OpenGLVendor
private set
override var active: Boolean = false
private set
var blendingSource = BlendingFunctions.ONE
private set
@ -140,6 +142,11 @@ class OpenGLRenderSystem(
Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.VERBOSE) { "OpenGL error: source=$source, type=$type, id=$id, severity=$severity, length=$length, message=$message, userParameter=$userParameter" }
}, 0)
}
active = true
}
override fun destroy() {
active = false
}
override fun enable(capability: RenderingCapabilities) {
@ -184,6 +191,7 @@ class OpenGLRenderSystem(
private var destinationRGB: BlendingFunctions = BlendingFunctions.ONE
private var sourceAlpha: BlendingFunctions = BlendingFunctions.ONE
private var destinationAlpha: BlendingFunctions = BlendingFunctions.ONE
override fun setBlendFunction(sourceRGB: BlendingFunctions, destinationRGB: BlendingFunctions, sourceAlpha: BlendingFunctions, destinationAlpha: BlendingFunctions) {
if (this.sourceRGB == sourceRGB && this.destinationRGB == destinationRGB && this.sourceAlpha == sourceAlpha && this.destinationAlpha == destinationAlpha) {
return
@ -261,7 +269,7 @@ class OpenGLRenderSystem(
}
override fun createFramebuffer(): OpenGLFramebuffer {
return OpenGLFramebuffer(renderWindow.window.size)
return OpenGLFramebuffer(this, renderWindow.window.size)
}
override fun createTextureManager(): OpenGLTextureManager {

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBuffer
import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferDrawTypes
import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferStates
import de.bixilon.minosoft.gui.rendering.system.base.buffer.RenderableBufferTypes
import de.bixilon.minosoft.gui.rendering.system.opengl.MemoryLeakException
import de.bixilon.minosoft.gui.rendering.system.opengl.OpenGLRenderSystem
import org.lwjgl.opengl.GL15.*
import org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER
@ -59,6 +60,11 @@ abstract class OpenGLRenderableBuffer(
state = RenderableBufferStates.UNLOADED
}
protected fun finalize() {
if (state == RenderableBufferStates.UPLOADED && renderSystem.active) {
throw MemoryLeakException("Buffer has not been unloaded!")
}
}
protected companion object {
val RenderableBufferTypes.gl: Int

View File

@ -19,12 +19,14 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.frame.FramebufferSta
import de.bixilon.minosoft.gui.rendering.system.base.buffer.frame.texture.FramebufferTexture
import de.bixilon.minosoft.gui.rendering.system.base.buffer.render.Renderbuffer
import de.bixilon.minosoft.gui.rendering.system.base.buffer.render.RenderbufferModes
import de.bixilon.minosoft.gui.rendering.system.opengl.MemoryLeakException
import de.bixilon.minosoft.gui.rendering.system.opengl.OpenGLRenderSystem
import de.bixilon.minosoft.gui.rendering.system.opengl.buffer.frame.texture.OpenGLFramebufferColorTexture
import de.bixilon.minosoft.gui.rendering.system.opengl.buffer.frame.texture.OpenGLFramebufferDepthTexture
import de.bixilon.minosoft.gui.rendering.system.opengl.buffer.render.OpenGLRenderbuffer
import org.lwjgl.opengl.GL30.*
class OpenGLFramebuffer(var size: Vec2i) : Framebuffer {
class OpenGLFramebuffer(val renderSystem: OpenGLRenderSystem, var size: Vec2i) : Framebuffer {
override var state: FramebufferState = FramebufferState.PREPARING
private set
@ -45,7 +47,7 @@ class OpenGLFramebuffer(var size: Vec2i) : Framebuffer {
colorTexture.init()
attach(colorTexture)
renderbuffer = OpenGLRenderbuffer(RenderbufferModes.DEPTH_COMPONENT24, size)
renderbuffer = OpenGLRenderbuffer(renderSystem, RenderbufferModes.DEPTH_COMPONENT24, size)
renderbuffer.init()
attach(renderbuffer)
@ -109,4 +111,10 @@ class OpenGLFramebuffer(var size: Vec2i) : Framebuffer {
delete()
init()
}
protected fun finalize() {
if (state == FramebufferState.COMPLETE && renderSystem.active) {
throw MemoryLeakException("Buffer has not been unloaded!")
}
}
}

View File

@ -16,28 +16,49 @@ package de.bixilon.minosoft.gui.rendering.system.opengl.buffer.render
import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.minosoft.gui.rendering.system.base.buffer.render.Renderbuffer
import de.bixilon.minosoft.gui.rendering.system.base.buffer.render.RenderbufferModes
import de.bixilon.minosoft.gui.rendering.system.base.buffer.render.RenderbufferStates
import de.bixilon.minosoft.gui.rendering.system.opengl.MemoryLeakException
import de.bixilon.minosoft.gui.rendering.system.opengl.OpenGLRenderSystem
import org.lwjgl.opengl.GL30.*
class OpenGLRenderbuffer(
private val renderSystem: OpenGLRenderSystem,
override val mode: RenderbufferModes,
override val size: Vec2i,
) : Renderbuffer {
override var state: RenderbufferStates = RenderbufferStates.PREPARING
private set
var id = -1
private set
override fun init() {
check(state == RenderbufferStates.PREPARING) { "Can not init renderbuffer in $state" }
id = glGenRenderbuffers()
bind()
unsafeBind()
glRenderbufferStorage(GL_RENDERBUFFER, mode.gl, size.x, size.y)
state = RenderbufferStates.GENERATED
}
fun bind() {
check(state == RenderbufferStates.GENERATED) { "Can not bind renderbuffer in $state" }
unsafeBind()
}
fun unsafeBind() {
glBindRenderbuffer(GL_RENDERBUFFER, id)
}
override fun unload() {
check(state == RenderbufferStates.GENERATED) { "Can not unload renderbuffer in $state" }
glDeleteRenderbuffers(id)
id = -1
state = RenderbufferStates.UNLOADED
}
protected fun finalize() {
if (state == RenderbufferStates.GENERATED && renderSystem.active) {
throw MemoryLeakException("Renderbuffer has not been unloaded!")
}
}
companion object {

View File

@ -27,7 +27,8 @@ import java.nio.FloatBuffer
class FloatOpenGLVertexBuffer(
renderSystem: OpenGLRenderSystem,
override val structure: MeshStruct, data: FloatBuffer,
override val structure: MeshStruct,
data: FloatBuffer,
override val primitiveType: PrimitiveTypes,
) : FloatOpenGLBuffer(renderSystem, data), FloatVertexBuffer {
override var vertices = -1
@ -89,7 +90,6 @@ class FloatOpenGLVertexBuffer(
super.unload()
}
private companion object {
val PrimitiveTypes.gl: Int
get() {