diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2017-08-11 10:12:57 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2017-08-11 13:07:16 +0000 |
commit | aa16ae56f6a3f559e4d195717fbdb9c57c7579cd (patch) | |
tree | 1ba119dc4b0c09f02d0c66d27b05bcc0e19372ed /src/render/services | |
parent | 7fcece168ebe2ab2ea8a8d28eadcf3206803e351 (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 'src/render/services')
-rw-r--r-- | src/render/services/vsyncframeadvanceservice.cpp | 20 | ||||
-rw-r--r-- | src/render/services/vsyncframeadvanceservice_p.h | 2 |
2 files changed, 17 insertions, 5 deletions
diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp index 533b0fba1..880985aea 100644 --- a/src/render/services/vsyncframeadvanceservice.cpp +++ b/src/render/services/vsyncframeadvanceservice.cpp @@ -52,20 +52,22 @@ namespace Render { class VSyncFrameAdvanceServicePrivate Q_DECL_FINAL : public Qt3DCore::QAbstractFrameAdvanceServicePrivate { public: - VSyncFrameAdvanceServicePrivate() + explicit VSyncFrameAdvanceServicePrivate(bool drivenByRenderThread) : QAbstractFrameAdvanceServicePrivate(QStringLiteral("Renderer Aspect Frame Advance Service - aligned with vsync")) , m_semaphore(0) , m_elapsedTimeSincePreviousFrame(0) + , m_drivenByRenderThread(drivenByRenderThread) { } QSemaphore m_semaphore; QElapsedTimer m_elapsed; quint64 m_elapsedTimeSincePreviousFrame; + bool m_drivenByRenderThread; }; -VSyncFrameAdvanceService::VSyncFrameAdvanceService() - : QAbstractFrameAdvanceService(*new VSyncFrameAdvanceServicePrivate()) +VSyncFrameAdvanceService::VSyncFrameAdvanceService(bool drivenByRenderThread) + : QAbstractFrameAdvanceService(*new VSyncFrameAdvanceServicePrivate(drivenByRenderThread)) { } @@ -77,7 +79,17 @@ VSyncFrameAdvanceService::~VSyncFrameAdvanceService() qint64 VSyncFrameAdvanceService::waitForNextFrame() { Q_D(VSyncFrameAdvanceService); - d->m_semaphore.acquire(1); + + // When rendering with Scene3D, we always want to acquire the available + // amount + 1 to handle the cases where for some reason proceedToNextFrame + // is being called more than once between calls to waitForNextFrame This + // could be the case when resizing the window + + // When Qt3D is driving rendering however, this shouldn't happen + if (d->m_drivenByRenderThread) + d->m_semaphore.acquire(1); + else + d->m_semaphore.acquire(d->m_semaphore.available() + 1); const quint64 currentTime = d->m_elapsed.nsecsElapsed(); qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame; diff --git a/src/render/services/vsyncframeadvanceservice_p.h b/src/render/services/vsyncframeadvanceservice_p.h index 98daebf81..f33d41b98 100644 --- a/src/render/services/vsyncframeadvanceservice_p.h +++ b/src/render/services/vsyncframeadvanceservice_p.h @@ -64,7 +64,7 @@ class VSyncFrameAdvanceServicePrivate; class Q_AUTOTEST_EXPORT VSyncFrameAdvanceService Q_DECL_FINAL : public Qt3DCore::QAbstractFrameAdvanceService { public: - VSyncFrameAdvanceService(); + explicit VSyncFrameAdvanceService(bool drivenByRenderThread); ~VSyncFrameAdvanceService(); qint64 waitForNextFrame() Q_DECL_FINAL; |