Crash in glDrawElements() using VBOs just after glBufferData()

by Robert Green » Wed, 17 Feb 2010 04:25:38 GMT

Sponsored Links
 ou're probably pointing something to some bad memory location
somewhere. I know you didn't post all of your real code so I can't
really say for sure but it looks to me like you may be doing something
wrong with your buffers. Here's how I do it:

-- Load --
GL11 gl11 = (GL11) gl;
if (modelData.normals != null) {
int[] vboIds = new int[5];
gl11.glGenBuffers(5, vboIds, 0);
vertexVBOId = vboIds[0];
texVBOId = vboIds[1];
normalVBOId = vboIds[2];
indexVBOId = vboIds[3];
lightmapVBOId = vboIds[4];
} else {
int[] vboIds = new int[4];
gl11.glGenBuffers(4, vboIds, 0);
vertexVBOId = vboIds[0];
texVBOId = vboIds[1];
indexVBOId = vboIds[2];
lightmapVBOId = vboIds[3];
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexVBOId);
modelData.vertices.length *
4, BufferUtil.createDirectIntBuffer(modelData.vertices),
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, texVBOId);
modelData.tex.length * 4,
BufferUtil.createDirectIntBuffer(modelData.tex), GL11.GL_STATIC_DRAW);
if (modelData.normals != null) {
modelData.normals.length *
4, BufferUtil.createDirectIntBuffer(modelData.normals),
modelData.indices.length * 2,
if (hasLightMap) {
lightMapModelData.tex.length * 4,
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);

-- Draw --

// use VBOs
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexVBOId);
gl11.glVertexPointer(3, GL10.GL_FIXED, 0, 0);
if (modelData.normals != null) {
gl11.glNormalPointer(GL10.GL_FIXED, 0, 0);
gl11.glTexCoordPointer(2, GL10.GL_FIXED, 0, 0);

Crash in glDrawElements() using VBOs just after glBufferData()

by Viktor Linder » Wed, 17 Feb 2010 04:43:16 GMT

 s you say, the most likely explanation is that I have a bad pointer
being used somewhere. The thing is I have gone over this code a bunch
of times and tried lots of different checks and I just can't find
what's wrong.
Do you have any pointers on ways to debug the crash in the GL library?

I forgot to mention: I bind the array buffer to 0 after the call to
glDrawElements(), so any future draw calls that are not using VBOs
will not break. Also, I am not using VBOs for all draw calls.

You keep a different VBO for each channel; is using a single VBO for
several channels not allowed?

If its possible to use a single buffer that would reduce the needed
calls to glBindBuffer() and allowed interleaved data which would
improve cache locality.

Curious; did using GL_FIXED give a large performance gain?

Thanks for your help.

On 16 Feb, 21:25, Robert Green <> wrote:


Sponsored Links

Crash in glDrawElements() using VBOs just after glBufferData()

by Clankrieger » Wed, 24 Feb 2010 18:01:58 GMT

 s what I am aware of, VBOs do not need direct buffers (and indirect
buffers might be handled faster), but this is just a detail. I also
tried GL_FIXED but it did not make much difference for me. I assume
that it gives performance gains only if you have a) static data that
is converted to fixed format once and then re-rendered or b) do all
calculations with fixed number precision (which is making things a lot
more complicated and less readable when you need to update data). So I
switched back to Float because I hat to convert most values to fixed
before uploading them in GL calls.

I wonder if your offsets are correct? Is _pos_size_bytes the correct
offset? For safety, I would stick to non-interleaved arrays for
testing. Also I'm not sure when to array-copying in the bufferdata
call takes place - have you tried a glFlush call or a buffer rebind
(bind VBO to 0 and the ID again) after all the buffering? Somebody
with knowledge about the native part of of this buffering could help
you better with this, I guess.


On Feb 16, 8:43pm, Viktor Linder <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Robert Green » Thu, 25 Feb 2010 06:50:21 GMT

 he OpenGL wrappers take the data pointer passed in by those sorts of
