Good thinking. It seems like I am actually getting error code 0x502 which is GL_INVALID_OPERATION when drawing this shape. I tried to create a minimal working example but I don’t really know what I am doing wrong at this point. Been doing trial and error the last 2 days without luck. Here’s the code in it’s entirety:
It works perfectly without the geometry shader but with it I get error 0x502. How would I go about hunting this down? Could it somehow be that geometry shaders are not supported on my GPU or something similarly silly?
OpenGL 4.1, latest glbinding and glfw
#include <iostream>
#define GLFW_INCLUDE_NONE
#include <glbinding/gl/gl.h>
#include <glbinding/Binding.h>
#define GLFW_DLL
#include <GLFW/glfw3.h>
using namespace gl;
void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s
", description);
}
void create_program(GLuint &handle, GLuint *shaders) {
handle = glCreateProgram();
for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
glAttachShader(handle, shaders[i]);
}
glLinkProgram(handle);
// clean up after successful linking
for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
glDetachShader(handle, shaders[i]);
}
}
// Comment to toggle geometry shader
#define GEOMETRY_SHADER
#ifdef GEOMETRY_SHADER
#define NUM_SHADERS 3
#else
#define NUM_SHADERS 2
#endif
// Globals
GLuint prog;
GLuint vbo[1];
GLuint vao; // not needed?
GLuint shaders[NUM_SHADERS];
// Vertex shader
const char* vert = R"glsl(
#version 410
layout (location = 0) in vec2 in_position;
out gs_PerVertex {
vec4 color;
} vs_out;
//uniform mat4 MVP;
void main() {
gl_Position = vec4(in_position.x, in_position.y, 0.0f, 1.0f);
// vs_out.color = vec4(1.0f); // white
}
)glsl";
// Geometry shader
const char* geom = R"glsl(
#version 410
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
// Input block
in gs_PerVertex {
vec4 color;
} gs_in[];
// Output block
out gs_PerVertex {
vec4 color;
} gs_out;
void main() {
for (int i = 0; i < 3; ++i) {
gl_Position = gl_in[i].gl_Position + vec4(0.3);
// gs_out.color = gs_in[i].color;
EmitVertex();
}
EndPrimitive();
}
)glsl";
// Fragment shader
const char* frag = R"glsl(
#version 410
in gs_PerVertex {
vec4 color;
} gs_in;
// in vec4 color;
out vec4 out_color;
void main() {
// out_color = gs_in.color;
out_color = vec4(1.0f);
}
)glsl";
void compile_info(const GLuint shader) {
GLint status(0);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (1 != status) {
GLint maxLength(0);
GLint logLength(0);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
GLchar log[maxLength];
glGetShaderInfoLog(shader, maxLength, &logLength, log);
fprintf(stderr, "Compiling shader %u failed: %s", shader, log);
}
}
void create_shader(GLuint &shader, GLenum type, const char* src) {
shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
// check for errors
compile_info(shader);
}
void link_info(const GLuint program) {
GLint status(0);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (1 != status) {
GLint maxLength(0);
GLint logLength(0);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
GLchar log[maxLength];
glGetProgramInfoLog(program, maxLength, &logLength, log);
fprintf(stderr, "Linking of program failed: %s
", log);
}
}
void create_program(GLuint &_p, GLint *_s) {
_p = glCreateProgram();
if(_p == 0)
fprintf(stderr, "Could not create shader program.
");
for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
glAttachShader(_p, _s[i]);
}
glLinkProgram(_p);
// Check for errors.
link_info(_p);
// Clean up.
for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
glDetachShader(_p, _s[i]);
}
}
/// Check for errors. Poll gl for all error messages and print to
/// stderr.
// TODO convert these messages to strings (with glfw?)
void check_errors() {
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "OpenGl encountered an error with code: %d
", err);
}
}
struct Point2D {
float x, y;
};
const Point2D vertices_data[] = {
{-0.5, -0.5},
{0.5, -0.5},
{-0.5, 0.5},
{-0.5, 0.5},
{0.5, -0.5},
{0.5, 0.5}
};
int init_resources() {
// Generate shader and shader program handles
#ifdef GEOMETRY_SHADER
create_shader(shaders[0], GL_VERTEX_SHADER, vert);
create_shader(shaders[1], GL_GEOMETRY_SHADER, geom);
create_shader(shaders[2], GL_FRAGMENT_SHADER, frag);
#else
create_shader(shaders[0], GL_VERTEX_SHADER, vert);
create_shader(shaders[1], GL_FRAGMENT_SHADER, frag);
#endif
create_program(prog, shaders);
GLint a_pos = glGetAttribLocation(prog, "in_position");
if (a_pos == -1) {
fprintf(stderr, "Could not find attribute in shader.");
}
glGenBuffers(1, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(/*index:*/a_pos, /*size:*/2, /*type:*/GL_FLOAT, /*norm:*/GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBindVertexArray(0);
check_errors();
return 1;
}
void draw_scene() {
glBindVertexArray(vao);
glUseProgram(prog);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glBindVertexArray(0);
check_errors();
}
void free_resources() {
glDeleteProgram(prog);
}
int main(int argc, const char * argv[]) {
GLFWwindow *window;
int width, height;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
return -1;
glfwDefaultWindowHints(); // ?
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
glfwWindowHint(GLFW_RESIZABLE, false);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); // ?
window = glfwCreateWindow(640, 480, "Hello", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwGetFramebufferSize(window, &width, &height);
glfwMakeContextCurrent(window);
glbinding::Binding::initialize(false);
init_resources();
// Just draw once to check for errors
draw_scene();
glfwSwapBuffers(window);
// Main loop
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
// draw_scene();
// glfwSwapBuffers(window);
}
// Clean up.
free_resources();
glUseProgram(0);
glDisableVertexAttribArray(0);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}