cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

salehqt
Journeyman III

Vertex attribute binding in GLSL

call to glVertexAttribPointer always fails

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

 

0 Likes
6 Replies
frali
Staff

Could you please provide the program? You know the function certainly works for most of the cases, we need more information.

0 Likes

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. 

 

0 Likes

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.

 

It fails at the first glVertexAttribPointer call already.
Here are relevant parts of the code, nothing special, really.

 

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;

 

 

 

 

 

And setting up the scene:
GLenum err;
//::wglMakeCurrent(dc, m_hrc);
//assert( ::glGetError() == GL_NO_ERROR );

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 );

0 Likes

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.

 



0 Likes

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.



0 Likes

Thanks for the reply! it works

0 Likes