summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2017-08-11 10:12:57 +0200
committerPaul Lemire <paul.lemire@kdab.com>2017-08-11 13:07:16 +0000
commitaa16ae56f6a3f559e4d195717fbdb9c57c7579cd (patch)
tree1ba119dc4b0c09f02d0c66d27b05bcc0e19372ed /tests
parent7fcece168ebe2ab2ea8a8d28eadcf3206803e351 (diff)
VSyncFrameAdvanceService: fix Scene3D rendering
When rendering with Scene3D it could be that doRender() is called a lot more times than the speed at which the Qt3D simulation loop is running (this happens when resizing the window) This results in vsyncFrameAdvance->proceedToNextFrame() being called while the simulation isn't in a waiting state (simulation loop not yet blocking on vsyncFrameAdvance->waitForNextFrame()). This means that when the simulation loop finally unlocks, it would be able to make several loops for a given frame. Obviously this is really dangerous as the simulation loop drives the synching of changes and this could result in the data being prepared by the render jobs and the actual data in the managers to be corrupt. To fix that, vsyncFrameAdvance->waitForNextFrame() now acquires all available resources + 1 to cope with proceedToNextFrame being called more than once. Obviously this doesn't happen when Qt3D drives the rendering and the VSyncFrameAdvanceService was adjusted to have different behaviors depending on whether we are rendering with Scene3D or not. Change-Id: I495779571256d132fa7e1b3b31114f737de35a71 Task-number: QTBUG-60613 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp84
1 files changed, 83 insertions, 1 deletions
diff --git a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
index 3d873258f..6f455ea56 100644
--- a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
+++ b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
@@ -50,6 +50,63 @@ private:
Qt3DRender::Render::VSyncFrameAdvanceService *m_tickService;
};
+class FakeAspectThread Q_DECL_FINAL : public QThread
+{
+public:
+ FakeAspectThread(Qt3DRender::Render::VSyncFrameAdvanceService *tickService)
+ : m_tickService(tickService)
+ , m_count(0)
+ , m_running(true)
+ , m_waitForStarted(0)
+ {
+ }
+
+ int count() const { return m_count; }
+
+ void stopRunning()
+ {
+ QMutexLocker lock(&m_mutex);
+ m_running = false;
+ }
+
+ void waitForStarted()
+ {
+ m_waitForStarted.acquire(1);
+ }
+
+protected:
+ // QThread interface
+ void run() Q_DECL_FINAL
+ {
+ m_waitForStarted.release(1);
+ while (true) {
+
+ bool running = true;
+ {
+ QMutexLocker lock(&m_mutex);
+ running = m_running;
+ }
+
+ if (!running) {
+ qDebug() << "exiting";
+ return;
+ }
+
+ m_tickService->waitForNextFrame();
+ ++m_count;
+
+ QThread::msleep(100);
+ }
+ }
+
+private:
+ Qt3DRender::Render::VSyncFrameAdvanceService *m_tickService;
+ int m_count;
+ bool m_running;
+ QMutex m_mutex;
+ QSemaphore m_waitForStarted;
+};
+
class tst_VSyncFrameAdvanceService : public QObject
{
Q_OBJECT
@@ -59,7 +116,7 @@ private Q_SLOTS:
void checkSynchronisation()
{
// GIVEN
- Qt3DRender::Render::VSyncFrameAdvanceService tickService;
+ Qt3DRender::Render::VSyncFrameAdvanceService tickService(true);
FakeRenderThread renderThread(&tickService);
QElapsedTimer t;
@@ -74,6 +131,31 @@ private Q_SLOTS:
QVERIFY(t.elapsed() >= 950);
}
+ void checkWaitForNextFrame()
+ {
+ // GIVEN
+ Qt3DRender::Render::VSyncFrameAdvanceService tickService(false);
+ FakeAspectThread aspectThread(&tickService);
+
+ // WHEN
+ aspectThread.start();
+ aspectThread.waitForStarted();
+
+ QElapsedTimer t;
+ t.start();
+
+ while (t.elapsed() < 1000)
+ tickService.proceedToNextFrame();
+
+ aspectThread.stopRunning();
+
+ // To make sure the aspectThread can finish
+ tickService.proceedToNextFrame();
+ aspectThread.wait();
+
+ // THEN
+ QCOMPARE(aspectThread.count(), 10);
+ }
};
QTEST_MAIN(tst_VSyncFrameAdvanceService)