immediate mode "on top of" vertex buffers

Hi all,

Suppose (mostly for compatibility reasons) that I want to implement an immediate mode style interface of my own using VBOs, without any actual calls to glBegin etc.

Now I can think of a few ways to do it, my first guess would be something like:

  • A vertex buffer is created with the GL_STREAM_DRAW flag
  • The vertex buffer is mapped in my “glBegin” call
  • Vertex data is copied into the mapped buffer during my “glVertex” etc. calls
  • The vertex buffer is unmapped in my “glEnd” call, and a call is made to glDrawArrays to draw the geometry

My concerns are mostly related to pipeline stalls; namely the calls to map and unmap the buffer. Stalls would be a big problem for this, because the buffer would be mapped and unmapped quite a bit. My understanding is the GL_STREAM_DRAW usage flag exists for cases like this… but I just thought I’d ask the boards here to see if there is already a consensus on what is best for these types of things. Maybe I should use my own staging buffer, and call glBufferSubData instead?

As a side question, what is the difference between GL_DYNAMIC_DRAW and GL_STREAM_DRAW anyways? I can see how they would both be different from GL_STATIC_DRAW, but what is the difference between these last two? (I do understand they are just hints, and that on some implementations the difference might be “none”, but they are separate enums for some reason… what is it? Even reading the spec it seems unclear.)

Cheers,

Jeff

IMHO your suggestion is already too advanced for an immediate mode. To emulate it, I would after the call to glBegin (emulated) and knowing the primitive type, create a vertex array and after the glEnd, call glDrawArrays.

Otherwise, you could just call glBufferData(NULL) and then glMapBuffer to first discard the vbo content and then update the content of the new allocated memory space.

My concerns are mostly related to pipeline stalls; namely the calls to map and unmap the buffer. Stalls would be a big problem for this, because the buffer would be mapped and unmapped quite a bit.

A better thing to do would be to fill up the buffer, then once you’ve filled in all of your immediate-mode-style stuff, you render it all. That way, you’re not confusing the driver.

You won’t be able to render it immediately after the glEnd equivalent, but this will work much better for streaming.

You might even have something like a glFlush-equivalent that causes all of the currently set stuff to get rendered.

As a side question, what is the difference between GL_DYNAMIC_DRAW and GL_STREAM_DRAW anyways?

You update STREAM more frequently than DYNAMIC. STREAM is usually used for 1:1 update:use. Or, more specifically, after you use the buffer, you are going to update it. DYNAMIC is more like for loading in different parts of a level. You do change it (so it isn’t STATIC), but you’re not doing so on a regular basis.

If you like, you can take a look at how i did it with glim.

It’s open source and free to use.

Basically i cache all data until something like glEnd is called, then i upload it into a buffer with GL_STREAM flag and do the drawcall.

Jan.

Jan: ooooh, interesting stuff. An interface like this is almost exactly what I had in mind. I can’t use it directly (since my system has to be built on our abstraction, so that certain… other… graphics APIs will be compatible), but if I end up ripping you off too badly I’ll give you some credit in the docs.

Thanks,

Jeff

if you are only rendering <1000 vertices, i wouldn’t worry too much