PDA

View Full Version : How to map Buffer Objects with zero copy?



hyppoo
06-06-2017, 04:18 AM
version: opengl es 3.0
platform: imx6q

In the book <opengl es programming guide> "Mapping Buffer Objects" says:


On architectures with shared memory, mapping the buffer returns a
direct pointer into the address space where the buffer will be stored for
the GPU. By mapping the buffer, the application can avoid the copy
step, thereby realizing better performance on updates.

I have gotten the pointer to the buffer, using
glMapBufferRange, so how to do zero copy?

Dark Photon
06-06-2017, 06:10 AM
version: opengl es 3.0
platform: imx6q

Never heard of it, so I looked it up. Apparently this is:


3D GPU = Vivante GC2000
CPU = ARM Cortex A9
SoC = NXP i.MX6 Quad (thus imx6q)



In the book <opengl es programming guide> "Mapping Buffer Objects" says:


On architectures with shared memory, mapping the buffer returns a
direct pointer into the address space where the buffer will be stored for
the GPU. By mapping the buffer, the application can avoid the copy
step, thereby realizing better performance on updates.

I have gotten the pointer to the buffer, using
glMapBufferRange, so how to do zero copy?

What it's saying is that this may just happen for you because of the way the driver is implemented.

What it "doesn't" say is that, depending on how you map the buffer and how the driver is written, if you've previously modified the buffer and a batch referencing that buffer is still in-flight, the driver may:


stall the entire pipeline until that buffer object is no longer in use by it,
create a copy of the entire buffer object, bloating your allocated GPU memory behind-the-scenes, so that the pipeline can continue to use the old copy while you modify a new copy, OR
just give you a pointer into the same buffer as before without any expensive stalls or copies ("ghosts") created.


#2 is also called resource "ghosting" or resource "renaming". #3 is of course what you want for best performance and predictable GPU memory usage.

If your driver is spec compliant, you're most likely to get #3 if you map the buffer range with the UNSYNCHRONIZED flag. ...or if you happen to have EXT_buffer_storage (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt) support, then with the PERSISTENT and COHERENT flags. For more on these, see Buffer Object Streaming (https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming) in the GL wiki.

You need to know what your driver will do. The best source is the GPU vendor's documentation or their support staff.

mhagain
06-06-2017, 07:09 AM
Write directly into the pointer.

You probably have things set up like so:
data[0] = something;
data[1] = something;
data[2] = something;
ptr = glMapBufferRange(...);
memcpy (ptr, data, size);
glUnmapBuffer ();
To avoid the copy you do this instead:

ptr = glMapBufferRange(...);
ptr[0] = something;
ptr[1] = something;
ptr[2] = something;
glUnmapBuffer ();
Note that this is not always possible. In particular it requires you to know the size you need to map in advance, and you just might not have that knowledge.

hyppoo
06-07-2017, 07:09 PM
Thank you for all!
Now I'm clear what I should do.