Skip to content

Instantly share code, notes, and snippets.

@McJty
Created March 17, 2019 09:30
Show Gist options
  • Save McJty/69a7130ce54caf765434c3af865d1b1a to your computer and use it in GitHub Desktop.
Save McJty/69a7130ce54caf765434c3af865d1b1a to your computer and use it in GitHub Desktop.
LWJGL crash in glfwTerminate
package renderer;
import org.lwjgl.system.MemoryUtil;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.memFree;
public class Buffer {
private final float[] vertices;
private int vaoId;
private int vboId;
public Buffer(float[] vertices) {
this.vertices = vertices;
init();
}
private void init() {
FloatBuffer verticesBuffer = MemoryUtil.memAllocFloat(vertices.length);
verticesBuffer.put(vertices).flip();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
memFree(verticesBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (verticesBuffer != null) {
MemoryUtil.memFree(verticesBuffer);
}
}
public void destroy() {
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(vboId);
glBindVertexArray(0);
glDeleteVertexArrays(vaoId);
}
public void render(ShaderProgram program) {
program.bind();
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
program.unbind();
}
}
#version 330
out vec4 fragColor;
void main()
{
fragColor = vec4(0.0, 0.5, 0.5, 1.0);
}
package engine;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import renderer.Buffer;
import renderer.ShaderProgram;
import renderer.Window;
import varia.Utils;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
public class GameEngine {
public Window currentWindow;
public static float[] vertices = new float[]{
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
public static ShaderProgram shader;
public static Buffer buffer;
public GameEngine() {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
currentWindow = new Window();
GL.createCapabilities();
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
try {
shader = new ShaderProgram();
shader.createVertexShader(Utils.loadResource("/vertex.vs"));
shader.createFragmentShader(Utils.loadResource("/fragment.fs"));
shader.link();
} catch (Exception e) {
throw new IllegalStateException("Error creating shader");
}
buffer = new Buffer(vertices);
}
public void destroy() {
if (shader != null) {
shader.destroy();
shader = null;
}
if (buffer != null) {
buffer.destroy();
buffer = null;
}
if (currentWindow != null) {
currentWindow.destroy();
currentWindow = null;
}
System.out.println("Renderer.destroy: 1");
System.out.flush();
glfwTerminate(); // <------ MEMORY CORRUPTION HERE!
System.out.println("Renderer.destroy: 2");
System.out.flush();
glfwSetErrorCallback(null).free();
}
private double getTime() {
return System.currentTimeMillis() / 1000.0;
}
private void sync(double loopStartTime) {
float loopSlot = 1f / 50;
double endTime = loopStartTime + loopSlot;
while (getTime() < endTime) {
try {
Thread.sleep(1);
} catch (InterruptedException ie) {
}
}
}
public void loop() {
while (!currentWindow.shouldClose()) {
double loopStartTime = getTime();
glfwPollEvents();
if (currentWindow != null) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
buffer.render(shader);
glfwSwapBuffers(currentWindow.window);
}
sync(loopStartTime);
}
}
}
import engine.GameEngine;
public class Main {
private GameEngine engine;
public void run() {
engine = new GameEngine();
engine.loop();
engine.destroy();
}
public static void main(String[] args) {
new Main().run();
}
}
package renderer;
import static org.lwjgl.opengl.GL20.*;
public class ShaderProgram {
private final int programId;
private int vertexShaderId;
private int fragmentShaderId;
public ShaderProgram() throws Exception {
programId = glCreateProgram();
if (programId == 0) {
throw new Exception("Could not create Shader");
}
}
public void createVertexShader(String shaderCode) throws Exception {
vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
}
public void createFragmentShader(String shaderCode) throws Exception {
fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
}
protected int createShader(String shaderCode, int shaderType) throws Exception {
int shaderId = glCreateShader(shaderType);
if (shaderId == 0) {
throw new Exception("Error creating shader. Type: " + shaderType);
}
glShaderSource(shaderId, shaderCode);
glCompileShader(shaderId);
if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
}
glAttachShader(programId, shaderId);
return shaderId;
}
public void link() throws Exception {
glLinkProgram(programId);
if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
throw new Exception("Error linking Shader code: " + glGetProgramInfoLog(programId, 1024));
}
if (vertexShaderId != 0) {
glDetachShader(programId, vertexShaderId);
}
if (fragmentShaderId != 0) {
glDetachShader(programId, fragmentShaderId);
}
glValidateProgram(programId);
if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
System.err.println("Warning validating Shader code: " + glGetProgramInfoLog(programId, 1024));
}
}
public void bind() {
glUseProgram(programId);
}
public void unbind() {
glUseProgram(0);
}
public void destroy() {
unbind();
if (programId != 0) {
glDeleteProgram(programId);
}
}
}
package varia;
import java.io.InputStream;
import java.util.Scanner;
public class Utils {
public static String loadResource(String fileName) throws Exception {
String result;
try (InputStream in = Class.forName(Utils.class.getName()).getResourceAsStream(fileName);
Scanner scanner = new Scanner(in, "UTF-8")) {
result = scanner.useDelimiter("\\A").next();
}
return result;
}
}
#version 330
layout (location=0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
package renderer;
import org.lwjgl.glfw.GLFWVidMode;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Window {
// The window handle
public long window;
private int width;
private int height;
public Window() {
this.width = 800;
this.height = 600;
window = glfwCreateWindow(width, height, "Game Engine!", NULL, NULL);
if ( window == NULL ) {
throw new RuntimeException("Failed to create the GLFW window");
}
glfwSetFramebufferSizeCallback(window, (w, width, height) -> {
this.width = width;
this.height = height;
});
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE ) {
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
}
});
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(vidmode.width() - width) / 2,
(vidmode.height() - height) / 2
);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
public void destroy() {
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
}
public boolean shouldClose() {
return glfwWindowShouldClose(window);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment