31

I'm trying to put together a very basic OpenGL 3.2 (core profile) application. In the following code, which is supposed to create a VBO containing the vertex positions for a triangle, the call to glVertexAttribPointer fails and raises the OpenGL error GL_INVALID_OPERATION. What does this mean, and how might I go about fixing it?

GLuint vbo, attribLocation = glGetAttribLocation(...);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLfloat vertices[] = { 0, 1, 0, 1, 0, 0, -1, 0, 0 };
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(attribLocation);
// At this point, glGetError() returns GL_NO_ERROR.
glVertexAttribPointer(attribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
// At this point, glGetError() returns GL_INVALID_OPERATION.
  • is this all inside of the same function? – Syntactic Fructose Nov 15 '12 at 18:43
  • Yes. I'll refactor it when it actually works :P –  Nov 15 '12 at 18:47
  • Are you sure that the `GL_INVALID_OPERATION` error is coming from `glVertexAttribPointer`? Remember: OpenGL stores the errors and returns them only when you call `glGetError`. So if you're not regularly [purging the error queue](http://www.opengl.org/wiki/FAQ#glGetError_.28or_.22How_do_I_check_for_GL_errors.3F.29), you may be getting older errors. – Nicol Bolas Nov 15 '12 at 19:02
  • It's definitely coming from glVertexAttribPointer - when I move the error check up to the line above no error is reported. –  Nov 15 '12 at 19:05
  • @robinjam: Please add the specific error checking code to the question, both the latest point where there is you see the error and the earliest point where the error appears. Because I think your error is coming from `glEnableVertexAttribArray`. – Nicol Bolas Nov 15 '12 at 19:25
  • At the moment, my "error checking" consists of moving `cout << glGetError() << endl;` around until I find the source of the error (I was planning to refactor once I get the basic demo done). I've added comments to the original question to show exactly where the error shows up. –  Nov 15 '12 at 19:33
  • @robinjam: Are you sure you're getting GL_INVALID_OPERATION? *Exactly* what enumeration value are you getting? The actual number, not the OpenGL thing. Also, can you provide an [SSCCE](sscce.org)? – Nicol Bolas Nov 15 '12 at 19:35
  • The exact return value from `glGetError()` is 1282. The code is so short at the moment that I may as well upload it to GitHub - give me a few minutes and I'll do so. –  Nov 15 '12 at 19:38

1 Answers1

60

First, let's get some preliminaries out of the way:

glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

Stop doing this. You already asked for a core OpenGL context. You don't need forward compatibility, and it does nothing for you. This was an old flag when 3.0 had deprecated things but didn't remove them. You don't need it.

That's not causing your problem, though. This is:

glEnableVertexAttribArray(program.getAttrib("in_Position"));
// A call to getGLError() at this point prints nothing.
glVertexAttribPointer(program.getAttrib("in_Position"), 3, GL_FLOAT, GL_FALSE, 0, 0);
// A call to getGLError() at this point prints "OpenGL error 1282".

First, there's an obvious driver bug here, because glEnableVertexAttribArray should also have issued a GL_INVALID_OPERATION error. Or you made a mistake when you checked it.

Why should both functions error? Because you didn't use a Vertex Array Object. glEnableVertexAttribArray sets state in the current VAO. There is no current VAO, so... error. Same goes for glVertexAttribPointer. It's even in the list of errors for both on those pages.

You don't need a VAO in a compatibility context, but you do in a core context. Which you asked for. So... you need one:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

Put that somewhere in your setup and your program will work.

Nicol Bolas
  • 378,677
  • 53
  • 635
  • 829
  • 2
    Thank you very much for your help. I'm still not getting any output on the screen, but at least I'm not getting any errors now! –  Nov 15 '12 at 20:30
  • 6
    With regards to the `glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);` statement - this project needs to support multiple platforms, and according to the [GLFW documentation](http://www.glfw.org/faq.html#4_2), OS X only gives you a core context if you ask for a forward-compatible one. –  Nov 15 '12 at 20:34
  • @robinjam: That sounds like a bug in GLFW to me. – Nicol Bolas Nov 15 '12 at 21:10
  • 1
    +1 I don't know how it worked in OpenGL 3.3 (which I've been using previously) but that was it - I never generated and bound the vertex array object. Thanks, Nicol! – Piotr Justyna Mar 07 '13 at 13:40
  • *Previously, I've been using AMD drivers. Now it's Nvidia and OpenGL 4.3 core profile – Piotr Justyna Mar 07 '13 at 16:39
  • 1
    The `GLFW_OPENGL_FORWARD_COMPAT` hint is needed on OS X. I keep getting this in output: `65543: NSGL: The targeted version of OS X only supports OpenGL 3.2 and later versions if they are forward-compatible` – Sri Harsha Chilakapati Dec 11 '14 at 14:36
  • 1
    The line mentioning to stop using `GLFW_OPENGL_FORWARD_COMPAT` should be removed from this answer, as it is clearly necessary for OpenGL 3.2 core profile support on macOS, as stated both in GLFW documentation and the official OpenGL documentation's API caveats. – galexite Oct 21 '20 at 11:28
  • A note to my future self when I see this question for the 110th time: a similar code works with OpenGL v3.1, but fails with the same error as OP (even after defining a VAO) on OpenGL v4.0. This note to my future self is probably good enough for now, but anybody has any thoughts why that's the case? – Maghoumi Apr 07 '21 at 19:38