Qt:vsync - 缺少渲染帧

Qt: vsync - missing rendered frames

对于科学任务,屏幕上应显示频率稳定(最大 60 Hz)的闪烁区域。我尝试使用 Qt 5.6 实现稳定的刺激可视化。

根据这个blog entry和许多其他在线建议,我实现了三种不同的方法:继承自QWindow Class、QOpenGLWindow Class 和QRasterWindow Class。我想获得 vsync 的优势并避免使用 QTimer。

可以显示闪烁区域。帧之间的稳定时间段也被测量为 16 到 17 毫秒。 但是每隔几秒就会发现一些丢失的帧。可以很清楚地看到,没有刺激的稳定可视化。所有三种方法都会产生相同的效果。

我是否正确执行了我的代码,或者是否存在更好的解决方案?如果代码足以满足其目的,我是否必须假设这是硬件问题?显示一个简单的闪烁区域有那么难吗?

非常感谢您对我的帮助!

例如,您可以在此处查看我的 QWindow Class 代码:

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));}

我得到了 qt-forum 一些专家的帮助。您可以关注整个讨论 here。结果是这样的:

” 垂直同步很难 ;) 基本上它是在与系统固有的噪音作斗争。如果输出显示 16-17 毫秒,那就是问题所在。 17 毫秒太多了。这就是你看到的跳过。

有几件事可以减少噪音:

  • 不要在渲染循环中执行 I/O! qDebug() 是 I/O,它可以阻止各种缓冲恶作剧。
  • 在调试器下测试垂直同步是没有用的。调试会将各种噪音引入您的应用程序。您应该在没有附加调试器的情况下在发布模式下测试垂直同步。
  • 如果可以的话尽量不要使用signals/slots/events。它们可能很嘈杂,即在 paintGL 结束时手动调用 update()。您可以通过这种方式跳过一些开销(不多但每一位都很重要)。
  • 如果您只需要闪烁的屏幕,请避免使用 QPainter。它并不完全慢,但进入它的 begin() 方法并查看它实际做了多少。 OpenGL 有快速、专用的工具来用颜色填充缓冲区。你不妨用一下。

没有直接关系,但它会使您的代码更清晰:

  • 使用 QElapsedTimer 而不是手动计算时间间隔。为什么要重新发明轮子。

应用这些位,我能够从您的示例中删除跳过。请注意,跳过 在某些情况下发生,例如当您 move/resize window 或 OS/other 应用忙于做某事时。你无法控制它。 “