Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interleaved VBO causing glDrawArrays() error

I recently changed my app from using OpenGL ES 1.1 to 2.0, and in the process I decided to optimise my code further by using VBOs. I think I've got to grips with the main differences with ES 2.0, and have results to show that I'm doing things correctly without VBOs, however I've been stumped by a problem that only presents itself when I try to use VBOs.

I use a custom struct containing vertex position, color and size (plus a little padding to align data), and then interleave this vertex data in a VBO. This data is used to render point sprites. The problem is that I get an EXC_BAD_ACCESS on the glDrawArrays() call. The backtrace at this error is as follows:

#0  0x31fc7358 in gleRunVertexSubmitARM ()
#1  0x31fc87b2 in gleLLVMArrayFunc ()
#2  0x31fc872a in gleSetVertexArrayFunc ()
#3  0x31fbefcc in gleDrawArraysOrElements_ExecCore ()
#4  0x31fc4608 in glDrawArrays_IMM_Exec ()
#5  0x36ddaee2 in glDrawArrays ()
#6  0x0001cab8 in -[Renderer renderDrawingVertexBuffer:withSize:usingTexture:] (self=0x1783b0, _cmd=0x50fec, vboID=0, size=3584, drawTexture=5) at /Users/Stu/Documents/...
#7  0x000202f4 in -[EAGLView drawSmoothCurveFromPoints:endOfLine:] (self=0x195be0, _cmd=0x50d34, points=0x1956f0, endOfLine=1 '\001') at /Users/Stu/Documents/...
#8  0x0001e50c in -[EAGLView drawView:] (self=0x195be0, _cmd=0x50d8a, sender=0x0) at /Users/Stu/Documents/...
#9  0x0001e174 in -[EAGLView layoutSubviews] (self=0x195be0, _cmd=0x3297d4ac) at /Users/Stu/Documents/...
#10 0x326805fa in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#11 0x35efbf02 in -[NSObject(NSObject) performSelector:withObject:] ()
#12 0x333fbbb4 in -[CALayer layoutSublayers] ()
#13 0x333fb96c in CALayerLayoutIfNeeded ()

This is the struct for storing vertex data:

typedef struct {
    ISVertex2D vertex;     // Made up of 2 GLfloats.
    ISColor    color;      // Made up of 4 GLfloats.
    GLfloat    size;
    GLfloat    padding;
} ISPointSpriteData;

After a set of data is stored in an array of these structs, the data is sent to the VBO and rendered using glDrawArrays():

[renderer prepareScene];
[renderer renderBackground];

glBindBuffer(GL_ARRAY_BUFFER, penVbo);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(ISPointSpriteData) * penVboSize, sizeof(ISPointSpriteData) * vertexCount, &vertexBuffer[0].vertex);

glBindTexture(GL_TEXTURE_2D, drawTexture);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_COLOR);
glEnableVertexAttribArray(ATTRIB_SIZE);
glDisableVertexAttribArray(ATTRIB_TEXTURE_COORD);
glUniform1i(uniforms[UNIFORM_IS_SPRITE], GL_TRUE);

glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, vertex));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, color));
glVertexAttribPointer(ATTRIB_SIZE, 1, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, size));

glDrawArrays(GL_POINTS, 0, vertexCount);     // <--- EXC_BAD_ACCESS

glDisableVertexAttribArray(ATTRIB_VERTEX);
glDisableVertexAttribArray(ATTRIB_COLOR);
glDisableVertexAttribArray(ATTRIB_SIZE);


[renderer presentScene];

This code worked right before I put the VBO in, with the only alteration being that the last parameter of the glVertexAttribPointer() calls would obviously point to the data rather than an offset. What am I missing? I don't think this code is particularly complicated so I can only think that I've made a stupid mistake somewhere.

Thanks

like image 751
Stuart Avatar asked May 25 '26 07:05

Stuart


1 Answers

Problem solved:

There were a few things wrong with my code, not all of which would have been apparent from the listings in the question. I'll outline the major issues:

  • In code not listed, I was creating the VBOs in a utility function. In this function I was incorrectly passing the GLuint handle for the buffer (I was attempting to pass it by reference in a function that returns void). In the interests of making this more readable I changed the function to simply initialise its own handle and return it. This stopped the program crashing at the glDrawArrays() line (presumably the uninitialised value must already have been assigned to another buffer somewhere).

A new problem presented itself - the screen was being drawn to black and there were BIG delays between draw calls. This was caused by...

  • Not unbinding the VBOs after each draw call. For each frame a background texture is first drawn, followed by the contents of the VBOs. By leaving the VBOs bound for the next background render, I was obviously causing OGL to have a bit of a fit! This was not only the cause of the black screen, but also the big delays between draw calls.

Hope this is helpful to somebody else in a similar situation!

like image 155
Stuart Avatar answered May 26 '26 22:05

Stuart