Чтение данных из gpu асинхронно с объектами Pixel Buffer
Получение данных из gpu кажется очень медленной задачей, если вы хотите читать их синхронизированными с вашим приложением. Одной из возможностей является асинхронное чтение с помощью объектов Pixel Buffer. К сожалению, я не могу увидеть, как это делается.
Сначала я создаю объект Pixel Buffer:
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, pbo_size, 0, GL_DYNAMIC_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
Затем я хочу прочитать пиксели из объекта Frame Buffer:
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, 0);
GLfloat *ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pbo_size, GL_MAP_READ_BIT);
memcpy(pixels, ptr, pbo_size);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
Но как это асинхронно? Блокирует ли glReadPixels или glMapBufferRange приложение, пока gpu не "готов"?
1 ответ
glReadPixels
вызов должен начать копирование в видимый процессором буфер. (всякий раз, когда он передается в графический процессор. Вы можете принудительно отправить его с помощью glFlush
). Вы начинаете чтение асинхронно.
glMapBufferRange
заставит glReadPixels
вызов до конца, если это не так (так как вы теперь получаете доступ к указателю на процессоре, нет никакого способа обойти это).
Так что... не делайте 2 спина к спине, но значительно позже.
Чтобы добавить к ответу Бахбара:
После
glReadPixels
, если вы планируете считывать данные, я считаю, что вам следует позвонитьglMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
.После
glReadPixels
а такжеglMemoryBarrier
, вы можете создать Fence Sync с помощьюglFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)
, затем либо проверьте, что графический процессор завершил выполнение всех инструкций перед синхронизацией сglGetSynciv(fence_sync, GL_SYNC_STATUS, sizeof(GLint), NULL, &result)
, или дождитесь, пока графический процессор завершит выполнение всех инструкций перед синхронизацией сglClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, nanosecond_timeout)
.