Для сценария с одним контекстом, когда вызывается glBufferData()
, существующий объект буфера удаляется, любые активные привязки этого ресурса в этом контексте будут развязаны, а все активные сопоставления будут удалены. Если вы вызовете glUnmapBuffer()
после glBufferData()
из того же контекста, вы получите ошибку GL_INVALID_OPERATION
, потому что состояние новой версии буфера изначально не отображается.
Для многоконтекстного сценария все становится сложнее. OpenGL ES определяет слабо согласованную модель управления состоянием (чтобы избежать дорогостоящих требований к блокировке на критичных для производительности путях вызовов).
- Состояние рендеринга, принадлежащее контексту (например, информация о привязке, разрешающие биты), никогда не может быть изменено другим контекстом (может быть реализовано без блокировки).
- Состояние ресурса, которое принадлежит объекту (например, буферы, сэмплеры, текстуры), слабо когерентно. Контекст немедленно увидит свои собственные изменения, но подхватит изменения, записанные другим контекстом, только при привязке ресурса (требуется блокировка только при изменениях привязки).
- Полезная нагрузка данных ресурсов вообще не согласованна. Если вы хотите, чтобы данные были доступны из одного контекста в другом, вы должны включить ручную синхронизацию между потоками.
Поток. Вызов glMapBuffer()
создаст копию основного состояния буфера "версия 1", включая локальную настройку состояния, указывающую на то, что буфер "сопоставлен".
Поток B, вызывающий glBufferData()
, создаст новую версию ресурса буфера «версия 2», но это не повлияет на состояние, удерживаемое потоком A, которое будет продолжать отражать состояние на момент, когда буфер был связан в потоке A (версия 1). ).
Поток A, вызывающий glUnmapBuffer()
, будет работать нормально, потому что он отменяет сопоставление буфера «версии 1» (отображенное состояние является локальным для контекста потока A, и это все еще говорит, что буфер «сопоставлен»).
Обратите внимание, что содержимое данных буфера, которое поток A видит после того, как поток B вызывает glBufferData()
, непредсказуем (это могут быть старые данные, это могут быть новые данные), в соответствии с дизайном, что данные вообще не связаны. Если не было ожидающих операций отрисовки, то для драйвера допустимо просто повторно использовать память, которая была поддержана «версией 1» буфера, чтобы содержать содержимое, которое было загружено для «версии 2». Если вам нужны гарантии согласованности данных в разных контекстах, вам нужна ручная синхронизация (концептуально это похоже на то, как два потока вызывают glBufferData()
в одном и том же буфере в одно и то же время).
Я бы рекомендовал прочитать главу 5 спецификации OpenGL ES 3.2.
person
solidpixel
schedule
26.07.2019