PDA

View Full Version : glMultiDrawElements() causing an access violation



Garanixx
03-24-2011, 12:59 PM
Hello everyone,

I have a problem with glMultiDrawElements() that I am unable to resolve. I am testing code as I read the red book. My code is as follows:



static GLint vertices[] = {-250, 0, 0,
0, 250, 0,
250, 0, 0,
0, -250, 0,
-400, -300, 0,
0, -300, 0,
0, -450, 0,
-400, -450, 0};

static GLfloat colors[] = {0.0, 1.0, 1.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0};

static GLint edges[] = {1, 1, 1, 1, 1, 1, 1, 1};

glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_INT, 0, vertices);
glEdgeFlagPointer(0, edges);

static GLubyte ind1[] = {0, 1, 2, 3};
static GLubyte ind2[] = {4, 5, 6, 7};
static GLsizei count[] = {4, 4};
static const GLvoid * indices[] = {ind1, ind2};

glMultiDrawElements(GL_LINE_STRIP, count, GL_UNSIGNED_BYTE, indices, 2);


In constrast to the example in the book, I had to change the definition of the indices array from just "static" to "static const", because the drawing function would not accept it otherwise, since it demands an argument of type "const GLvoid **" and not just "GLvoid **". My change makes the code compile, but it always spits out an access violation. I set up some breakpoints with a debugger and checked the pointer values of indices. They both point correctly to the respective ind1 and ind2 arrays.

Using glDrawElements() in a loop instead works fine for me, but this I simply cannot figure this out. I found another thread on this but the person didn't describe how they solved the problem in the end, so any help would be appreciated :)

If it helps, I am using OpenGL version 3.0 and Visual Studio 2010 as my compiler.

V-man
03-24-2011, 04:35 PM
What does glGetError() say?
Put some glGetError() after every GL function call.

mbentrup
03-25-2011, 12:12 AM
Are you sure that glMultiDrawElements is not NULL ?

Usually you have to get the address of extension functions with wglGetProcAddress (see http://msdn.microsoft.com/en-us/library/ms537568(v=vs.85).aspx).

Garanixx
03-25-2011, 07:13 AM
Are you sure that glMultiDrawElements is not NULL ?

Usually you have to get the address of extension functions with wglGetProcAddress (see http://msdn.microsoft.com/en-us/library/ms537568(v=vs.85).aspx).


Ah, I am sorry I forgot to mention that I am also using both GLEW(and GLUT), so it should be handling that for me. Every other function has worked fine for me thus far.


What does glGetError() say?
Put some glGetError() after every GL function call.

I put some glGetError() after every gl function call as you suggested. Everything else prior to the access violation point came out clean, except the main function keeps constantly generating error code 1282(invalid operation) for some reason.

If you take a look at the code below, I can literally just put several glGetError() calls one after the other and each one of them generates 1282 without any gl function calls inbetween. The errors appear to stop after the init() function is executed. Past that point no further errors are generated.. Strange :\



void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT, GL_LINE);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_EDGE_FLAG_ARRAY);
}



int main(int argc, char** argv)
{
err = glGetError();
err = glGetError();
err = glGetError(); //These ALL generate errors, even with nothing inbetween
err = glGetError();
err = glGetError();
err = glGetError();
err = glGetError();
glutInit(&argc, argv);
err = glGetError();
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
err = glGetError();
glutInitWindowSize(1024, 768);
err = glGetError();
glutInitWindowPosition(0,0);
err = glGetError();
glutInitContextVersion(3, 0);
err = glGetError();
//glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutCreateWindow("NOM");
err = glGetError();

init(); //Errors stop here for some reason

glutDisplayFunc(display);
err = glGetError();
glutReshapeFunc(reshape);
err = glGetError();
glutMouseFunc(mouse);
err = glGetError();
glutMainLoop();
return 0;
}


Once again, thank you for your help. I'm really stumped about this. :(

_arts_
03-25-2011, 07:33 AM
Don't glGetError before your OpenGL context has been initialized (so not before glutInit).

V-man
03-25-2011, 08:32 AM
Hmmm, my doc says that glEdgeFlagPointer takes 1 for the first parameter.

