В чем разница между glBufferStorage и glBufferData?

glBufferStorage создает новое неизменяемое хранилище данных для буфера объект, привязанный к цели. Размер хранилища данных указанный по размеру. Если исходные данные доступны, его адрес может быть поставлены в данных. В противном случае для создания неинициализированных данных хранилище, данные должны быть NULL.

Неизменяемый означает, что я не могу его правильно изменить. Но тогда "неинициализированные данные" были бы бессмысленными.

Но это не является действительно неизменным, потому что мы можем указать GL_DYNAMIC_STORAGE_BIT​

В чем разница между glBufferStorage и glBufferData?

Ответ 1

Просто, чтобы вы знали, это тот же принцип, что и за glTexStorage* (...). Фактически, вы подписываете контракт с API, в котором говорится, что вам никогда не удастся изменить некоторые свойства вашего объекта, и взамен он дает объект неизменному статусу и позволяет вам делать то, что вы обычно не могли с ним.

Представления текстуры представляют собой интересный пример, в котором внутренние данные изображения неизменяемой текстуры могут быть разделены между несколькими объектами текстур и даже иметь переформатированный формат/размеры (например, 1 фрагмент текстуры 2D-массива может использоваться совместно и использоваться как бы это была обычная 2D-текстура).

Для вершинных буферов неизменяемое хранилище открывает класс оптимизации производительности (например, постоянную сопоставленную память), что было бы невозможно, если бы вы могли в любой момент изменить размер буфера. Вы создаете буфер, размер которого никогда не может быть изменен, но вы по-прежнему можете отправлять новые данные в любое время с помощью команд glBufferSubData* (...) или путем записи в буфер при отображении памяти.

С помощью glBufferData (...) вы можете вызывать эту команду несколько раз на одном и том же объекте, и она будет сиротой старой памяти и выделяет новое хранилище. С glBufferStorage (...) размер буфера устанавливается для времени жизни объекта (неизменяемого), и это ошибка (GL_INVALID_OPERATION), чтобы снова вызвать glBufferStorage (...) после того, как она была назначена неизменно.

Короче говоря, это хранилище данных (характеристики хранения) является неизменным, а не фактические данные.

Ответ 2

Я считаю, что эти слова из [https://www.opengl.org/registry/specs/ARB/buffer_storage.txt] показывают ключ:

OpenGL имеет длинные поддерживаемые объекты буфера в качестве средства хранения данных     которые могут использоваться для атрибутов вершинного источника, данных пикселей для текстур,     униформы и другие элементы. В нерасширенном GL хранилища буферных данных     являются изменяемыми - то есть они могут быть де-распределены или изменены, в то время как они     используются. Расширение GL_ARB_texture_storage добавило неизменяемое хранилище     для объекта текстуры (и впоследствии был включен в OpenGL 4.2).     Это расширение далее применяет концепцию неизменяемого хранилища для     буферных объектов. Если реализация осознает неизменность буфера,     он может сделать определенные предположения или применить конкретные     оптимизация для повышения производительности или надежности.

Они упомянули, что изменяемый буфер может быть выделен или изменен, и это происходит от glBufferData, которые приносят изменяемый буфер. Но glBufferStorage покажет вам возможность создания неизменяемого буфера.

Ключ здесь - "неизменный" означает, что вы не можете изменить его размер или отказаться от него в будущем, но не означает, что вы не можете его записывать/читать.

[Изменить] Я думаю, что также неплохо добавить некоторый образец, который может сделать слова из спецификации более понятными,:)

  • glBufferData Когда-нибудь вы можете встретить слова "сирот-сирот", обычно вы увидите похожие вызовы вроде (есть еще какой-то другой способ сделать буфера сиротой, например GL_MAP_INVALIDATE_BUFFER_BIT и т.д.):
    glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STREAM_DRAW); GLubyte* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_WRITE_BIT); Foo(ptr, size); glUnmapBuffer(GL_ARRAY_BUFFER);
  • glBufferStorage не позволяйте вам выделять его [обратите внимание на параметр 0 в glBufferData, но он сохранит память для Persistent-mapped Buffer, обычно вы увидите, что использование выглядит следующим образом: < ш > glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferStorage(GL_ARRAY_BUFFER, size, data, GL_MAP_PRESISTENT_BIT|GL_MAP_COHERENT_BIT); GLubyte* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_PRESISTENT_BIT|GL_MAP_COHERENT_BIT); Foo(ptr, size);
    Обратите внимание, что ptr просто поддерживает один и тот же адрес буфера, что означает, что буфер сохраняется в памяти, и вам не нужно отменить его, пока он вам действительно не понадобится.

Спасибо