2016-05-15 4 views
2

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

В соответствии с этим blog entry и многими другими онлайн-рекомендациями я понял три разных подхода: Наследование от QWindow Class, QOpenGLWindow Class и QRasterWindow Class. Я хотел получить преимущество 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();} 

The 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-форума. Вы можете следить за всем обсуждением here. В конце концов, это было результатом:

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

Пара вещей, чтобы уменьшить этот шум:.!

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

Не напрямую связаны, но это сделает ваш код понятнее:

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

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

Смежные вопросы