3

I'm using OpenGL 4.2 and I can't figure out why I'm getting a GL_INVALID_VALUE error in this program. I get an error when I call glBindAttribLocation. According to the OpenGL 4 reference page, there are only two reasons why GL_INVALID_VALUE should be generated from glBindAttribLocation.

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);

  1. INVALID_VALUE is generated if index is equal or greater than MAX_VERTEX_ATTRIBS.
  2. INVALID_VALUE is generated if program is not a value generated by OpenGL.

As you can see from the program below, condition 1 is not set since index is 20 and GL_MAX_VERTEX_ATTRIBS is 34921. Condition 2 is not met because program is generated by OpenGL using glCreateProgram(). So how could I possibly get a GL_INVALID_VALUE error?

// test.cpp
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("Test");
    glewInit();

    std::cout << "Max Vertex Attributes : " << GL_MAX_VERTEX_ATTRIBS << std::endl;
    // create program
    GLuint program = glCreateProgram();
    if ( program == 0 )
        std::cout << "Program error" << std::endl;

    // clear existing errors        
    if ( glGetError() != GL_NO_ERROR )
        std::cout << "Pre-existing error" << std::endl;

    // bind attribute location to index 20
    glBindAttribLocation(program, 20U, "DoesNotExist");

    // why is this generating an INVALID_VALUE error?
    if ( glGetError() == GL_INVALID_VALUE )
        std::cout << "Invalid value error" << std::endl;

    glDeleteProgram(program);
    return 0;
}

Terminal output

$ g++ test.cpp -lGLEW -lglut
$ ./a.out 
Max Vertex Attributes : 34921
Invalid value error

Also to verify OpenGL 4.2

$ glxinfo | grep OpenGL
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GT 540M/PCIe/SSE2
OpenGL version string: 4.2.0 NVIDIA 304.64
OpenGL shading language version string: 4.20 NVIDIA via Cg compiler
OpenGL extensions:

Note : According to the reference page. "glBindAttribLocation can be called before any vertex shader objects are bound to the specified program object. It is also permissible to bind a generic attribute index to an attribute variable name that is never used in a vertex shader." So the fact that no shaders are loaded and DoesNotExist doesn't exist aren't the problem.

jodag
  • 19,885
  • 5
  • 47
  • 66
  • might be a driver bug but why are you doing this? I don't see any point... also with 4.2 you have explicit attribute location. – yngccc Sep 29 '13 at 01:11
  • This is just a dummy program to replicate a bug in a much larger program. I'm aware that in 4.2 I can define my attribute locations in my shader but I've structured my program in such a way that binding the locations is optimal. Also this is repeatable on my other machine running OpenGL 4.2 with a Nvidia 560 GTX. I'll try updating the drivers – jodag Sep 29 '13 at 01:17

1 Answers1

10

This is the second time I can recall this question being asked in a couple of months now. The last time this was asked, though it is not immediately apparent that this is the same question, was here.

What it boils down to is this: GL_MAX_VERTEX_ATTRIBS as the compiler sees it is a pre-processor token that defines an ID that you can use to ask the OpenGL driver its implementation-defined limit at run-time. When you attempt to print this value directly the only thing you are doing is printing the universal ID that all OpenGL implementations use to query this particular limit.

To get the actual implementation-dependent limit, you need to do this at run-time:

int max_attribs;
glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &max_attribs);

Incidentally, OpenGL implementations are only required to provide a minimum of 16 per-vertex attributes; most only give you the minimum, which explains why 20 is out-of-bounds.

Community
  • 1
  • 1
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Wonderful! I tested and you're right, GL_MAX_VERTEX_ATTRIBS is actually 16. – jodag Sep 29 '13 at 01:20
  • 1
    Now comes the hard part: are you really using 20 per-vertex attributes? :) If so you will need to figure out ways to drastically simplify your vertex data structure. Note that things like `mat4` take up 4 vertex attrib slots. – Andon M. Coleman Sep 29 '13 at 01:21
  • Haha, I won't need 20 per-vertex attributes, part of the reason is I'm using a single VBO with multiple programs with different vertex shaders. No single vertex shader has more than 4 vertex attributes. – jodag Sep 29 '13 at 01:23
  • Oops I meant single VAO not VBO – jodag Sep 29 '13 at 01:45
  • The code snippet above returns a very large number for me (likely what happens for an attribute that is not always set). My guess is that GL_MAX_VERTEX_ATTRIBS is not always set on all platforms. –  Aug 16 '16 at 05:43
  • I'd guess that you don't have an active render context when you make this call and it has no effect, leaving the value you queried uninitialized. Render contexts use thread-local storage, so not only do you need an active one, it needs to be active in the calling thread. – Andon M. Coleman Aug 16 '16 at 09:28