summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2017-12-22 14:06:04 +0100
committerPaul Lemire <paul.lemire@kdab.com>2018-01-16 07:46:01 +0000
commit907869e8f87bab55671bfabf29f773cc01f40b68 (patch)
tree6cd673235d34fd13cd33fb66df9b1d939c729e3c
parent855a19b41237711037f85ae671d7999021b4cc4e (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.cpp6
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h1
-rw-r--r--src/render/backend/abstractrenderer_p.h2
-rw-r--r--src/render/backend/renderer.cpp17
-rw-r--r--src/render/backend/renderer_p.h2
-rw-r--r--src/render/frontend/qrenderaspect.cpp4
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--tests/auto/render/commons/testrenderer.h2
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; }