Стриминг 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 дает черное окно и показывает только декодированный контент при закрытии

Неясно, является ли это только результатом отсутствия синхронизации, ошибки в вашем коде или даже ошибки драйвера.

Другие вопросы по тегам