Buffer Object Spec, Multiple Threads

So the VBO extension document suggests an interesting usage for doing multi-threaded data transfers to/fro GL server.

Say you have two threads, each with their own GL context. They share namespaces, so they have access to each other’s texture, display lists, buffer objects, etc.

Producer Thread:

  1. get buffer object from pool
  2. fill buffer with data
  3. notify Thread 2 of buffer object name

Consumer Thread:

  1. map buffer object
  2. read data, do stuff
  3. unmap buffer object
  4. return buffer object to pool

Thread 2 can also just getData instead of mapping.

Basically, Thread 1 has no blocking calls so it can still issue calls to GL without waiting for the map to complete. I think you can do a similar thing to write data to GL asynchronously.

The bad news is that it doesn’t work on my 6800GT with PBOs. The ~60 drivers crash, and the ~65 drivers crashes when you getData and gives you garbage when you map.

Question 1:
Did I interpret the spec correctly? Is there some reason why I shouldn’t expect this to work?

Question 2:
Has anyone done anything like this or gotten it to work?

Thanks all.

-Won

–EDIT–

It DOES work! Turns out we had a problem with wglShareLists… Yay.

Using the pointer from glMapBuffer I am filling the VBO from another thread that has no GL context. It seems to work well on ATI and NVIDIA drivers. Am I violating any rules?

As long as the context that mapped does not unmap while you are filling, it should be ok. If it does unmap, you’re in trouble; there’s no guarantee that the buffer won’t be moved somewhere else at any moment.

Umm… try this…

Producer Thread:

  1. get buffer object from pool
    1.1) Lock it
  2. fill buffer with data
    2.1) Unlock it
  3. notify Thread 2 of buffer object name

Consumer Thread:
0.9) Lock it (buffer object)

  1. map buffer object
  2. read data, do stuff
  3. unmap buffer object
    3.1) Unlock it
  4. return buffer object to pool

Lock and unlock should be some thread sync object from OS (usually critical section).

yooyo

Here is what I did using two large VBO’s.

Low priority producer thread without GL context:

  1. after waking fill the buffer with data
  2. notify consumer thread when complete
  3. Go to sleep

High priority consumer thread with GL context:

  1. map a buffer object
  2. wake up producer thread
  3. loop checking for producer thread completion,
    use the previous buffer for GL drawing until
    producer completes

For good performance using a VBO pointer, the buffer must be filled sequentially. There are special cases to handle if a buffer is lost. Use VSYNC and avoid the use glFinish to allow plenty of CPU time for the low priority thread to run.