Стриминг PBO, когда именно происходит синхронизация?
Я пытался заставить ffmpeg декодировать и преобразовывать пиксели в формат rgb8, записывать в сопоставленный буфер пикселей и использовать потоковую передачу для обновления текстуры opengl, которая затем отображается в окне sdl.
Декодирование и загрузка происходят в выделенном потоке (make sws_scale записывает в сопоставленный буфер), а визуализация выполняется в потоке визуализации в другом контексте с совместным использованием. (PBO на самом деле содержит несколько кадров, а текстура представляет собой 2-мерную текстуру массива для разделения позиций.)
Все работает нормально, если я сбрасываю отображаемый диапазон в потоке декодирования и использую glTextureSubImage3D в потоке рендеринга для обновления текстуры по необходимому индексу. В этом сценарии интегрированный графический процессор Intel работает довольно быстро (должен), но драйвер NV жалуется наPixel-path performance warning: Pixel transfer is synchronized with 3D rendering.
Я подумал, что может быть только glTextureSubImage3D действительно выполняет загрузку, поэтому я переместил glTextureSubImage3D сразу после операции очистки. На этот раз графический процессор NV работает нормально, и предупреждение исчезает, тогда как графический процессор Intel показывает черное окно и показывает только декодированный контент при закрытии.
Код выглядит примерно так:
//render thread
void RenderFrame(SDL_Window* window,GLobjects& glo, int index, int width, int height) {
glUniform1f(glo.index_location,index);
//The function in question
glTextureSubImage3D(glo.texture, 0, 0, 0, index, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)(index * width * height * 4));
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
SDL_GL_SwapWindow(window);
}
//Decode thread
int DecodeFrameToPBO(GLobjects& glo, int index){
//fill the mapped range needed
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, index * width * height * 4, 4 * width * height);
//The function in question
//glTextureSubImage3D(glo.texture, 0, 0, 0, index, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)(index * width * height * 4));
}
Меня действительно смущает идея клиентской памяти и того, как драйвер асинхронно загружает текстуру, где именно должна происходить загрузка и что на самом деле делает glTextureSubImage3D, когда привязан GL_PIXEL_UNPACK_BUFFER?
РЕДАКТИРОВАТЬ:
После добавления команды glFlush() для очистки очереди команд контекста загрузки после каждой загрузки версия Intel работает правильно без черного экрана.
ОБНОВИТЬ:
Добавление glFlush(), похоже, заставляет NV gpu выдавать предупреждение "Предупреждение о производительности пиксельного пути: передача пикселей синхронизирована с 3D-рендерингом". опять же, и загрузка графического процессора того же образца видео выросла с 8% до 10%. Кажется, что glFlush() запускает некоторую внутреннюю синхронизацию, которая, возможно, заставляет вещи работать в режиме ожидания? Поскольку графический процессор Intel не может работать без glFlush, даже с версией clientwaitsync с установленным битом команды flush, явный вызов flush на стороне рендеринга также не работает. Итак, что нужно сделать, чтобы осчастливить обоих водителей (и снизить загрузку)?
1 ответ
Я думаю, вас ввело в заблуждение предупреждение nvidia. Это не означает, что есть синхронизация CPU-GPU, это только говорит вам, что рендеринг текстуры синхронизирован (должен ждать), загрузка текстуры в порядке. См. Этот ответ для получения более подробной информации.
Итак, мой ответ: нет никаких проблем, следовательно, решение - ничего не менять.
Я думал, что это может быть только
glTextureSubImage3D
фактически выполняет загрузку, поэтому я переместилglTextureSubImage3D
сразу после операции сброса [в поток декодирования].
Если вы это сделаете, теперь вам придется вручную синхронизировать рендеринг с загрузкой текстуры, иначе вы будете время от времени сталкиваться с наполовину записанными кадрами или даже с неопределенным содержимым и в основном иметь состояние гонки.
Вы можете выполнить такую синхронизацию с помощью OpenGL Sync Objects. Но в итоге вы не получите большей производительности, чем в исходном варианте.
тогда как Intel gpu дает черное окно и показывает только декодированный контент при закрытии
Неясно, является ли это только результатом отсутствия синхронизации, ошибки в вашем коде или даже ошибки драйвера.