Расширение ARB_buffer_storage

Традиционные буфера, предоставляемые OpenGL, могут менять свой размер во время использования - команда glBufferData может или освбодить выделенную под буфер память или изменить размер буфера.

По аналогии с расширением ARB_texture_storage данное расширение вводит понятие неизменяемых (immutable) буферов. Следует при этом иметь в виду, что неизменяемость не относится к содержимому буфера - его все равно можно менять даже для неизменяемых буферов. Однако размер неизменяемого буфера (также как и его флаги) изменить уже нельзя, что позволяет OpenGL выполнять определенные оптимизации работы с этим буфером.

Данное расширение вводит следующую функцию:

void glBufferStorage ( GLenum target, GLsizeiptr size,
                       const void * data, GLbitfield flags );

Также в случае поддержки расширения EXT_direct_state_access, вводится следующая дополнительная функция:

void glNamedBufferStorage ( GLuint buffer, GLsizeiptr size,
                            const void * data, GLbitfield flags )

Расширение ARB_buffer_storage входит в состав OpenGL, начиная с версии 4.4, расширение ARB(EXT)_diredct_state_access входит в состав начиная с версии 4.5.

Вызов каждой из рассмотренных выше функций делает текущий (или заданный) буфер неизменяемым и выделенная в его результате память размеров в size байт не может быть снова перевыделена - ее размер остается постоянным вплоть до уничтожения буфера. Обратите внимание, что после этого вызова для данного буфера уже нельзя вызывать glBufferData и glBufferStorage.

Параметр data задает начальные данные для инициализации выделенной под буфер памяти и может принимать значение NULL, когда выделенную память не нужно инициализировать (но память все рано будет выделена).

Параметр flags задает один или несколько битовых флагов, описывающих использование данного буфера приложением. Поддерживаются следующие флаги:

У самого буфера появляется дополнительные параметры - GL_BUFFER_IMMUTABLE_STORAGE и GL_BUFFER_MAPPED. Значения, соответствующие этим параметрам можно узнать при помощи функций glgGetBufferParameter*.

Следующий пример показывает, как можно узнать отображен ли в память текущий буфер для цели target.

GLint isMappedl;

glGetBufferParameteriv ( target, GL_BUFFER_MAPPED, &isMapped );

Также в качестве параметра access команды glMapBufferRange можно использовать GL_MAP_PERSISTENT_BIT и GL_MAP_COHERENT_BIT. Если вы хотите получить постоянное отображения для буфера, то нада указать флаг GL_MAP_PERSISTENT_BIT при вызове glBufferStorage и glMapBufferRange.

GLuint id;

glGenBuffers    ( 1, &id );
glBindBuffer    ( target, id );
glBufferStorage ( target, size, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_DYNAMIC_BIT );

void * data = glMapBufferRange ( target, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT );

Аналогично функция glMemoryBarrier теперь также поддерживает еще один тип барьера - GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT. Данный барьер гарантирует, что доступ со стороны клиента через отображенный в память буфер (с GLMAP_PERSISTENT_BIT) будет отражать данные, записанные шейдерами до этого барьера.