summaryrefslogtreecommitdiffstats
path: root/src/render/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/backend')
-rw-r--r--src/render/backend/abstractrenderer_p.h17
-rw-r--r--src/render/backend/backendnode.cpp6
-rw-r--r--src/render/backend/backendnode_p.h5
-rw-r--r--src/render/backend/boundingvolumedebug.cpp1
-rw-r--r--src/render/backend/cameralens.cpp2
-rw-r--r--src/render/backend/computejob.cpp1
-rw-r--r--src/render/backend/entity.cpp1
-rw-r--r--src/render/backend/layer.cpp1
-rw-r--r--src/render/backend/nodefunctor_p.h1
-rw-r--r--src/render/backend/renderattachment.cpp1
-rw-r--r--src/render/backend/renderer.cpp45
-rw-r--r--src/render/backend/renderer_p.h9
-rw-r--r--src/render/backend/renderersettings.cpp1
-rw-r--r--src/render/backend/renderqueue.cpp16
-rw-r--r--src/render/backend/renderqueue_p.h3
-rw-r--r--src/render/backend/rendertarget.cpp1
-rw-r--r--src/render/backend/transform.cpp2
17 files changed, 105 insertions, 8 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 4a432f641..dbc157a2c 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -50,6 +50,7 @@
// We mean it.
//
+#include <QtCore/qflags.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
@@ -77,6 +78,17 @@ class NodeManagers;
class Entity;
class FrameGraphNode;
class RendererSettings;
+class BackendNode;
+
+// Changes made to backend nodes are reported to the Renderer
+enum class BackendNodeDirtyFlag {
+ Transform = 1 << 0,
+ Material = 1 << 1,
+ Geometry = 1 << 2,
+ Any = 1 << 15
+};
+Q_DECLARE_FLAGS(BackendNodeDirtySet, BackendNodeDirtyFlag)
+Q_DECLARE_OPERATORS_FOR_FLAGS(BackendNodeDirtySet)
class QT3DRENDERSHARED_PRIVATE_EXPORT AbstractRenderer
{
@@ -111,6 +123,11 @@ public:
virtual bool isRunning() const = 0;
+ virtual void markDirty(BackendNodeDirtySet changes, BackendNode *node) = 0;
+ virtual BackendNodeDirtySet dirtyBits() = 0;
+ virtual bool shouldRender() = 0;
+ virtual void skipNextFrame() = 0;
+
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0;
diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp
index 3051e6c90..247f6340b 100644
--- a/src/render/backend/backendnode.cpp
+++ b/src/render/backend/backendnode.cpp
@@ -61,6 +61,12 @@ void BackendNode::setRenderer(AbstractRenderer *renderer)
m_renderer = renderer;
}
+void BackendNode::markDirty(BackendNodeDirtySet changes)
+{
+ Q_ASSERT(m_renderer);
+ m_renderer->markDirty(changes, this);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h
index b4996051c..e5e6c7b33 100644
--- a/src/render/backend/backendnode_p.h
+++ b/src/render/backend/backendnode_p.h
@@ -61,7 +61,7 @@ namespace Qt3DRender {
namespace Render {
-class BackendNode : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT BackendNode : public Qt3DCore::QBackendNode
{
public:
BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
@@ -69,6 +69,9 @@ public:
void setRenderer(AbstractRenderer *renderer);
+protected:
+ void markDirty(BackendNodeDirtySet changes);
+
private:
AbstractRenderer *m_renderer;
};
diff --git a/src/render/backend/boundingvolumedebug.cpp b/src/render/backend/boundingvolumedebug.cpp
index f9f6b84ff..21073e989 100644
--- a/src/render/backend/boundingvolumedebug.cpp
+++ b/src/render/backend/boundingvolumedebug.cpp
@@ -82,6 +82,7 @@ void BoundingVolumeDebug::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (propertyName == QByteArrayLiteral("recursive")) {
m_recursive = propertyChange->value().toBool();
}
+ markDirty(BackendNodeDirtyFlag::Any);
}
}
diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp
index 067fb28e9..d1a273a99 100644
--- a/src/render/backend/cameralens.cpp
+++ b/src/render/backend/cameralens.cpp
@@ -92,6 +92,8 @@ void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
} else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
m_enabled = propertyChange->value().toBool();
}
+
+ markDirty(BackendNodeDirtyFlag::Any);
}
break;
diff --git a/src/render/backend/computejob.cpp b/src/render/backend/computejob.cpp
index ed7d6ad35..6444e271e 100644
--- a/src/render/backend/computejob.cpp
+++ b/src/render/backend/computejob.cpp
@@ -73,6 +73,7 @@ void ComputeJob::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (e->type() == Qt3DCore::NodeUpdated) {
if (propertyChange->propertyName() == QByteArrayLiteral("enabled"))
m_enabled = propertyChange->value().toBool();
+ markDirty(BackendNodeDirtyFlag::Any);
}
}
diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp
index 728ef17ff..b7edb7c25 100644
--- a/src/render/backend/entity.cpp
+++ b/src/render/backend/entity.cpp
@@ -205,6 +205,7 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
default:
break;
}
+ markDirty(BackendNodeDirtyFlag::Any);
}
void Entity::dump() const
diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp
index c384479b6..c1a0a7d0b 100644
--- a/src/render/backend/layer.cpp
+++ b/src/render/backend/layer.cpp
@@ -91,6 +91,7 @@ void Layer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
} else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
m_enabled = propertyChange->value().toBool();
}
+ markDirty(BackendNodeDirtyFlag::Any);
}
} // namespace Render
diff --git a/src/render/backend/nodefunctor_p.h b/src/render/backend/nodefunctor_p.h
index 1fb1a8d82..2b5e8c9f7 100644
--- a/src/render/backend/nodefunctor_p.h
+++ b/src/render/backend/nodefunctor_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
#include <Qt3DCore/qnode.h>
#include <Qt3DRender/private/backendnode_p.h>
diff --git a/src/render/backend/renderattachment.cpp b/src/render/backend/renderattachment.cpp
index 472eaad37..44ee3bb60 100644
--- a/src/render/backend/renderattachment.cpp
+++ b/src/render/backend/renderattachment.cpp
@@ -119,6 +119,7 @@ void RenderAttachment::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
else if (propertyChange->propertyName() == QByteArrayLiteral("name")) {
m_attachmentData.m_name = propertyChange->value().toString();
}
+ markDirty(BackendNodeDirtyFlag::Any);
}
}
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index b2df0bb32..0d67d7500 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -140,6 +140,8 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_waitForInitializationToBeCompleted(0)
, m_pickEventFilter(new PickEventFilter())
, m_exposed(0)
+ , m_lastFrameCorrect(0)
+ , m_changeSet(0)
, m_glContext(Q_NULLPTR)
, m_pickBoundingVolumeJob(Q_NULLPTR)
, m_time(0)
@@ -597,6 +599,8 @@ bool Renderer::submitRenderViews()
const int renderViewsCount = renderViews.size();
quint64 frameElapsed = queueElapsed;
+ m_lastFrameCorrect.store(1); // everything fine until now.....
+ m_changeSet = 0; // mark "not dirty"
// Early return if there's actually nothing to render
if (renderViewsCount <= 0)
@@ -674,7 +678,8 @@ bool Renderer::submitRenderViews()
m_graphicsContext->setViewport(renderView->viewport(), renderView->surfaceSize() * renderView->devicePixelRatio());
// Execute the render commands
- executeCommands(renderView);
+ if (!executeCommands(renderView))
+ m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame!
// executeCommands takes care of restoring the stateset to the value
// of gc->currentContext() at the moment it was called (either
@@ -705,16 +710,42 @@ bool Renderer::submitRenderViews()
return true;
}
+void Renderer::markDirty(BackendNodeDirtySet changes, BackendNode *node)
+{
+ Q_UNUSED(node);
+ m_changeSet |= changes;
+}
+
+BackendNodeDirtySet Renderer::dirtyBits()
+{
+ return m_changeSet;
+}
+
+bool Renderer::shouldRender()
+{
+ // Only render if something changed during the last frame, or the last frame
+ // was not rendered successfully
+ return (m_changeSet != 0 || !m_lastFrameCorrect.load());
+}
+
+void Renderer::skipNextFrame()
+{
+ // make submitRenderViews() actually run
+ m_renderQueue->setNoRender();
+ m_submitRenderViewsSemaphore.release(1);
+}
+
// Waits to be told to create jobs for the next frame
// Called by QRenderAspect jobsToExecute context of QAspectThread
QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
{
+ QVector<QAspectJobPtr> renderBinJobs;
+
// Traverse the current framegraph. For each leaf node create a
// RenderView and set its configuration then create a job to
// populate the RenderView with a set of RenderCommands that get
// their details from the RenderNodes that are visible to the
// Camera selected by the framegraph configuration
- QVector<QAspectJobPtr> renderBinJobs;
FrameGraphVisitor visitor;
visitor.traverse(frameGraphRoot(), this, &renderBinJobs);
@@ -842,8 +873,11 @@ bool Renderer::createOrUpdateVAO(RenderCommand *command,
}
// Called by RenderView->submit() in RenderThread context
-void Renderer::executeCommands(const RenderView *rv)
+// Returns true, if all RenderCommands were sent to the GPU
+bool Renderer::executeCommands(const RenderView *rv)
{
+ bool allCommandsIssued = true;
+
// Render drawing commands
const QVector<RenderCommand *> commands = rv->commands();
@@ -867,6 +901,7 @@ void Renderer::executeCommands(const RenderView *rv)
const bool hasGeometryRenderer = rGeometry != Q_NULLPTR && rGeometryRenderer != Q_NULLPTR && !rGeometry->attributes().isEmpty();
if (!hasGeometryRenderer) {
+ allCommandsIssued = false;
qCWarning(Rendering) << "RenderCommand should have a mesh to render";
continue;
}
@@ -935,6 +970,8 @@ void Renderer::executeCommands(const RenderView *rv)
//// Draw Calls
if (primitiveCount && (specified || (vao && vao->isSpecified()))) {
performDraw(rGeometry, rGeometryRenderer, primitiveCount, indexAttribute);
+ } else {
+ allCommandsIssued = false;
}
}
} // end of RenderCommands loop
@@ -955,6 +992,8 @@ void Renderer::executeCommands(const RenderView *rv)
Q_FOREACH (Geometry *geometry, m_dirtyGeometry)
geometry->unsetDirty();
m_dirtyGeometry.clear();
+
+ return allCommandsIssued;
}
Attribute *Renderer::updateBuffersAndAttributes(Geometry *geometry, RenderCommand *command, GLsizei &count, bool forceUpdate)
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index 8cb1f8725..f68d8f9db 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -152,6 +152,11 @@ public:
void setFrameGraphRoot(const Qt3DCore::QNodeId fgRootId) Q_DECL_OVERRIDE;
FrameGraphNode *frameGraphRoot() const Q_DECL_OVERRIDE;
+ void markDirty(BackendNodeDirtySet changes, BackendNode *node) Q_DECL_OVERRIDE;
+ BackendNodeDirtySet dirtyBits() Q_DECL_OVERRIDE;
+ bool shouldRender() Q_DECL_OVERRIDE;
+ void skipNextFrame() Q_DECL_OVERRIDE;
+
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE;
@@ -164,7 +169,7 @@ public:
virtual void setSettings(RendererSettings *settings) Q_DECL_OVERRIDE;
virtual RendererSettings *settings() const Q_DECL_OVERRIDE;
- void executeCommands(const RenderView *rv);
+ bool executeCommands(const RenderView *rv);
Attribute *updateBuffersAndAttributes(Geometry *geometry, RenderCommand *command, GLsizei &count, bool forceUpdate);
void setOpenGLContext(QOpenGLContext *context);
@@ -250,6 +255,8 @@ private:
QVector<Attribute *> m_dirtyAttributes;
QVector<Geometry *> m_dirtyGeometry;
QAtomicInt m_exposed;
+ BackendNodeDirtySet m_changeSet;
+ QAtomicInt m_lastFrameCorrect;
QOpenGLContext *m_glContext;
PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
diff --git a/src/render/backend/renderersettings.cpp b/src/render/backend/renderersettings.cpp
index 148ce16fb..56e705bd7 100644
--- a/src/render/backend/renderersettings.cpp
+++ b/src/render/backend/renderersettings.cpp
@@ -75,6 +75,7 @@ void RendererSettings::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_pickMethod = propertyChange->value().value<QRendererSettings::PickMethod>();
else if (propertyChange->propertyName() == QByteArrayLiteral("pickResult"))
m_pickResultMode = propertyChange->value().value<QRendererSettings::PickResultMode>();
+ markDirty(BackendNodeDirtyFlag::Any);
}
}
diff --git a/src/render/backend/renderqueue.cpp b/src/render/backend/renderqueue.cpp
index 691288fc4..78bebfb42 100644
--- a/src/render/backend/renderqueue.cpp
+++ b/src/render/backend/renderqueue.cpp
@@ -51,6 +51,7 @@ RenderQueue::RenderQueue()
: m_targetRenderViewCount(0)
, m_currentRenderViewCount(0)
, m_currentWorkQueue(1)
+ , m_noRender(false)
{
}
@@ -66,7 +67,15 @@ int RenderQueue::currentRenderViewCount() const
void RenderQueue::reset()
{
m_currentRenderViewCount = 0;
- Q_ASSERT(currentRenderViewCount() == 0);
+ m_targetRenderViewCount = 0;
+ m_currentWorkQueue.clear();
+ m_noRender = false;
+}
+
+void RenderQueue::setNoRender()
+{
+ Q_ASSERT(m_targetRenderViewCount == 0);
+ m_noRender = true;
}
/*!
@@ -76,6 +85,7 @@ void RenderQueue::reset()
*/
bool RenderQueue::queueRenderView(RenderView *renderView, uint submissionOrderIndex)
{
+ Q_ASSERT(!m_noRender);
m_currentWorkQueue[submissionOrderIndex] = renderView;
++m_currentRenderViewCount;
return isFrameQueueComplete();
@@ -96,6 +106,7 @@ QVector<RenderView *> RenderQueue::nextFrameQueue()
*/
void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
{
+ Q_ASSERT(!m_noRender);
m_targetRenderViewCount = targetRenderViewCount;
m_currentWorkQueue.resize(targetRenderViewCount);
}
@@ -107,7 +118,8 @@ void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
*/
bool RenderQueue::isFrameQueueComplete() const
{
- return m_targetRenderViewCount && m_targetRenderViewCount == currentRenderViewCount();
+ return (m_noRender
+ || (m_targetRenderViewCount && m_targetRenderViewCount == currentRenderViewCount()));
}
} // namespace Render
diff --git a/src/render/backend/renderqueue_p.h b/src/render/backend/renderqueue_p.h
index 063b948f2..49316049b 100644
--- a/src/render/backend/renderqueue_p.h
+++ b/src/render/backend/renderqueue_p.h
@@ -76,7 +76,10 @@ public:
QVector<RenderView *> nextFrameQueue();
void reset();
+ void setNoRender();
+
private:
+ bool m_noRender;
int m_targetRenderViewCount;
int m_currentRenderViewCount;
QVector<RenderView *> m_currentWorkQueue;
diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp
index 19bac8a3c..2d7130c23 100644
--- a/src/render/backend/rendertarget.cpp
+++ b/src/render/backend/rendertarget.cpp
@@ -90,6 +90,7 @@ void RenderTarget::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
appendRenderAttachment(propertyChange->value().value<QNodeId>());
else if (e->type() == NodeRemoved && propertyChange->propertyName() == QByteArrayLiteral("attachment"))
removeRenderAttachment(propertyChange->value().value<QNodeId>());
+ markDirty(BackendNodeDirtyFlag::Any);
}
} // namespace Render
diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp
index 603529736..96fe7e991 100644
--- a/src/render/backend/transform.cpp
+++ b/src/render/backend/transform.cpp
@@ -92,6 +92,8 @@ void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_enabled = propertyChange->value().toBool();
}
}
+
+ markDirty(BackendNodeDirtyFlag::Transform);
}
void Transform::updateMatrix()