Как Qt разделяет контексты OpenGL за кулисами? - PullRequest
2 голосов
/ 21 мая 2019

Я пишу заявление, которое:

  • Непрерывно выводит материал за пределы экрана в конвейере, который имеет частный контекст OpenGL и частный поток
  • Рисует некоторые из ранее отрисованных текстур в виджетах

Чтобы сделать это, мне нужно поделиться этими текстурами как с конвейером, так и с контекстами виджетов:

Подход 1: разделить все контексты

int main (int argc, char *argv[])
{
     QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
     QApplication a(argc, argv);

     // [...] Create and initialize the pipeline (private context)
     // [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
     // [...] Set the texture to display in the widget with one created and rendered in the pipeline
}

К тому времени, когда я хочу нарисовать свою текстуру (в обратном вызове paintGL()), glBindTexture дает GL_INVALID_OPERATION.
Графический отладчик показывает странную текстуру вместо моей: разделение контекста, похоже, не работает.

Подход 2: виджет имеет самостоятельно созданный контекст, который разделяет как конвейер, так и Qt

// [...] Create and initialize the pipeline (private context)
// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// widget's initializeGL() callback gets called
void initializeGL()
{
     initializeOpenGLFunctions();
     m_secondContext.setShareContext(QOpenGLContext::currentContext());
     m_secondContext.setShareContext(pipelineContext);
     m_secondContext.create();
}
// use the second context during paintEvents
void paintGL()
{
     auto contextBackup(QOpenGLContext::currentContext());
     auto surfaceBackup(contextBackup->surface());
     assert(m_secondContext->makeCurrent(surfaceBackup));

     // [...] draw texture

     contextBackup->makeCurrent(surfaceBackup);
}

Также не работает, выдает ту же ошибку, что и подход 1 + еще, что я не обнаружил.

Подход 3: Конвейер разделяет контекст виджетов

// [...] Create a window with a widget that can display a texture (Qt creates a private context itself)
// [...] Create and initialize the pipeline with the widgets context set as shared 
//       before calling create on the new pipeline context
void initializePipeline()
{
     m_pipelineContext.setShareContext(widgetContext);
     m_pipelineContext.create();
}

Это работает, НО это нежелательное решение, так как не позволяет создавать такие виджеты ПОСЛЕ инициализации конвейера

Вопросы, которые я задаю:

  • Все три сценария должны дать один и тот же результат, что происходит, что я пропустил?
  • Нужно ли добавлять специальные инструкции для распределения общего ресурса в общем контексте?
  • Безопасен ли обмен контекстами? Например, могу ли я использовать общие ресурсы, не заботясь о взаимном исключении? (редактировать: использование одного не решает проблему)

1 Ответ

1 голос
/ 21 мая 2019

Отвечая на ваши вопросы:

Нужно ли добавлять специальные инструкции для распределения общего ресурса? в контексте, который является общим?

номер

Безопасен ли обмен контекстами? Например, я могу использовать общие ресурсы не заботясь о взаимном исключении?

Совместное использование контекста не является потокобезопасным. Совместное использование - это консолидация пространства имен объекта OpenGL.

Но я подозреваю, что эти ответы вам совсем не помогут. Я буду продолжать с наблюдением. Ваша ошибка странная, потому что GL_INVALID_OPERATION генерируется только в одном сценарии для glBindTexture:

GL_INVALID_OPERATION генерируется, если текстура была создана ранее с целью, которая не соответствует цели target .

Что указывает на наличие текстуры с именем textureHandle, но не с целью GL_TEXTURE_2D. Возможно, цель текстуры на самом деле GL_TEXTURE_2D_MULTISAMPLE?

Конечно, есть вероятность, что обмен не работает по любой причине. Это должно быть легко найдено с помощью практически любого графического отладчика для перечисления объектов в каждом контексте; создать в одном, посмотреть, если он появляется в другом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...