diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2017-12-22 14:06:04 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2018-01-16 07:46:01 +0000 |
commit | 907869e8f87bab55671bfabf29f773cc01f40b68 (patch) | |
tree | 6cd673235d34fd13cd33fb66df9b1d939c729e3c | |
parent | 855a19b41237711037f85ae671d7999021b4cc4e (diff) |
Scene3D: allow to force blocking rendering
When using Scene3D, when the jobs preparing the render commands for the 3D
scene take too long (more than the QtQuick refresh rate), the Scene3D wouldn't
render anything when QtQuick requested it to. Then, the next time
it would be asked to render (next QtQuick frame), if the jobs have finished by
then, it will render. If the jobs are still not ready, then the above process
is repeated.
This patch introduces an environment variable SCENE3D_BLOCKING_RENDERMODE which
can be set to force Scene3D to wait (for at most 10ms) instead of returning
immediately for the jobs being ready.
Change-Id: I2db10e622570a7bc8a2e2cbaff113c110135cd3e
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer.cpp | 6 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer_p.h | 1 | ||||
-rw-r--r-- | src/render/backend/abstractrenderer_p.h | 2 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 17 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 2 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect.cpp | 4 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect_p.h | 2 | ||||
-rw-r--r-- | tests/auto/render/commons/testrenderer.h | 2 |
8 files changed, 27 insertions, 9 deletions
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 23aaf9ed0..f95839e1b 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -134,6 +134,7 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead , m_lastMultisample(false) , m_needsShutdown(true) + , m_blocking(false) { Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -146,6 +147,9 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp ContextSaver saver; static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderInitialize(saver.context()); scheduleRootEntityChange(); + + const bool blockingRendermode = !qgetenv("SCENE3D_BLOCKING_RENDERMODE").isEmpty(); + m_blocking = blockingRendermode; } Scene3DRenderer::~Scene3DRenderer() @@ -299,7 +303,7 @@ void Scene3DRenderer::render() m_finalFBO->bind(); // Render Qt3D Scene - static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(); + static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(m_blocking); // We may have called doneCurrent() so restore the context if the rendering surface was changed // Note: keep in mind that the ContextSave also restores the surface when destroyed diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index ab1db1010..692390bb6 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -106,6 +106,7 @@ private: bool m_multisample; bool m_lastMultisample; bool m_needsShutdown; + bool m_blocking; friend class Scene3DCleaner; }; diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index ce56c04b9..3db012197 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -133,7 +133,7 @@ public: // Threaded renderer virtual void render() = 0; // Synchronous renderer - virtual void doRender() = 0; + virtual void doRender(bool scene3dBlocking = false) = 0; virtual void cleanGraphicsResources() = 0; diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 7726e5ab7..acb640caf 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -539,7 +539,7 @@ void Renderer::render() } } -void Renderer::doRender() +void Renderer::doRender(bool scene3dBlocking) { Renderer::ViewSubmissionResultData submissionData; bool hasCleanedQueueAndProceeded = false; @@ -549,9 +549,22 @@ void Renderer::doRender() // Lock the mutex to protect access to the renderQueue while we look for its state QMutexLocker locker(&m_renderQueueMutex); - const bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); + bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0; + // Scene3D Blocking Mode + if (scene3dBlocking && !queueIsComplete && !queueIsEmpty) { + int i = 0; + // We wait at most 10ms to avoid a case we could never recover from + while (!queueIsComplete && i++ < 10) { + QThread::msleep(1); + qCDebug(Backend) << Q_FUNC_INFO << "Waiting for ready queue (try:" << i << "/ 10)"; + locker.unlock(); + queueIsComplete = m_renderQueue->isFrameQueueComplete(); + locker.relock(); + } + } + // When using synchronous rendering (QtQuick) // We are not sure that the frame queue is actually complete // Since a call to render may not be synched with the completions diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index 0c6d2fd09..6311f35d6 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -169,7 +169,7 @@ public: void releaseGraphicsResources() Q_DECL_OVERRIDE; void render() Q_DECL_OVERRIDE; - void doRender() Q_DECL_OVERRIDE; + void doRender(bool scene3dBlocking = false) Q_DECL_OVERRIDE; void cleanGraphicsResources() Q_DECL_OVERRIDE; bool isRunning() const Q_DECL_OVERRIDE { return m_running.load(); } diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 3c2b36d85..af5457336 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -370,9 +370,9 @@ void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context) } /*! \internal */ -void QRenderAspectPrivate::renderSynchronous() +void QRenderAspectPrivate::renderSynchronous(bool blocking) { - m_renderer->doRender(); + m_renderer->doRender(blocking); } /*! diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index 4f9983d32..5f6b8f526 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -88,7 +88,7 @@ public: void loadSceneParsers(); void loadRenderPlugin(const QString &pluginName); void renderInitialize(QOpenGLContext *context); - void renderSynchronous(); + void renderSynchronous(bool blocking = false); void renderShutdown(); void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor); QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs(); diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 74f529fa0..269eebbe9 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -52,7 +52,7 @@ public: void shutdown() Q_DECL_OVERRIDE {} void releaseGraphicsResources() Q_DECL_OVERRIDE {} void render() Q_DECL_OVERRIDE {} - void doRender() Q_DECL_OVERRIDE {} + void doRender(bool scene3dBlocking = false) Q_DECL_OVERRIDE { Q_UNUSED(scene3dBlocking); } void cleanGraphicsResources() Q_DECL_OVERRIDE {} bool isRunning() const Q_DECL_OVERRIDE { return true; } bool shouldRender() Q_DECL_OVERRIDE { return true; } |