Я использую атомный счетчик в вычислительном шейдере с atomic_uint
привязан к динамическому GL_ATOMIC_COUNTER_BUFFER
(аналогично этому opengl-atomic-counter учебник маяк3d).
Я использую атомный счетчик в системе частиц, чтобы проверить, достигнуто ли условие для всех частиц; Я ожидаю увидеть counter==numParticles
когда все частицы находятся в правильном месте.
Я сопоставляю буфер каждого кадра и проверяю, подсчитал ли атомный счетчик все частицы:
GLuint *ptr = (GLuint *) glMapBuffer( GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY );
GLuint particleCount = ptr[ 0 ];
glUnmapBuffer( GL_ATOMIC_COUNTER_BUFFER );
if( particleCount == numParticles() ){ // do stuff }
На одном хосте GPU код работает нормально и particleCount
всегда достигает numParticles()
но на мульти хосте GPU particleCount
никогда не достигает numParticles()
,
Я могу визуально проверить, что условие выполнено, и тест должен быть верным, однако, ParticleCount изменяет каждый кадр, поднимаясь и опускаясь, но никогда не достигая numParticles ().
Я пробовал барьер памяти opengl на GL_ATOMIC_COUNTER_BARRIER_BIT
Прежде чем я разархивировать particleCount
:
glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
GLuint *ptr = (GLuint *) glMapBuffer( GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY );
GLuint particleCount = ptr[ 0 ];
glUnmapBuffer( GL_ATOMIC_COUNTER_BUFFER );
if( particleCount == m_particleSystem->numParticles() )
{ // do stuff }
и я пробовал glsl барьер перед увеличением счетчика в вычислительном шейдере:
memoryBarrierAtomicCounter();
atomicCounterIncrement( particleCount );
но атомный счетчик не синхронизируется между устройствами.
Как правильно синхронизировать атомный счетчик с несколькими устройствами?
Этот барьер (GL_ATOMIC_COUNTER_BARRIER_BIT
) внесет изменения в атомный счетчик видимый (например очищать кеши и запускать шейдеры в определенном порядке), но он не проверяет, завершены ли какие-либо параллельные шейдеры, прежде чем вы отобразите, прочитаете и снимите отображение своего буфера.
Поскольку ваш буфер отображается и читается обратно, вам не нужен этот барьер — этот барьер для согласованности между проходами шейдеров. Что вам действительно нужно, так это убедиться, что все шейдеры, которые обращаются к вашему атомарному счетчику, завершены, прежде чем вы попытаетесь прочитать данные с помощью команды GL, и для этого вам нужно GL_BUFFER_UPDATE_BARRIER_BIT
,
GL_BUFFER_UPDATE_BARRIER_BIT
:Читает / пишет через
glBuffer(Sub)Data
,glCopyBufferSubData
,glProgramBufferParametersNV
, а такжеglGetBufferSubData
или для буферизации памяти объекта, отображаемойglMapBuffer(Range)
после барьера будут отображаться данные, записанные шейдерами до барьера.Кроме того, запись с помощью этих команд, выполненных после того, как барьер будет ожидать завершения любой записи шейдера в ту же память, инициированную до барьера.
Вы можете думать о барьерах с неправильной точки зрения. Необходимый барьер зависит от того, какой тип операции чтение памяти должен быть последовательным.
(1) шейдерная запись / чтение между командами рендеринга
Один Команда рендеринга пишет бессвязно, а другой читает. Там нет необходимости
coherent
(Классификатор GLSL)Здесь вообще. Просто используйтеglMemoryBarrier
Перед выдачей команды рендеринга чтения, используя соответствующий бит доступа.(2) шейдер пишет, другие операции чтения OpenGL
Снова,
coherent
Не обязательно Вы должны использоватьglMemoryBarrier
Перед выполнением чтения, используя битовое поле, которое соответствует интересующей операции чтения.
В случае (1), барьер, который вы хотите, на самом деле GL_ATOMIC_COUNTER_BARRIER_BIT
потому что он будет устанавливать строгие правила памяти и порядок выполнения между различными проходами шейдеров, которые используют один и тот же атомный счетчик.
В случае (2), барьер вы хотите GL_BUFFER_UPDATE_BARRIER_BIT
, «операция чтения интереса» является glMapBuffer (...)
и, как показано выше, это покрыто GL_BUFFER_UPDATE_BARRIER_BIT
,
В вашей ситуации вы читаете буфер обратно, используя GL API. Вам нужны команды GL, чтобы дождаться, пока все ожидающие шейдеры завершат запись (это не происходит автоматически при несогласованном доступе к памяти — загрузка / сохранение изображений, атомные счетчики и т. Д.). Это дело учебника (2).