2016-05-15 6 views
2

für eine wissenschaftliche Aufgabe, Flimmern Bereiche mit einer stabilen Frequenz (max. 60 Hz), soll auf dem Bildschirm angezeigt werden. Ich versuchte mit Qt 5.6 eine stabile Stimulusvisualisierung zu erreichen.Qt: vsync - fehlende gerenderte Frames

Entsprechend dieser blog entry und viele andere Online-Empfehlungen, realisierte ich drei verschiedene Ansätze: Vererben von QWindow-Klasse, QOpenGLWindow-Klasse und QRasterWindow-Klasse. Ich wollte den Vorteil von vsync bekommen und die Verwendung von QTimer vermeiden.

Der flackernde Bereich kann angezeigt werden. Auch eine stabile Zeitspanne zwischen den Frames wurde mit 16 bis 17 ms gemessen. Aber alle paar Sekunden werden einige verpasste Frames entdeckt. Es ist sehr deutlich zu sehen, dass es keine stabile Visualisierung des Reizes gibt. Derselbe Effekt tritt bei allen drei Ansätzen auf.

Habe ich die Implementierung meines Codes richtig gemacht oder gibt es bessere Lösungen? Wenn der Code für seinen Zweck geeignet ist, muss ich davon ausgehen, dass es sich um ein Hardwareproblem handelt? Könnte es dann schwierig sein, einen einfachen flackernden Bereich anzuzeigen?

Vielen Dank für Ihre Hilfe!

Als Beispiel Sie meinen Code für Qwindow Klasse hier sehen können:

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

Die render()-Funktion, die durch überschrieben Event-Funktionen aufgerufen wird, ist:

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

Antwort

2

ich Hilfe einiger Experten bekam aus dem Qt-Forum. Sie können die ganze Diskussion here folgen. Am Ende war das das Ergebnis:

" V-Sync ist hart;) Im Grunde kämpft es mit dem inhärenten Lärm des Systems. Wenn der Ausgang zeigt 16-17 ms dann ist das Problem. 17 ms ist auch . viel das ist das Überspringen Sie sehen

paar Dinge, die Geräusche zu reduzieren.!

  • ich nicht tun/O in der Schleife machen qDebug() I/O ist und es blockieren auf kann Alle Arten von Puffer-Shenanigans
  • Testen von V-Sync unter einem Debugger ist nutzlos.Das Debuggen führt alle Arten von Rauschen in deine App Sie sollten V-Sync im Freigabemodus ohne angehängtes Debugger testen.
  • versuchen Sie nicht, Signale/Slots/Events zu verwenden, wenn Sie es helfen können. Sie können laut sein, d. H. Rufen Sie update() manuell am Ende von paintGL auf. Sie überspringen einige Overhead auf diese Weise (nicht viel, aber jedes Bit zählt).
  • Wenn Sie nur einen flackernden Bildschirm benötigen, vermeiden Sie QPainter. Es ist nicht gerade langsam, aber lass dich in die begin() -Methode fallen und sieh, wie viel es tatsächlich macht. OpenGL verfügt über schnelle, dedizierte Funktionen, um den Puffer mit einer Farbe zu füllen. Du kannst es genauso gut benutzen.

nicht direkt, aber es wird der Code sauberer machen:

  • Verwenden QElapsedTimer anstelle von Zeitintervallen manuell zu berechnen. Warum erfinde das Rad neu?

Mit diesen Bits konnte ich das Überspringen aus Ihrem Beispiel entfernen.Man beachte, dass das Überspringen wird in einigen Umständen, z. wenn Sie das Fenster verschieben/in der Größe ändern oder wenn OS/andere Anwendungen damit beschäftigt sind, etwas zu tun. Du hast keine Kontrolle darüber. "