Qt: vsync - missing rendered frames

自古美人都是妖i 提交于 2019-12-24 00:59:48

问题


for a scientific task, flickering areas with a stable frequency (max. 60 Hz), shall be displayed on the screen. I tried to achieve a stable stimulus visualization using Qt 5.6.

According to this blog entry and many other online recommendations, I realized three different approaches: Inheriting from QWindow Class, QOpenGLWindow Class and QRasterWindow Class. I wanted to get the advantage of vsync and avoid the usage of QTimer.

The flickering area can be displayed. Also a stable time period between the frames has been measured with 16 up to 17 ms. But every few seconds some missed frames are spotted. It can be seen very clearly that there is no stable visualization of the stimulus. The same effect occurs on all three approaches.

Have I done the implementation of my code properly or do better solutions exist? If the code is adequate for its purpose do I have to assume that it is a hardware problem? Could it be that difficult then, to display a simple flickering area?

Thank you very much for helping me!

As Example you can see my code for QWindow Class here:

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() function, which is called by overwritten event functions, is:

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

回答1:


I got help of some experts from the qt-forum. You can follow the whole discussion here. At the end, this was the result:

" V-sync is hard ;) Basically it's fighting with the inherent noisiness of the system. If the output shows 16-17 ms then that's the problem. 17 ms is too much. That's the skipping you see.

Couple of things to reduce that noise:

  • Don't do I/O in the render loop! qDebug()is I/O and it can block on all kinds of buffering shenanigans.
  • Testing V-sync under a debugger is useless. Debugging introduces all kinds of noise into your app. You should be testing v-sync in Release mode without debugger attached.
  • try not to use signals/slots/events if you can help it. They can be noisy i.e. call update() manually at the end of paintGL. You skip some overhead this way (not much but every bit counts).
  • If all you need is a flickering screen avoid QPainter. It's not exactly slow, but drop into the begin() method of it and see how much it actually does. OpenGL has fast, dedicated facilities to fill the buffer with a color. You might as well use it.

Not directly related, but it will make your code cleaner:

  • Use QElapsedTimer instead of manually calculating time intervals. Why re-invent the wheel.

Applying these bits I was able to remove the skipping from your example. Note that the skipping will occur in some circumstances, e.g. when you move/resize the window or when OS/other apps are busy doing something . You have no control over that. "



来源:https://stackoverflow.com/questions/37239900/qt-vsync-missing-rendered-frames

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!