diff options
Diffstat (limited to 'src/render/backend')
-rw-r--r-- | src/render/backend/abstractrenderer_p.h | 17 | ||||
-rw-r--r-- | src/render/backend/backendnode.cpp | 6 | ||||
-rw-r--r-- | src/render/backend/backendnode_p.h | 5 | ||||
-rw-r--r-- | src/render/backend/boundingvolumedebug.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/cameralens.cpp | 2 | ||||
-rw-r--r-- | src/render/backend/computejob.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/entity.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/layer.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/nodefunctor_p.h | 1 | ||||
-rw-r--r-- | src/render/backend/renderattachment.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 45 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 9 | ||||
-rw-r--r-- | src/render/backend/renderersettings.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/renderqueue.cpp | 16 | ||||
-rw-r--r-- | src/render/backend/renderqueue_p.h | 3 | ||||
-rw-r--r-- | src/render/backend/rendertarget.cpp | 1 | ||||
-rw-r--r-- | src/render/backend/transform.cpp | 2 |
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() |