diff options
author | Antti Määttä <antti.maatta@qt.io> | 2020-01-17 07:57:05 +0200 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2020-01-22 13:28:49 +0200 |
commit | 88849a83a6f9ca3524cf3ba32c3a4ed7e6fabdb9 (patch) | |
tree | cbe79006339b63245381cef7e2822cbbf01dcae9 | |
parent | 7a49e1bdc590f0d3f397dd04355fd165bbd1cb86 (diff) |
Don't render when scene is not changing
Reduce CPU and GPU load by checking if the scene has changed and render
only if it has.
Task-number: QT3DS-4042
Change-Id: I54e447760f04fdad8d64319f326245175b471331
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r-- | src/api/studio3dqml/q3dsrenderer.cpp | 13 | ||||
-rw-r--r-- | src/api/studio3dqml/q3dsrenderer_p.h | 2 | ||||
-rw-r--r-- | src/engine/Qt3DSRenderRuntimeBinding.cpp | 4 | ||||
-rw-r--r-- | src/engine/Qt3DSRuntimeView.cpp | 8 | ||||
-rw-r--r-- | src/engine/Qt3DSRuntimeView.h | 2 | ||||
-rw-r--r-- | src/runtime/Qt3DSApplication.cpp | 13 | ||||
-rw-r--r-- | src/runtime/Qt3DSApplication.h | 2 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp | 5 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp | 13 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h | 4 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp | 5 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h | 2 | ||||
-rw-r--r-- | src/viewer/Qt3DSViewerApp.cpp | 6 | ||||
-rw-r--r-- | src/viewer/Qt3DSViewerApp.h | 4 |
14 files changed, 51 insertions, 32 deletions
diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp index 7d63b30..c902934 100644 --- a/src/api/studio3dqml/q3dsrenderer.cpp +++ b/src/api/studio3dqml/q3dsrenderer.cpp @@ -197,27 +197,32 @@ void Q3DSRenderer::render() // Don't render if the plugin is hidden; however, if hidden, but sure // to process pending commands so we can be shown again. if (m_initialized) { + bool updateAgain = false; if (m_visibleFlag) - draw(); + updateAgain = draw(); else processCommands(); - update(); // mark as dirty to ensure update again + + if (updateAgain) + update(); // mark as dirty to ensure update again } } /** Cause Qt3DS runtime to render content. * Initializes GL and the runtime when called the first time. */ -void Q3DSRenderer::draw() +bool Q3DSRenderer::draw() { + bool ret = true; if (m_runtime && m_runtime->IsInitialised() && m_window) { if (m_initialized) m_runtime->RestoreState(); - m_runtime->Render(); + ret = m_runtime->Render(); m_runtime->SaveState(); m_window->resetOpenGLState(); } + return ret; } bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo) diff --git a/src/api/studio3dqml/q3dsrenderer_p.h b/src/api/studio3dqml/q3dsrenderer_p.h index 0817494..dbc85a2 100644 --- a/src/api/studio3dqml/q3dsrenderer_p.h +++ b/src/api/studio3dqml/q3dsrenderer_p.h @@ -89,7 +89,7 @@ protected: static void onInitHandler(void *userData); static void onUpdateHandler(void *userData); bool initializeRuntime(QOpenGLFramebufferObject *inFbo); - void draw(); + bool draw(); void render() override; void synchronize(QQuickFramebufferObject *inView) override; void releaseRuntime(); diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp index 28c5403..e830e0f 100644 --- a/src/engine/Qt3DSRenderRuntimeBinding.cpp +++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp @@ -1505,9 +1505,11 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, bool firstFrame) override { Qt3DSRenderScene *theFirstScene = nullptr; - for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx) + for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end; ++idx) { if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation) theFirstScene = m_Scenes[idx].second; + m_Scenes[idx].second->TransferDirtyProperties(); + } if (theFirstScene && theFirstScene->m_Presentation) { m_LastRenderedScene = theFirstScene; diff --git a/src/engine/Qt3DSRuntimeView.cpp b/src/engine/Qt3DSRuntimeView.cpp index fd3be65..2335cf1 100644 --- a/src/engine/Qt3DSRuntimeView.cpp +++ b/src/engine/Qt3DSRuntimeView.cpp @@ -179,7 +179,7 @@ public: void Cleanup() override; bool CanRender() override; - void Render() override; + bool Render() override; bool WasLastFrameDirty() override; bool HandleMessage(const QEvent *inEvent) override; @@ -394,8 +394,9 @@ bool CRuntimeView::CanRender() * returns KD_TRUE to call egl_render and swap properly, KD_FALSE if there has been no scene update *or redraw. */ -void CRuntimeView::Render() +bool CRuntimeView::Render() { + bool ret = true; if (m_Application.mPtr == nullptr) { // InitializeGraphics has not been called QT3DS_ASSERT(false); @@ -403,7 +404,7 @@ void CRuntimeView::Render() PerfLogGeneralEvent1(DATALOGGER_FRAME); - m_Application->UpdateAndRender(); + ret = m_Application->UpdateAndRender(); if (m_startupTime < 0 && m_startupTimer && m_startupTimer->isValid()) { @@ -457,6 +458,7 @@ void CRuntimeView::Render() manager.PopState(); } + return ret; } bool CRuntimeView::WasLastFrameDirty() diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h index e3f57d1..e0061b0 100644 --- a/src/engine/Qt3DSRuntimeView.h +++ b/src/engine/Qt3DSRuntimeView.h @@ -185,7 +185,7 @@ public: // loading virtual bool CanRender() = 0; - virtual void Render() = 0; + virtual bool Render() = 0; virtual bool WasLastFrameDirty() = 0; diff --git a/src/runtime/Qt3DSApplication.cpp b/src/runtime/Qt3DSApplication.cpp index cb8f732..79866c5 100644 --- a/src/runtime/Qt3DSApplication.cpp +++ b/src/runtime/Qt3DSApplication.cpp @@ -1031,7 +1031,7 @@ struct SApp : public IApplication } // End QT3DS_PERF_SCOPED_TIMER scope } - void UpdateScenes() { m_RuntimeFactory->GetSceneManager().Update(); } + bool UpdateScenes() { return m_RuntimeFactory->GetSceneManager().Update(); } bool LazyLoadSubPresentations() { @@ -1113,7 +1113,7 @@ struct SApp : public IApplication void ResetDirtyCounter() { m_DirtyCountdown = 5; } // Update all the presentations and render them. - void UpdateAndRender() override + bool UpdateAndRender() override { QT3DS_ASSERT(m_AppLoadContext.mPtr == NULL); m_ThisFrameStartTime = qt3ds::foundation::Time::getCurrentCounterValue(); @@ -1147,15 +1147,17 @@ struct SApp : public IApplication } UpdatePresentations(); - UpdateScenes(); + bool dirty = UpdateScenes(); // If subpresentations changed we need to check if any of them needs to be loaded. if (LazyLoadSubPresentations()) { // Just redo all UpdatePresentations(); - UpdateScenes(); + dirty |= UpdateScenes(); } - + bool renderNextFrame = false; + if (m_LastRenderWasDirty || dirty || m_initialFrame) + renderNextFrame = true; Render(); m_InputEnginePtr->ClearInputFrame(); @@ -1185,6 +1187,7 @@ struct SApp : public IApplication ResetDirtyCounter(); else m_DirtyCountdown = NVMax(0, m_DirtyCountdown - 1); + return renderNextFrame; } // hook this up to -layer-caching. diff --git a/src/runtime/Qt3DSApplication.h b/src/runtime/Qt3DSApplication.h index 72d88a1..ad447f7 100644 --- a/src/runtime/Qt3DSApplication.h +++ b/src/runtime/Qt3DSApplication.h @@ -174,7 +174,7 @@ public: virtual QList<Q3DStudio::CPresentation *> GetPresentationList() = 0; // Update all the presentations and render them. Called exactly once per frame. - virtual void UpdateAndRender() = 0; + virtual bool UpdateAndRender() = 0; virtual bool IsApplicationDirty() = 0; diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp index 0484390..104bd09 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp @@ -253,7 +253,7 @@ namespace render { SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer, id); if (theRenderData) { - theRenderData->PrepareForRender(); + bool needsRender = theRenderData->PrepareForRender(); if (id) { if (m_initialPrepareData.contains(theLayer)) { // Copy dirty state from the initial since the graph is @@ -268,7 +268,8 @@ namespace render { m_initialPrepareData.insert(theLayer, theRenderData); } } - retval = retval || theRenderData->m_LayerPrepResult->m_Flags.WasDirty(); + retval = retval || needsRender + || theRenderData->m_LayerPrepResult->m_Flags.WasDirty() ; } else { QT3DS_ASSERT(false); } diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp index c43ed1a..e453c91 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp @@ -120,9 +120,9 @@ namespace render { if (m_AdvancedBlendDrawTexture) m_AdvancedBlendDrawTexture = NULL; } - void SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions) + bool SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions) { - SLayerRenderPreparationData::PrepareForRender(inViewportDimensions); + bool needsRender = SLayerRenderPreparationData::PrepareForRender(inViewportDimensions); SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult); IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager()); @@ -182,6 +182,9 @@ namespace render { m_Renderer.GetQt3DSContext().GetEffectSystem().GetResourceManager() .DestroyFreeSizedResources(); } + bool isProgressiveAABlendPass = + m_ProgressiveAAPassIndex && m_ProgressiveAAPassIndex < thePrepResult.m_MaxAAPassIndex; + return needsRender || isProgressiveAABlendPass; } NVRenderTextureFormats::Enum SLayerRenderData::GetDepthBufferFormat() @@ -2328,13 +2331,13 @@ void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn, QSize(theCurrentViewport.m_Width, theCurrentViewport.m_Height)); } - void SLayerRenderData::PrepareForRender() + bool SLayerRenderData::PrepareForRender() { // When we render to the scene itself (as opposed to an offscreen buffer somewhere) // then we use the MVP of the layer somewhat. NVRenderRect theViewport = m_Renderer.GetQt3DSContext().GetRenderList().GetViewport(); - PrepareForRender( - QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height)); + return PrepareForRender( + QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height)); } void SLayerRenderData::ResetForFrame() diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h index aa4d456..7520edf 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h @@ -102,10 +102,10 @@ struct AdvancedBlendModes virtual ~SLayerRenderData(); - void PrepareForRender(); + bool PrepareForRender(); // Internal Call - void PrepareForRender(const QSize &inViewportDimensions) override; + bool PrepareForRender(const QSize &inViewportDimensions) override; NVRenderTextureFormats::Enum GetDepthBufferFormat(); NVRenderFrameBufferAttachments::Enum diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp index 1f191b0..821a0b8 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp @@ -1219,12 +1219,12 @@ namespace render { } }; - void SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions) + bool SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions) { QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(), "LayerRenderData: PrepareForRender") if (m_LayerPrepResult.hasValue()) - return; + return false; m_Features.clear(); m_FeatureSetHash = 0; @@ -1576,6 +1576,7 @@ namespace render { GetTransparentRenderableObjects(); GetCameraDirection(); + return wasDirty; } void SLayerRenderPreparationData::ResetForFrame() diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h index 53b60f2..8b1463a 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h @@ -344,7 +344,7 @@ namespace render { // returns true if this object will render something different than it rendered the last // time. - virtual void PrepareForRender(const QSize &inViewportDimensions); + virtual bool PrepareForRender(const QSize &inViewportDimensions); bool CheckLightProbeDirty(SImage &inLightProbe); void AddRenderWidget(IRenderWidget &inWidget); void SetShaderFeature(const char *inName, bool inValue); diff --git a/src/viewer/Qt3DSViewerApp.cpp b/src/viewer/Qt3DSViewerApp.cpp index a4cec7f..ce8163f 100644 --- a/src/viewer/Qt3DSViewerApp.cpp +++ b/src/viewer/Qt3DSViewerApp.cpp @@ -522,8 +522,9 @@ void Q3DSViewerApp::setupSearchPath(std::vector<std::string> &cmdLineArgs) //NvFAppendSearchPath(theModuleDirectory.c_str()); } -void Q3DSViewerApp::Render() +bool Q3DSViewerApp::Render() { + bool ret = true; if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine()) { if (m_Impl.m_appInitSuccessful) { for (QEvent *e : m_Impl.m_pendingEvents) { @@ -535,9 +536,10 @@ void Q3DSViewerApp::Render() HandleController(*m_Impl.m_view); #endif - m_Impl.m_view->Render(); + ret = m_Impl.m_view->Render(); } } + return ret; } void Q3DSViewerApp::SaveState() diff --git a/src/viewer/Qt3DSViewerApp.h b/src/viewer/Qt3DSViewerApp.h index 25d2ed7..db8ba57 100644 --- a/src/viewer/Qt3DSViewerApp.h +++ b/src/viewer/Qt3DSViewerApp.h @@ -257,9 +257,9 @@ public: /* * @brief does the actual scene rendering * - * @return no return + * @return true if the scene needs to be rendered again in next frame */ - void Render(); + bool Render(); /* * @brief handle keyboard input |