Direct State AccessGL 4.5

glMapNamedBufferRange

Gives the CPU a pointer into part of a buffer's memory, by ID.

Signature

void *glMapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
                            GLbitfield access);

How it works

The DSA form of glMapBufferRange. Instead of copying data in with glNamedBufferSubData, you write (or read) through the returned pointer directly.

With storage created by glNamedBufferStorage using GL_MAP_PERSISTENT_BIT, the buffer can stay mapped forever: map once at start-up and write each frame into a region the GPU is not reading, protected by fences (glFenceSync). That is the fastest way to stream data every frame.

Parameters

bufferGLuint

The buffer.

offsetGLintptr

First byte to map.

lengthGLsizeiptr

Number of bytes.

accessGLbitfield

What you will do, combined with |.

Common values

GL_MAP_WRITE_BIT / GL_MAP_READ_BIT
Write into it / read from it.
GL_MAP_INVALIDATE_RANGE_BIT
The old contents can be thrown away: no wait for the GPU to finish with them.
GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT
Stay mapped while the GPU uses the buffer, with writes visible without a flush (the storage needs the same flags).
GL_MAP_FLUSH_EXPLICIT_BIT
You say which parts changed with glFlushMappedNamedBufferRange.

Return value

A pointer to the mapped bytes, or nullptr on error.

Tips & pitfalls

  • Direct State Access (GL 4.5): the object is passed as a parameter, so nothing needs to be bound and no global state is disturbed.

  • Never keep using a non-persistent pointer after glUnmapNamedBuffer, and never read from a pointer mapped only for writing: it can be uncached memory and very slow.

Errors

When the call is invalid it does nothing and sets an error, which glGetError returns:

GL_INVALID_VALUE
The range goes outside the buffer.
GL_INVALID_OPERATION
The buffer is already mapped, or access asks for something the storage flags do not allow.

Example

example.cpp
1GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
2glNamedBufferStorage(buf, 3 * regionSize, nullptr, flags);
3char *ptr = (char *)glMapNamedBufferRange(buf, 0, 3 * regionSize, flags);
4// each frame: write into ptr + frame % 3 * regionSize
Official Khronos documentation