Created
March 17, 2019 09:30
-
-
Save McJty/69a7130ce54caf765434c3af865d1b1a to your computer and use it in GitHub Desktop.
LWJGL crash in glfwTerminate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 | |
out vec4 fragColor; | |
void main() | |
{ | |
fragColor = vec4(0.0, 0.5, 0.5, 1.0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 | |
layout (location=0) in vec3 position; | |
void main() | |
{ | |
gl_Position = vec4(position, 1.0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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