#define GLAD_GL_IMPLEMENTATION #include"gl.h" #include #include void debug_callback(GLenum src, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *msg, const void *ud) { puts(msg); } int main() { assert(glfwInit() && "Failed to initialize glfw"); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); glfwWindowHint(GLFW_CONTEXT_DEBUG, GLFW_TRUE); GLFWwindow *window = glfwCreateWindow(512, 512, "OpenGL Test", NULL, NULL); assert(window && "Failed to create window"); glfwMakeContextCurrent(window); assert(gladLoadGL(glfwGetProcAddress) && "Failed to load GL"); glDebugMessageCallback(debug_callback, NULL); glEnable(GL_DEBUG_OUTPUT); #if TEST == 0 // Fixed-function lighting cannot be enabled without crashing glEnable(GL_LIGHTING); #elif TEST == 1 // Fixed-function lighting cannot be disabled without crashing // even though it's already disabled by default glDisable(GL_LIGHTING); #elif TEST == 2 || TEST == 3 || TEST == 4 // Expected result: draw a white triangle // (TEST == 2) // dFdx in a shader works // (TEST == 3) // dFdy in a shader will cause a crash in its draw call, even if // the return value is unused // (TEST == 4) // Any GLSL image function will also cause a crash in its draw call, // even if the return value is unused. Here I try imageLoad. int status; GLuint vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &(const char*) { "#version 430\n" "\n" "const vec4 positions[3] = vec4[3] (vec4(-1, -1, 0, 1), vec4(3, -1, 0, 1), vec4(-1, 3, 0, 1));\n" "\n" "out vec4 v_pos;\n" "\n" "void main() {\n" " v_pos = positions[gl_VertexID];\n" " gl_Position = v_pos;\n" "}\n" }, (GLuint[]) {-1}); glCompileShader(vs); glGetShaderiv(vs, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, (const char*[]) { "#version 430\n" "\n" "in vec4 v_pos;\n" "\n" "layout(r32ui, binding = 0) uniform uimage2D imgtest;\n" "\n" "void main() {\n" #if TEST == 2 " dFdx(v_pos);\n" #elif TEST == 3 " dFdy(v_pos);\n" #elif TEST == 4 " imageLoad(imgtest, ivec2(0, 0));\n" #endif " \n" " gl_FragColor = vec4(1, 1, 1, 1);\n" "}\n" }, (GLuint[]) {-1}); glCompileShader(fs); glGetShaderiv(fs, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); GLuint program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); assert(status == GL_TRUE); GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glUseProgram(program); #if TEST == 4 GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 128, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); #endif // Here is where each crash happens (except for TEST == 2, because // dFdx works just fine). glDrawArrays(GL_TRIANGLES, 0, 3); #else #error No such test. #endif glfwSwapBuffers(window); while(!glfwWindowShouldClose(window)) { glfwPollEvents(); } }