Using buffer mapped with glMapBuffer in a different thread?

#1

Greetings,

can I safely write to buffers mapped with glMapBuffer in a thread different from the one that holds the gl context? I have a program that currently does a lot of large glBufferData calls in the main thread and I want to move the burden caused by the internal memcpy somewhere else.

Regards!

#2

Yes, if you either: 1) Make sure the content is only active on one thread at a time, or 2) Use multiple contexts which share objects and are careful about synchronizing buffer updates and use of the resulting data. However, I wouldn’t expect a performance miracle from doing either. For more details, see:

See:

[ul]
[li]Parallel OpenGL FAQ [/li][li]OpenGL and Multithreading [/li][/ul]
Another solution that is sometimes used is to Map/Unmap in the “GL” thread (the only thread that talks to GL), but move the memcpys into the mapped buffer region into a background thread. That offloads the memcpy to another thread, and can avoid a lot of context swapping inefficiency.

Yet another option to consider: using PERSISTENT COHERENT buffer mappings with memcpys on a background thread (see Buffer Object Streaming#Persistent mapped streaming in the OpenGL wiki) and synchronization to coordinate updates. That has similar advantages to the last approach, but also gets rid of all the Maps/Unmaps too. You can do the updates whenever and wherever you want. Just don’t forget to synchronize!

#3

Isn’t this exactly what I was proposing (mapping in the main thread, writing (=memcpy) in the worker thread? )

And do the maps/unmaps have more performance penalties so I should move them too?

Regards anyways

#4

Sorry, I read your question differently than you intended.

can I safely (write to buffers mapped with glMapBuffer in a thread) (different from the one that holds the gl context)?

vs.
can I safely (write to buffers in a thread) (different from the one that holds the gl context and calls glMapBuffer)?

The former had me thinking the glMapBuffers and the buffer writes were off in some background thread together.

#5

Then I’m happy. Thank you!

#6

Hey, I’m currently in a similar situation as described here where we are currently doing the following:

  1. Writing to the VBO pointer via memcpy after using glMapBuffer on a background thread using a background OpenGL context. We are also uploading some textures on this background thread as well.
  2. Performing essential rendering functions (i.e. glDrawElements, rendering to color/depth/stencil buffers, etc.) on the main thread.

Sometimes, we get crashes because of this memcpy, which happens either because of two reasons:

  1. The VBO pointer we obtain is corrupt
  2. Some of the locations where we plan to write to the VBO array are corrupted

Do you know of a situation in using glMapBuffer where crashes can happen because of the driver itself? I’m stuck trying to figure out if this is a threading issue from our side or not, but I’m not convinced by this because this can happen randomly when nothing rendering related is happening on the main thread.

As you can imagine, this is hard to reproduce and can only be reproduced when all optimizations are on.

Keep in mind I’m using OpenGL 2.1 and an NVIDIA GeForce GTX 1060 6GB. I don’t know if this is NVIDIA specific or not, but I’ve included my card here anyway.

Thanks so much for any help you can provide in advance!

#7

How do you know that these are corrupted ? For the first one I suppose you get an invalid address. But for the other one, this looks very weird.

Could you let people here how do you do your mapping more precisely ?

#8

Hey @Silence,

To answer your queries:

  1. I know the data is corrupted because when I hover my mouse over my pointer (which is an unsigned char*) and Visual Studio tells me “Error in string values” or something like that.
  2. For the mapping into VRAM, we do a couple of different things in our pipeline. First, when create our vertex attribute stream, which contains the data that represents the triangles, lines, whatever is present in the scene. We then place this representation into RAM, to maintain a representation of this data. Then, when we decide to upload directly to VRAM, we call glMapBuffer to get the VBO pointer, perform our memcpy, and then call glUnmapBuffer to make the changes. Keep in mind glMapBuffer/glUnmapBuffer can be called on either the main thread or the background thread in our case.

Hopefully this answers your queries. Thanks for your willingness to help!

#9

It would be safer to have the main thread map/unmap the buffer, with the background thread simply writing to the mapped region.

Other than that: if it’s affected by optimisation level, then I’d tend to suspect an issue with communicating information between threads. E.g. not using volatile qualifiers or memory barriers where they’re required. Optimisation won’t change the order in which API calls are made, but it might change the order of memory access (or in some cases, whether those memory accesses even occur).

#10

This does not mean that the content is invalid, except if your intend is to store readable string in your buffer.

#11

Do we know how glMapBuffer chooses the address that it gives back to the client? I know that glMapBuffer looks at virtual memory and finds an address, but I don’t know how it obtains this address. Is it dependent on the buffer we allocate from glBufferData before we call glMapBuffer? My working theory surrounding my problem involves performing glBufferData on one thread, and somehow that allocation overlaps with the buffer we are performing a memcpy to on the background thread, thus causing a crash. This seems plausible to me but I suppose I don’t enough about OpenGL drivers to qualify how plausible this situation actually sounds.

#12

No. The choice of address may be left to the OS.

Only insofar as repeatedly obtaining a mapping for a specific size increases the chances that the same address region will be used each time.

It isn’t going to use an address range that is already in use.