Added OpenGL buffers cleanup
- Now OpenGL buffers are being cleaned when GL objects are disposed - Fixed a bug when garbage collector ignore OpenGL objects
This commit is contained in:
parent
bfd5c02b0c
commit
bfdb22f357
@ -83,6 +83,8 @@ class LWJGLInitializer {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
RenderTaskQueue.schedule(OpenGLObjectTracker::deleteEnqueuedObjects);
|
||||
}
|
||||
|
||||
private static void setupWindowCallbacks() {
|
||||
|
@ -17,29 +17,80 @@
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.progressia.client.graphics.backend;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/*
|
||||
* FIXME deal with client invocations of .delete() when properly disposing of
|
||||
* objects mid-execution
|
||||
*/
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
public class OpenGLObjectTracker {
|
||||
|
||||
public static interface OpenGLDeletable {
|
||||
void delete();
|
||||
|
||||
public interface OpenGLDeletable {
|
||||
int getHandle();
|
||||
}
|
||||
|
||||
private static final Collection<OpenGLDeletable> TO_DELETE = new ArrayList<>();
|
||||
private static final Collection<GLPhantomReference<OpenGLDeletable>> TO_DELETE = new ArrayList<>();
|
||||
private static final ReferenceQueue<OpenGLDeletable> DELETE_QUEUE = new ReferenceQueue<>();
|
||||
|
||||
public synchronized static void register(OpenGLDeletable object) {
|
||||
TO_DELETE.add(object);
|
||||
}
|
||||
|
||||
public synchronized static void deleteAllObjects() {
|
||||
TO_DELETE.forEach(OpenGLDeletable::delete);
|
||||
TO_DELETE.clear();
|
||||
public synchronized static void register(OpenGLDeletable object, IntConsumer glDeleter) {
|
||||
GLPhantomReference<OpenGLDeletable> glRef =
|
||||
new GLPhantomReference<>(object, DELETE_QUEUE, object.getHandle(), glDeleter);
|
||||
TO_DELETE.add(glRef);
|
||||
}
|
||||
|
||||
public static void deleteAllObjects() {
|
||||
for (GLPhantomReference<OpenGLDeletable> glRef
|
||||
: TO_DELETE
|
||||
) {
|
||||
glRef.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteEnqueuedObjects() {
|
||||
while (true) {
|
||||
GLPhantomReference<?> glRef;
|
||||
glRef = (GLPhantomReference<?>) DELETE_QUEUE.poll();
|
||||
if (glRef == null) {
|
||||
break;
|
||||
} else {
|
||||
glRef.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GLPhantomReference<T> extends PhantomReference<T> {
|
||||
|
||||
private final int referentGLhandle;
|
||||
private final IntConsumer GLDeleter;
|
||||
|
||||
/**
|
||||
* Creates a new phantom reference that refers to the given object and
|
||||
* is registered with the given queue.
|
||||
*
|
||||
* <p> It is possible to create a phantom reference with a {@code null}
|
||||
* queue, but such a reference is completely useless: Its {@code get}
|
||||
* method will always return {@code null} and, since it does not have a queue,
|
||||
* it will never be enqueued.
|
||||
*
|
||||
* @param referent the object the new phantom reference will refer to
|
||||
* @param q the queue with which the reference is to be registered,
|
||||
* or {@code null} if registration is not required
|
||||
*/
|
||||
public GLPhantomReference(T referent,
|
||||
ReferenceQueue<? super T> q,
|
||||
int referentGLhandle,
|
||||
IntConsumer GLDeleter) {
|
||||
super(referent, q);
|
||||
this.referentGLhandle = referentGLhandle;
|
||||
this.GLDeleter = GLDeleter;
|
||||
}
|
||||
|
||||
public int getHandle() {
|
||||
return referentGLhandle;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GLDeleter.accept(referentGLhandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||
|
||||
public class VertexBufferObject implements OpenGLDeletable {
|
||||
@ -47,7 +48,7 @@ public class VertexBufferObject implements OpenGLDeletable {
|
||||
|
||||
public VertexBufferObject(Usage usage) {
|
||||
handle = glGenBuffers();
|
||||
OpenGLObjectTracker.register(this);
|
||||
OpenGLObjectTracker.register(this, GL20::glDeleteBuffers);
|
||||
|
||||
this.usage = usage;
|
||||
}
|
||||
@ -194,10 +195,4 @@ public class VertexBufferObject implements OpenGLDeletable {
|
||||
public int getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
glDeleteBuffers(handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package ru.windcorp.progressia.client.graphics.backend.shaders;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
|
||||
@ -32,7 +33,7 @@ public class Program implements OpenGLDeletable {
|
||||
|
||||
public Program(Shader vertexShader, Shader fragmentShader) {
|
||||
handle = glCreateProgram();
|
||||
OpenGLObjectTracker.register(this);
|
||||
OpenGLObjectTracker.register(this, GL20::glDeleteProgram);
|
||||
|
||||
glAttachShader(handle, vertexShader.getHandle());
|
||||
glAttachShader(handle, fragmentShader.getHandle());
|
||||
@ -57,8 +58,6 @@ public class Program implements OpenGLDeletable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
glDeleteProgram(handle);
|
||||
}
|
||||
public int getHandle() { return handle; }
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||
import ru.windcorp.progressia.common.resource.Resource;
|
||||
@ -69,7 +70,7 @@ public class Shader implements OpenGLDeletable {
|
||||
|
||||
public Shader(ShaderType type, String source) {
|
||||
handle = glCreateShader(type.getGlCode());
|
||||
OpenGLObjectTracker.register(this);
|
||||
OpenGLObjectTracker.register(this, GL20::glDeleteShader);
|
||||
|
||||
this.type = type;
|
||||
|
||||
@ -90,11 +91,6 @@ public class Shader implements OpenGLDeletable {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
glDeleteShader(handle);
|
||||
}
|
||||
|
||||
public int getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
@ -87,7 +88,7 @@ public class TexturePrimitive implements OpenGLDeletable {
|
||||
if (isLoaded()) return;
|
||||
|
||||
handle = pixels.load();
|
||||
OpenGLObjectTracker.register(this);
|
||||
OpenGLObjectTracker.register(this, GL11::glDeleteTextures);
|
||||
|
||||
if (handle < 0) {
|
||||
CrashReports.report(null, "Failed to allocate texture");
|
||||
@ -95,9 +96,7 @@ public class TexturePrimitive implements OpenGLDeletable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (isLoaded())
|
||||
glDeleteTextures(handle);
|
||||
public int getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user