Call to glVertexAttribPointer always fails. after looking up in some other forums, I thought it might be the problem with binding attributes to shader variables. I checked attribute locations in shader program and it correctly maps in_Position to 0 index slot. EnableVertexAttribArray on index slot 0 does not give any error but glVertexAttribPointer fails with GL_INVALID_OPERATION.
It happens to all my OpenGL programs which make use of shaders. Even ones which does not directly use VertexAttribPointer and use old-style VertexPointer call.
Same scenario happens with freeglut sample program, smooth_opengl3, in both Windows and Linux.
GPU: Radeon HD5830
OS: Ubuntu 64-bit 10.04 & Windows 7 32-bit
Driver: Catalyst 10.6
Could you please provide the program? You know the function certainly works for most of the cases, we need more information.
Easiest way to reproduce the error:
1. Download freeglut-2.6.0.tar.gz from http://freeglut.sourceforge.net/ and extract it
2. Open C++ project file from VisualStudio2008Static folder and Build the project
3. Switch startup project to smooth_opengl3 and run it.
4. You will see OpenGL 0x502 error on console output.
5. Tracking down the error you will see it happens at call to VertexAttribPointer.
Hello, I have a very simple application for windows, doing some basic setup of the context, loading, compiling shaders, setting up vertex array objects for a colored square and rendering the scene.
It worked in OpenGL 3.2 context in February with Catalysts 10.2 and 10.3 IIRC, but in 10.7 and 10.8 it's no longer working, failing at glVertexAttribPointer with GL_INVALID_OPERATION.
If I change context to 3.1, it works just fine.
Some simplest example apps demoing OpenGL 3.2 don't work as well.
Creating context:
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
const int nPixelFormat = ::ChoosePixelFormat( _dc, &pfd );
if(nPixelFormat == 0)
return false;const BOOL result = ::SetPixelFormat( _dc, nPixelFormat, &pfd );
if( !result )
return false;
HGLRC tempContext = ::wglCreateContext( _dc );
::wglMakeCurrent( _dc, tempContext );initAPI();
int major, minor;
getGLVersion(&major, &minor);
if(major < 3 || (major == 3 && minor < 2))
{
::MessageBox(NULL, _T("OpenGL 3.2 not supported!"), _T("Error!"), MB_ICONERROR);
return false;
}major = 3;
minor = 2;wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB != NULL)
{
m_hrc = NULL;
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, major,
WGL_CONTEXT_MINOR_VERSION_ARB, minor,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};m_hrc = wglCreateContextAttribsARB(_dc, NULL, attribs);
}
else
{
::MessageBox(NULL, _T("OpenGL 3.x Rendering Context function was not retrieved!"), _T("Error!"), MB_ICONERROR);
::wglMakeCurrent( NULL, NULL );
::wglDeleteContext( tempContext );
return false;
}::wglMakeCurrent( _dc, m_hrc );
assert( ::glGetError() == GL_NO_ERROR );
::wglDeleteContext( tempContext );if (!m_hrc)
{
::MessageBox(NULL, _T("OpenGL 3.x Rendering Context was not created!"), _T("Error!"), MB_ICONERROR);
return false;
}return true;
GLenum err;
m_pProgram = new GLProgram();
m_pVertexShader = new GLShader( VERTEX_SHADER );
m_pFragmentShader = new GLShader( FRAGMENT_SHADER );
bool success;
success = m_pVertexShader->load( "minimal_vs.glsl" );
assert( success );
success = m_pFragmentShader->load( "minimal_fs.glsl" );
assert( success );
success = m_pVertexShader->compile();
assert( success );
success = m_pFragmentShader->compile();
assert( success );
m_pProgram->attachShader( m_pVertexShader );
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->attachShader( m_pFragmentShader );
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->bindAttribLocation( 0, "in_Position" );
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->bindAttribLocation( 1, "in_Color" );
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->bindFragDataLocation( 0, "out_Color" );
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->link();
assert( (err = ::glGetError()) == GL_NO_ERROR );
m_pProgram->use();
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glClearDepth( 1.0f );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glEnable( GL_DEPTH_TEST );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glDepthFunc( GL_LEQUAL );
assert( (err = ::glGetError()) == GL_NO_ERROR );
GLfloat * v = new GLfloat[ 12 ];
GLfloat * c = new GLfloat[ 12 ];
v[0] = -0.8f; v[1] = 0.8f; v[2] = -1.0f;
v[3] = 0.8f; v[4] = 0.8f; v[5] = -1.0f;
v[6] = -0.8f; v[7] = -0.8f; v[8] = -1.0f;
v[9] = 0.8f; v[10] = -0.8f; v[11] = -1.0f;
c[0] = 1.0f; c[1] = 0.0f; c[2] = 0.0f;
c[3] = 0.0f; c[4] = 1.0f; c[5] = 0.0f;
c[6] = 0.0f; c[7] = 0.0f; c[8] = 1.0f;
c[9] = 1.0f; c[10] = 0.0f; c[11] = 1.0f;
::glGenBuffers( 2, &m_vboID[0] );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glEnableVertexAttribArray( 0 );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glBindBuffer( GL_ARRAY_BUFFER, m_vboID[0] );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glBufferData( GL_ARRAY_BUFFER, 12 * sizeof( GLfloat ), v, GL_STATIC_DRAW );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)NULL );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glEnableVertexAttribArray( 1 );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glBindBuffer( GL_ARRAY_BUFFER, m_vboID[1] );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glBufferData( GL_ARRAY_BUFFER, 12 * sizeof( GLfloat ), c, GL_STATIC_DRAW );
assert( (err = ::glGetError()) == GL_NO_ERROR );
::glVertexAttribPointer( (GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, NULL );
assert( (err = ::glGetError()) == GL_NO_ERROR );
delete [] v;
delete [] c;
::glDrawBuffer( GL_BACK_LEFT );
assert( ::glGetError() == GL_NO_ERROR );
Try inserting this after glGenBuffers:
GLuint ArrayObject;
glGenVertexArrays(1, &ArrayObject);
glBindVertexArray(ArrayObject);
From section 2.8 of the GL 3.2 spec:
An INVALID_OPERATION error is generated if any of the *Pointer commands specifying the location and organization of vertex array data are called while zero is bound to the ARRAY_BUFFER buffer object binding point (see section 2.9.6),and the pointer argument is not NULL.
It broke my stuff as well and I thought it was a bug, but apparently it's how forward compatible contexts are supposed to work.
Thanks for the reply! I did read this section in the spec but had absolutely no idea, what to do about it.
Although the spec is exhaustive, it's sometimes difficult to put all the pieces together.
AMD seems a bit to strict with their implementation of the forward compatible context and shader language versions. While it's nice to work with a compliant implementation, it's sometimes a pain.
Thanks for the reply! it works