2016-05-15 116 views
2

对于科学任务,应在屏幕上显示具有稳定频率(最大60 Hz)的闪烁区域。我试图用Qt 5.6实现稳定的可视化刺激。Qt:vsync - 缺少渲染帧

根据这blog entry和许多其他在线建议,我实现了三种不同的方法:从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论坛。您可以按照整个讨论here。最后,这是结果:

“ V-sync很难;)基本上它与系统固有的噪声有关,如果输出显示16-17毫秒,那就是问题17毫秒也是如此。多这就是你看到跳绳

夫妇的事情,以减少噪音。!

  • 不要做I/O在渲染循环qDebug()是I/O,它可以阻断各种缓冲诡计
  • 在调试器下测试V-sync是无用的。调试将各种噪声引入你的应用。您应该在发布模式下测试v-sync而不附加调试器。
  • 尽量不要使用信号/插槽/事件,如果你可以帮助它。它们可能很嘈杂,即在paintGL的末尾手动调用update()。你可以这样跳过一些开销(不是很多,但是每一个位都是重要的)。
  • 如果您只需要一个闪烁的屏幕,请避免使用QPainter。它不是很慢,但放入它的begin()方法,看它实际上有多少。 OpenGL具有快速,专用的功能,可以用一种颜色填充缓冲区。你可以使用它。

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

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

应用这些位我能够从您的示例中删除跳过。请注意,在某些情况下会出现跳过,例如。当您移动/调整窗口大小或OS /其他应用程序忙于做某事时。你无法控制。 “