Qt: vsync — пропущенные отрендеренные кадры

для научной задачи на экране должны отображаться мерцающие области со стабильной частотой (макс. 60 Гц). Я попытался добиться стабильной визуализации стимула с помощью Qt 5.6.

Согласно этому запись в блоге и во многих других онлайн-рекомендациях я реализовал три различных подхода: наследование от класса QWindow, класса QOpenGLWindow и класса QRasterWindow. Я хотел получить преимущество от vsync и избежать использования QTimer.

Мерцающая область может быть отображена. Также стабильный период времени между кадрами был измерен с 16 до 17 мс.
Но каждые несколько секунд обнаруживаются пропущенные кадры. Очень хорошо видно, что нет устойчивой визуализации стимула. Тот же эффект происходит на всех трех подходах.

Правильно ли я реализовал свой код или существуют лучшие решения? Если код соответствует своему назначению, должен ли я считать, что это аппаратная проблема? Может ли быть так сложно отобразить простую мерцающую область?

Большое спасибо за помощь!

В качестве примера вы можете увидеть мой код для класса QWindow здесь:

Window::Window(QWindow *parent)
: m_context(0)
, m_paintDevice(0)
, m_bFlickerState(true){
setSurfaceType(QSurface::OpenGLSurface);

QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setSwapInterval(1);
this->setFormat(format);

m_context.setFormat(format);
m_context.create();}

render() Функция, которая вызывается перезаписанными функциями событий:

void Window::render(){

//calculating exposed time between frames
m_t1 = QTime::currentTime();
int curDelta = m_t0.msecsTo(m_t1);
m_t0 = m_t1;
qDebug()<< curDelta;

m_context.makeCurrent(this);

if (!m_paintDevice)
m_paintDevice = new QOpenGLPaintDevice;
if (m_paintDevice->size() != size())
m_paintDevice->setSize(size());

QPainter p(m_paintDevice);
// draw using QPainter
if(m_bFlickerState){
p.setBrush(Qt::white);
p.drawRect(0,0,this->width(),this->height());
}
p.end();
m_bFlickerState = !m_bFlickerState;
m_context.swapBuffers(this);

// animate continuously: schedule an update
QCoreApplication::postEvent( this, new QEvent(QEvent::UpdateRequest));}

2

Решение

Мне помогли некоторые эксперты с форума qt. Вы можете следить за всем обсуждением Вот. В конце концов, это был результат:

«V-синхронизация сложна;) В основном она борется с присущей системе шумностью. Если на выходе отображается 16-17 мс, тогда это проблема. 17 мс — это слишком. Это пропуск, который вы видите.

Несколько вещей, чтобы уменьшить этот шум:

  • Не делайте ввод / вывод в цикле рендеринга! qDebug () — это ввод-вывод, и он может блокировать все виды буферизирующих махинаций.
  • Тестирование V-sync под отладчиком бесполезно. Отладка вводит все виды шума в ваше приложение. Вы должны тестировать v-sync в режиме Release без отладчика.
  • Старайтесь не использовать сигналы / слоты / события, если вы можете помочь. Они могут быть шумными, то есть вызывать update () вручную в конце paintGL. Вы пропускаете некоторые накладные расходы таким образом (не много, но каждый бит считается).
  • Если все, что вам нужно, это мерцающий экран, избегайте QPainter. Это не совсем медленно, но зайдите в метод begin () и посмотрите, сколько он на самом деле делает. OpenGL имеет быстрые, выделенные средства для заполнения буфера цветом. Вы могли бы также использовать это.

Не имеет прямого отношения, но это сделает ваш код чище:

  • Используйте QElapsedTimer вместо вычисления временных интервалов вручную. Зачем заново изобретать колесо.

Применяя эти биты, я смог убрать пропуск из вашего примера. Обратите внимание, что пропуск будут происходят в некоторых обстоятельствах, например когда вы перемещаете / изменяете размер окна или когда ОС / другие приложения заняты чем-то. Вы не можете это контролировать.
«

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]