methods using native GetDirectBufferAddress of the corresponding type
(int or float) and pass that pointer into the native gl method. That
only works correctly if it's a direct buffer.

I just checked android_opengl_GLES10.cpp and GLES11.cpp and found that
glTexImage2D and glBufferData use the same getPointer() method to get
to the data. That means that behavior should be the same.
Ultimately, the data comes from:

*array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
getBaseArrayID, buffer);
offset = _env->CallStaticIntMethod(nioAccessClass,
getBaseArrayOffsetID, buffer);
data = _env->GetPrimitiveArrayCritical(*array, (jboolean *)
return (void *) ((char *) data + offset);

then the gl method is called, then the pointer is released.

Always use direct buffers when working with any aspect of OpenGL on

On Feb 24, 4:01am, Clankrieger <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Twisted Ware » Thu, 25 Feb 2010 16:45:32 GMT

 obert has a very good point, but I also think you can expect the GL
implementation to allow the buffers to get garbage collected before
they have been used.

You allocate the buffer in a scope and then pass that buffer pointer
into the GL system - and then toss the memory away. Unless you flush
the GL queue, there is no guarantee the graphics system has done
anything with the data you've passed. The point of the direct buffers
is to prevent copying data around all the time during these calls, so
the GL system could be using the memory directly much later than you
expect. You should probably not deallocate the buffer until the next
frame comes around, when you know the system is done with the data.

On Feb 24, 2:50pm, Robert Green <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Bob Kerns » Fri, 26 Feb 2010 01:30:31 GMT

 his would be a bug in the JNI code, which is responsible for
protecting from the GC any and all memory which it is using. Only it
can do so, because only it knows when it is done.

That's unlikely, though. The the JNI API makes it impossible to get
your JNI code to get its hands on the data without protecting it from
the GC -- and even then, you may only get a copy, if the system feels
like doing that instead. Bugs ARE still possible -- you can free it an
then hang onto the data you no longer have rights to.

But really, the only impact of holding onto a buffer on the Java side,
only to discard it next frame, is to make the GC work harder. If you
were to REUSE that buffer, however, you'd avoiding extra GC work.

On Feb 25, 12:45am, Twisted Ware <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Robert Green » Fri, 26 Feb 2010 03:08:55 GMT

 ctually, let me clear something technical up.  I just realized that
the OpenGL native side is using GetPrimitiveArrayCritical and not
GetDirectBufferAddress. I'm not sure why they decided to take that
route but I'm sure there was a good reason for it. The fact of the
matter is that while GPAC doesn't guarantee the actual array address
(it has the option to make a copy), it's most likely that it won't
make a copy and will instead hand over the actual array address. This
of course depends on the VM's implementation. The could have easily
implemented it to always use the actual address. Someone from that
camp would have to comment because I'm not going to dig through
Dalvik's source :)

Read more about it here:

That being said - all of what I talked about still stands. It's just
a different JNI function to get to it.

On Feb 25, 12:39pm, Robert Green <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Robert Green » Fri, 26 Feb 2010 03:25:17 GMT

 et me explain something.  Using directly allocated NIO buffers is a
DIRECT LINK between Java and native. The pointer you get from (void
*)GetDirectBufferAddress points to the exact memory that the Java
buffer is using. The memory is not managed in Java on the heap like
everything else. This is one of the few cases where you can write to
natively accessible code that does not need to be copied to work on
like an array does.

It's not a copy. It's the original buffer data that the native side
sees. That memory will be freed when the Buffer's java object is GCed
(from no more references.) It's safe to use that address so long as
you're still holding on to a reference to the Buffer (in Java, not
native. That native pointer is only as good as the java
counterpart). In the context of OpenGL, the memory is needed during
the GL bufferdata or GL array call and most likely during the draw
call (As that normally needs to read from system memory, particularly
with arrays) but I don't know if it needs it all the way to the end of
the flush. One would have to ask why you'd be allocating/deallocating
memory in a real time simulation, though :) Preallocation throughout
the sim would be the ideal solution and that wouldn't have issues with
invalidating memory before it's done being used.

