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_DEPTH_TEST);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
RenderTaskQueue.schedule(OpenGLObjectTracker::deleteEnqueuedObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setupWindowCallbacks() {
|
private static void setupWindowCallbacks() {
|
||||||
|
@ -17,29 +17,80 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package ru.windcorp.progressia.client.graphics.backend;
|
package ru.windcorp.progressia.client.graphics.backend;
|
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
/*
|
|
||||||
* FIXME deal with client invocations of .delete() when properly disposing of
|
|
||||||
* objects mid-execution
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class OpenGLObjectTracker {
|
public class OpenGLObjectTracker {
|
||||||
|
|
||||||
public static interface OpenGLDeletable {
|
public interface OpenGLDeletable {
|
||||||
void delete();
|
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) {
|
public synchronized static void register(OpenGLDeletable object, IntConsumer glDeleter) {
|
||||||
TO_DELETE.add(object);
|
GLPhantomReference<OpenGLDeletable> glRef =
|
||||||
|
new GLPhantomReference<>(object, DELETE_QUEUE, object.getHandle(), glDeleter);
|
||||||
|
TO_DELETE.add(glRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static void deleteAllObjects() {
|
public static void deleteAllObjects() {
|
||||||
TO_DELETE.forEach(OpenGLDeletable::delete);
|
for (GLPhantomReference<OpenGLDeletable> glRef
|
||||||
TO_DELETE.clear();
|
: 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 java.nio.*;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
|
||||||
public class VertexBufferObject implements OpenGLDeletable {
|
public class VertexBufferObject implements OpenGLDeletable {
|
||||||
@ -47,7 +48,7 @@ public class VertexBufferObject implements OpenGLDeletable {
|
|||||||
|
|
||||||
public VertexBufferObject(Usage usage) {
|
public VertexBufferObject(Usage usage) {
|
||||||
handle = glGenBuffers();
|
handle = glGenBuffers();
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this, GL20::glDeleteBuffers);
|
||||||
|
|
||||||
this.usage = usage;
|
this.usage = usage;
|
||||||
}
|
}
|
||||||
@ -194,10 +195,4 @@ public class VertexBufferObject implements OpenGLDeletable {
|
|||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return handle;
|
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.GL11.*;
|
||||||
import static org.lwjgl.opengl.GL20.*;
|
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;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
|
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) {
|
public Program(Shader vertexShader, Shader fragmentShader) {
|
||||||
handle = glCreateProgram();
|
handle = glCreateProgram();
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this, GL20::glDeleteProgram);
|
||||||
|
|
||||||
glAttachShader(handle, vertexShader.getHandle());
|
glAttachShader(handle, vertexShader.getHandle());
|
||||||
glAttachShader(handle, fragmentShader.getHandle());
|
glAttachShader(handle, fragmentShader.getHandle());
|
||||||
@ -57,8 +58,6 @@ public class Program implements OpenGLDeletable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public int getHandle() { return handle; }
|
||||||
glDeleteProgram(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import static org.lwjgl.opengl.GL20.*;
|
|||||||
|
|
||||||
import java.util.Locale;
|
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;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
import ru.windcorp.progressia.common.resource.Resource;
|
import ru.windcorp.progressia.common.resource.Resource;
|
||||||
@ -69,7 +70,7 @@ public class Shader implements OpenGLDeletable {
|
|||||||
|
|
||||||
public Shader(ShaderType type, String source) {
|
public Shader(ShaderType type, String source) {
|
||||||
handle = glCreateShader(type.getGlCode());
|
handle = glCreateShader(type.getGlCode());
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this, GL20::glDeleteShader);
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
@ -90,11 +91,6 @@ public class Shader implements OpenGLDeletable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete() {
|
|
||||||
glDeleteShader(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import static org.lwjgl.opengl.GL20.*;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
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;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
@ -87,7 +88,7 @@ public class TexturePrimitive implements OpenGLDeletable {
|
|||||||
if (isLoaded()) return;
|
if (isLoaded()) return;
|
||||||
|
|
||||||
handle = pixels.load();
|
handle = pixels.load();
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this, GL11::glDeleteTextures);
|
||||||
|
|
||||||
if (handle < 0) {
|
if (handle < 0) {
|
||||||
CrashReports.report(null, "Failed to allocate texture");
|
CrashReports.report(null, "Failed to allocate texture");
|
||||||
@ -95,9 +96,7 @@ public class TexturePrimitive implements OpenGLDeletable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public int getHandle() {
|
||||||
if (isLoaded())
|
return handle;
|
||||||
glDeleteTextures(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user