summaryrefslogtreecommitdiffstats
path: root/src/quick3d
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick3d')
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp23
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp19
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h3
3 files changed, 38 insertions, 7 deletions
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index 5a1cec495..f0ebfbc38 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -433,12 +433,26 @@ void Scene3DItem::applyRootEntityChange()
bool Scene3DItem::needsRender()
{
+ // We need the dirty flag which is connected to the change arbiter
+ // receiving updates to know whether something in the scene has changed
+
+ // Ideally we would use shouldRender() alone but given that it becomes true
+ // only after the arbiter has sync the changes and might be reset before
+ // process jobs is completed, we cannot fully rely on it. It would require
+ // splitting processFrame in 2 parts.
+
+ // We only use it for cases where Qt3D render may require several loops of
+ // the simulation to fully process a frame (e.g shaders are loaded in frame
+ // n and we can only build render commands for the new shader at frame n +
+ // This is where renderer->shouldRender() comes into play as it knows
+ // whether some states remain dirty or not (even after processFrame is
+ // called)
+
auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect));
const bool dirty = m_dirty
|| (renderAspectPriv
&& renderAspectPriv->m_renderer
- && renderAspectPriv->m_renderer->settings()
- && renderAspectPriv->m_renderer->settings()->renderPolicy() == QRenderSettings::Always);
+ && renderAspectPriv->m_renderer->shouldRender());
m_dirty = false;
return dirty;
}
@@ -466,10 +480,6 @@ void Scene3DItem::onBeforeSync()
if (!isVisible())
return;
- // Has anything in the 3D scene actually changed that requires us to render?
- if (!needsRender())
- return;
-
Q_ASSERT(QThread::currentThread() == thread());
// Since we are in manual mode, trigger jobs for the next frame
@@ -510,6 +520,7 @@ void Scene3DItem::onBeforeSync()
// start rendering before this function has been called
// We add in a safety to skip such frames as this could otherwise
// make Qt3D enter a locked state
+ m_renderer->setSkipFrame(!needsRender());
m_renderer->allowRender();
// Note: it's too early to request an update at this point as
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index 1e322a615..fafeeedf4 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -161,6 +161,7 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
, m_forceRecreate(false)
, m_shouldRender(false)
, m_dirtyViews(false)
+ , m_skipFrame(false)
, m_allowRendering(0)
, m_compositingMode(Scene3DItem::FBO)
{
@@ -278,6 +279,19 @@ void Scene3DRenderer::beforeSynchronize()
// We could otherwise enter a deadlock state
if (!m_allowRendering.tryAcquire(std::max(m_allowRendering.available(), 1)))
return;
+
+ // In the case of OnDemand rendering, we still need to get to this
+ // point to ensure we have processed jobs for all aspects.
+ // We also still need to call render() to allow proceeding with the
+ // next frame. However it won't be performing any 3d rendering at all
+ // so we do it here and return early. This prevents a costly QtQuick
+ // SceneGraph update for nothing
+ if (m_skipFrame) {
+ m_skipFrame = false;
+ static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(false);
+ return;
+ }
+
m_shouldRender = true;
// Check size / multisampling
@@ -360,6 +374,11 @@ void Scene3DRenderer::setCompositingMode(Scene3DItem::CompositingMode mode)
m_compositingMode = mode;
}
+void Scene3DRenderer::setSkipFrame(bool skip)
+{
+ m_skipFrame = skip;
+}
+
// Main Thread, Render Thread locked
void Scene3DRenderer::setScene3DViews(const QVector<Scene3DView *> views)
{
diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h
index 4f3651cd3..08a2c60a3 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer_p.h
+++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h
@@ -87,7 +87,7 @@ public:
void setCleanerHelper(Scene3DCleaner *cleaner);
void allowRender();
void setCompositingMode(Scene3DItem::CompositingMode mode);
-
+ void setSkipFrame(bool skip);
void setScene3DViews(const QVector<Scene3DView *> views);
public Q_SLOTS:
@@ -119,6 +119,7 @@ private:
bool m_forceRecreate;
bool m_shouldRender;
bool m_dirtyViews;
+ bool m_skipFrame;
QSemaphore m_allowRendering;
Scene3DItem::CompositingMode m_compositingMode;
QVector<Scene3DView *> m_views;