Like Bob said, don't be creating new buffers all the time. In a
dynamic system (where you don't know how many triangles you'll be
drawing until visibility checks are done), make one the biggest buffer
it ever needs to be and use however much of it you need to use for
that draw. Most systems are relatively static, though, so all you
need to do is preallocate for each unique 3d object and use transforms
to do the dirty work.

I have a dynamic system for animations so I end up recalcing vertex
positions, but that's a fixed size buffer so I never need to
reallocate. I just process it in native code and it really works

On Feb 25, 11:30am, Bob Kerns <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Viktor Linder » Fri, 26 Feb 2010 03:42:10 GMT

 o clarify, in the original example, no buffer is allocated. The call
to "DynamicBuffer.allocate()" simply moves a position in a previously
allocated buffer which is filled each frame - ie. an "arena
allocator". DynamicBuffer.deallocate_last(size) simply moves the
position back without destroying any memory.

So it is not a gc issue. Also, while the buffer might get filled with
"junk" it will still be valid floats of some sort, since the array is
only written to from java.

Best regards,
Viktor Linder

On 25 Feb, 20:08, Robert Green <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Robert Green » Fri, 26 Feb 2010 07:49:32 GMT


Would you be willing to show a bit of your DynamicBuffer code so I can
see what it's doing? It's hard for me to help when there's a black
box in the middle.

On Feb 25, 1:41pm, Viktor Linder <> wrote:


Crash in glDrawElements() using VBOs just after glBufferData()

by Viktor Linder » Sat, 27 Feb 2010 04:30:38 GMT

It doesn't really do very much, just a wrapper around a buffer.
frame_reset() is called once each frame.

public class DynamicBuffer {
private static final int BUFFER_SIZE = 32*1024;
private static final int SCRATCH_SIZE = 32*1024;
private static int _p = 0;
public static FloatBuffer _buffer;
public static float _scratch[] = new float[SCRATCH_SIZE];

static {
_buffer = Util.create_floatbuffer(BUFFER_SIZE);

public static int allocate(int size) {
int r = _p;
_p += size;
if(_p > BUFFER_SIZE)
throw new RuntimeException("Dynamic buffer overflow");

return r;

// will only deallocate the last consecutive sequence of allocated
public static void deallocate(int size) {
_p -= size;
if(_p < 0)
throw new RuntimeException("Dynamic buffer underflow");

// write to dynamic buffer at offset off (returned by allocate())
contents of buf at [buf_off,buf_off+buf_len)
public static void put(int off, float[] buf, int buf_off, int
buf_len) {
_buffer.put(buf, buf_off, buf_len);

public static void frame_reset() {
_p = 0;

public class Util {
public static FloatBuffer create_floatbuffer(int size) {
ByteBuffer bb = ByteBuffer.allocateDirect(size*4);
FloatBuffer fb = bb.asFloatBuffer();
return fb;

On 26 Feb, 00:49, Robert Green <> wrote:


Other Threads

1. HTC Desire Debugging on Snow Leopard


I am trying to debug an Android application on my HTC Desire from
Eclipse (Snow Leopard). Really followed these steps,
but after connecting device via USB it appears some time when listing
using "adb devices" command (i achieve debug during a short time), but
later device is not shown anymore on the list...It is really weird...

Any idea on what could be happening?



2. SDK or some tool to develop a VERY simple Android game?


I am decent in Java and now I want to make a very simple android game,
would you recommend I do it in plain Java (I have never made a game in
java) or is there a tool like what these guys are promoting :

that you can recommend?



3. how to run our application at avd startup

4. [WTA] begitu susahnya ya nyari case buat O1?

5. Share : Nexus S setelah 2.3.3

6. [WTA] Upgrade ke ROM Apanda Froyo, nggak bisa install app :(

7. Mas AH in action di UGM