RaptorDotCpp
RaptorDotCpp

Reputation: 1465

Bad access code 1 glDrawElements

I'm trying to draw things each frame by batching it. This means I have to use glBufferSubData(), which I'm unfamiliar with. I'm thinking I'm doing something wrong when substituting the data, causing the access violation when calling glDrawElements.

My setup code:

GL_TRY(glGenVertexArrays(1, &mVao));
GL_TRY(glBindVertexArray(mVao));

GL_TRY(glGenBuffers(1, &mEbo));
GL_TRY(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo));
GL_TRY(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));

GL_TRY(glGenBuffers(1, &mVbo));
GL_TRY(glBindBuffer(GL_ARRAY_BUFFER, mVbo));
GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));

GLint posAttrib;
GL_TRY(posAttrib = glGetAttribLocation(mShader.getProgram(), "position"));
GL_TRY(glEnableVertexAttribArray(posAttrib));
GL_TRY(glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0));

GLint texAttrib;
GL_TRY(texAttrib = glGetAttribLocation(mShader.getProgram(), "texCoords"));
GL_TRY(glEnableVertexAttribArray(texAttrib));
GL_TRY(glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))));

GL_TRY(glBindVertexArray(0));

My drawing code:

GL_TRY(glBindVertexArray(mVao));

GL_TRY(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo));
GL_TRY(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(GLuint), &indices[0]));

GL_TRY(glBindBuffer(GL_ARRAY_BUFFER, mVbo));
GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));

GL_TRY(glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, 0));

GL_TRY(glBindVertexArray(0));

I've been checking everything and trying to debug for a while now, but I just can't find what I'm doing wrong.

For the record, GL_TRY is a macro that reports any OpenGL errors. I'm not getting any.

Upvotes: 0

Views: 260

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54562

The size of your buffers is always 0:

GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));

The second argument to glBufferData() specifies the size of the buffer, which is 0 in your case.

As the name suggests, glBufferSubData() can only replace sub-sections of the buffer. It can't change the size. So the size is still 0 after this call. You should actually get a GL_INVALID_VALUE error from this call.

One way of looking at these entry points is:

  • glBufferData() allocates buffer memory, and optionally fills it with data. When called with NULL as the data pointer, the comparable call for CPU memory is malloc().
  • glBufferSubData() writes data to already allocated buffer memory. It does not change the amount of memory allocated. The comparable call for CPU memory is memcpy().

To make this work, you'll need to pass the size to glBufferData():

GL_TRY(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));

Using glBufferSubData() does not really make much sense in this case. You might just as well pass the data to glBufferData() here. glBufferSubData() is primarily useful if you want to replace only part of your buffer.

To use glBufferSubData() in your case, you'll want to call glBufferData() only once, during setup. This will work well as long as the size is constant, or you can at least establish a good upper limit. Otherwise you will have to call it again when the size changes. But if you want to use glBufferSubData() productively, this would still have to be much less frequent than every draw call. Otherwise you're better off specifying the data as part of the glBufferData() call:

GL_TRY(glBufferData(GL_ARRAY_BUFFER,
                    vertices.size() * sizeof(Vertex), &vertices[0]), GL_STREAM_DRAW));

Upvotes: 1

Related Questions