View Full Version : glMultiDrawElements problem accessing buffer object

01-04-2013, 04:42 AM
I am trying to call a vertex array, placed into a buffer object, using glMultiDrawElements(). The (short) program is attached. If I use glDrawElements() instead, the program runs fine. However, the (I think) equivalent glMultiDrawElements() statement compiles/links ok but bombs on execution with an access error. Both statements are at the bottom of the drawing routine.

I would really appreciate if someone is kind enough look at the code and tell me what is wrong.


01-04-2013, 06:19 AM
glMultiDrawElements(GL_QUADS, count, GL_UNSIGNED_BYTE, (const void **)BUFFER_OFFSET(0), 6);

Look at the function and think about what the GL tries to do when you specify 6 sets of primitives like you do above.

Your array of vertex counts is ok, its size matches the number specified for primcount. However, since you're trying to access an element buffer six times, you also need 6 offsets. In particular, you need a pointer to an array of offsets and what you do above is pass a pointer to an address that you yourself defined, i.e. BUFFER_OFFSET(0). I assume BUFFER_OFFSET(x) expands to (void*)(x) so what you do above is the following: (const void**)((void *)0). You're simply passing a null pointer and you know that thou shall never use the null pointer!

This is rigth way to do it:

// stuff you already defined goes here ...

void* offsets[6] = {BUFFER_OFFSET(0)};
glMultiDrawElements(GL_QUADS, count, GL_UNSIGNED_BYTE, offsets, 6);

What this does is merely create an array of six 0-offsets which the GL can iterate over. offsets has a valid address and thus access violations are not going to happen - unless the index offsets stored in the array are causing such violations. However, an offset of 0 is probably safe in 99% of all cases - so don't worry.

However, you'll see that this is nothing more than instancing, i.e. drawing multiple objects from the same dataset. If you want to do real hardware instancing, you should go for GL 3.1 or higher and use glDrawElementsInstanced (http://www.opengl.org/wiki/GLAPI/glDrawElementsInstanced). However, you need to turn your quads into triangles first.

01-04-2013, 12:13 PM
Thanks much, Thokra, for looking at it. Still have a problem though. I pasted in your code and get the error messages below (I am in a Win7/VC++ 2010 environment). Seems to be a type mismatch issue.

1>f:\work1\graphics\bookstuff\active\ed2\testbed\squ are\square.cpp(78): error C2664: 'void (GLenum,const GLsizei *,GLenum,const GLvoid **,GLsizei)' : cannot convert parameter 4 from 'void *[6]' to 'const GLvoid **'
1> Conversion loses qualifiers
1>f:\work1\graphics\bookstuff\active\ed2\testbed\squ are\square.cpp(78): error C2664: 'void (GLenum,const GLsizei *,GLenum,const GLvoid **,GLsizei)' : cannot convert parameter 2 from 'int' to 'const GLsizei *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

01-05-2013, 02:26 AM
Well the first one was my fault. The solution is already told by the compiler: declare the array of void pointers const. Alternatively, you could cast the point to a const void**. The former is preferable. With the second error you made a mistake. You must have either entered a constant or a variable of type int. What you need is a const array to primcount element counts, i.e. const GLsizei count[primcount].

01-05-2013, 11:36 AM
Perfect! Thanks again, Thokra.