Let's look at the specification to see when glMultiDrawElements was introduced : http://www.opengl.org/documentation/specs/

It looks like GL glspec14.pdf.
Make sure you have GL 1.4

Garanixx
03-25-2011, 09:31 AM
Don't glGetError before your OpenGL context has been initialized (so not before glutInit).

Oops! Thank you for pointing that out! Well, aside from that there were no errors to speak of. I literally placed the error call after every gl function.


Hmmm, my doc says that glEdgeFlagPointer takes 1 for the first parameter.

Let's look at the specification to see when glMultiDrawElements was introduced : http://www.opengl.org/documentation/specs/

It looks like GL glspec14.pdf.
Make sure you have GL 1.4

You were right about the edgeflagpointer argument. An oversight on my part, I changed it to 1, even tried commenting the whole thing out, and disabling the corresponding array. Still no dice.

As for the version, I am using OpenGL 3.0(gl3.h) and on the man page http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawElements.xml it says that I need version 1.4 or greater for it to be available. Do you mean I actually need to install a separate header for version 1.4 even though I have 3.0?

In case it helps, here is a list of all my includes:



#include "gl\glew.h"
#include "gl\wglew.h"
#include "gl\freeglut.h"
#include "gl3\gl3.h"
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
#include <sstream>
#include <string>



Thank you for your continued responses, I appreciate it greatly! :)

EDIT: I think what mbentrup said earlier may be true.. I don't know why I didn't see this earlier, but the address of the access violation is 0x00000000 which means there must be a null pointer somewhere.. But the pointers in my indices pointer array are both pointing correctly to the 2 arrays.. Could this by any chance be a problem with GLEW somehow? Maybe the function address not being retrieved correctly?

V-man
03-25-2011, 12:02 PM
gl3.h is just a header file and a header file just defines functions and tokens.

What I am saying is that your GL driver and video card must support GL 1.4 at mininum, otherwise you should give and Message such as "Sorry, you need to update your video driver or perhaps buy a new ...".

So check the GL version
http://www.opengl.org/wiki/FAQ#How_do_I_tell_what_version_of_OpenGL_I.27m_usi ng.3F

Garanixx
03-25-2011, 12:24 PM
gl3.h is just a header file and a header file just defines functions and tokens.

What I am saying is that your GL driver and video card must support GL 1.4 at mininum, otherwise you should give and Message such as "Sorry, you need to update your video driver or perhaps buy a new ...".

So check the GL version
http://www.opengl.org/wiki/FAQ#How_do_I_tell_what_version_of_OpenGL_I.27m_usi ng.3F

Ah! Sorry, the thought never crossed my mind as I use this computer for gaming constantly, so the video card and drivers are up to date.

I have tried doing as you suggest and calling GL_VERSION, and the version number returned is 3.1.

I would also like to add that the same access violation problem is appearing in glGenVertexArrays(). I am using the function as noted in the red book, my usage should be correct:



static GLuint VAO[2];

glGenVertexArrays(2, VAO); //Causes access violation


But the function also causes an access violation in the same manner.. At the address of 0x000000000 :(

EDIT: Is it possible that it could have to do with the compiler(Visual Studio 2010)?

_arts_
03-25-2011, 01:38 PM
Initialize glew, after you got an OpenGL context.

V-man
03-25-2011, 01:43 PM
Yes, if you are using GLEW then you need to call it after you have a context : glutCreateWindow("NOM");

Also, if you are using a forward compatible context you need to set glewExperimental to TRUE

glewExperimental=TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
cout << "glewInit failed, aborting." << endl;
}

GLEW isn't really coded for GL 3.0. They need to update their code.

Garanixx
03-25-2011, 02:04 PM
Thank you very much! That solved the problem completely. I forgot to initialize GLEW.. Funny enough, most functions worked fine despite that fact. :D

If GLEW isn't ideal for OpenGL 3.0, could you recommend me a good alternative? Or do you recommend that I learn how to make the contexts by myself?

Again, thank you for your help!

V-man
03-25-2011, 05:18 PM
GLEW doesn't create a context. It gets function pointers via wglGetProcAddress.

They are planning to fix it in a later update.