143 lines
3.4 KiB
C
143 lines
3.4 KiB
C
#define GLAD_GL_IMPLEMENTATION
|
|
#include"gl.h"
|
|
|
|
#include<assert.h>
|
|
#include<GLFW/glfw3.h>
|
|
|
|
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();
|
|
}
|
|
}
|