diff options
author | Antti Määttä <antti.maatta@qt.io> | 2022-08-25 08:30:55 +0300 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2022-08-29 09:33:59 +0300 |
commit | df02b3f36cfda76d5b027cd34f42266f16b596c2 (patch) | |
tree | d47efcb3c49aa30291b17c27c7074a04be1d1994 /src | |
parent | 4563961362c14aceb47a9a416626d54cec10cd5d (diff) |
Fix memory leak in Qt3DSRendererImplLayerRenderHelper
Two camera nodes are allocated but never freed. Every frame.
This leads to a massive memory consumption.
We are changing the memory model for these two nodes from dynamic memory
allocation to automatic memory allocation. However,
this only works when we keep the SLayerRenderHelper object longer
alive. Otherwise we are holding addresses to temp object longer alive
than allowed.
That why the temporary creation of "thePrepResult" and then copy to the
member "m_LayerPrepResult" will be avoided with this patch.
Which saves us additional code executions.
Change-Id: I564516e20616c2bbb979619cd71f26145e962db7
Reviewed-by: Kaj Grönholm <kaj.gronholm@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Antti Määttä <antti.maatta@qt.io>
Diffstat (limited to 'src')
3 files changed, 41 insertions, 46 deletions
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp index b3a190d..5f290fa 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp @@ -70,8 +70,8 @@ QT3DSVec2 ToRectRelativeCoords(const QT3DSVec2 &inCoords, const NVRenderRectF &i SLayerRenderHelper::SLayerRenderHelper() : m_Layer(nullptr) , m_Camera(nullptr) - , m_CameraLeftEye(nullptr) - , m_CameraRightEye(nullptr) + , m_CameraLeftEye() + , m_CameraRightEye() , m_Offscreen(false) { } @@ -90,8 +90,8 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo , m_PresentationDesignDimensions(inPresentationDesignDimensions) , m_Layer(&inLayer) , m_Camera(nullptr) - , m_CameraLeftEye(nullptr) - , m_CameraRightEye(nullptr) + , m_CameraLeftEye() + , m_CameraRightEye() , m_Offscreen(inOffscreen) , m_ScaleMode(inScaleMode) , m_StereoMode(inStereoMode) @@ -272,9 +272,9 @@ QSize SLayerRenderHelper::GetTextureDimensions() const SCamera *SLayerRenderHelper::GetCamera() { if (m_StereoView == StereoViews::Left) - return m_CameraLeftEye; + return &m_CameraLeftEye; if (m_StereoView == StereoViews::Right) - return m_CameraRightEye; + return &m_CameraRightEye; return m_Camera; } @@ -413,25 +413,20 @@ void SLayerRenderHelper::copyCameraProperties(SCamera *sourceCamera, void SLayerRenderHelper::adjustCameraStereoSeparation() { - if (!m_CameraLeftEye) - m_CameraLeftEye = new SCamera(); - if (!m_CameraRightEye) - m_CameraRightEye = new SCamera(); - // Copy m_Camera properties into left & right cameras - copyCameraProperties(m_Camera, m_CameraLeftEye); - copyCameraProperties(m_Camera, m_CameraRightEye); + copyCameraProperties(m_Camera, &m_CameraLeftEye); + copyCameraProperties(m_Camera, &m_CameraRightEye); // Adjust left & right camera positions by eye separation QT3DSVec3 eyeMove(m_StereoEyeSeparation, 0, 0); QT3DSVec3 camMove = m_Camera->m_GlobalTransform.transform(eyeMove) - m_Camera->m_GlobalTransform.getPosition(); camMove.z *= -1; // Inverse z - m_CameraLeftEye->m_Position -= camMove; - m_CameraLeftEye->m_Flags.SetTransformDirty(true); - m_CameraRightEye->m_Position += camMove; - m_CameraRightEye->m_Flags.SetTransformDirty(true); + m_CameraLeftEye.m_Position -= camMove; + m_CameraLeftEye.m_Flags.SetTransformDirty(true); + m_CameraRightEye.m_Position += camMove; + m_CameraRightEye.m_Flags.SetTransformDirty(true); - m_CameraLeftEye->MarkDirty(); - m_CameraRightEye->MarkDirty(); + m_CameraLeftEye.MarkDirty(); + m_CameraRightEye.MarkDirty(); } diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h index 7d2254a..078c2ec 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h @@ -60,8 +60,8 @@ namespace render { QT3DSVec2 m_PresentationDesignDimensions; SLayer *m_Layer; SCamera *m_Camera; - SCamera *m_CameraLeftEye; - SCamera *m_CameraRightEye; + SCamera m_CameraLeftEye; + SCamera m_CameraRightEye; bool m_Offscreen; NVRenderRectF m_originalViewport; diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp index c2726ab..0ee8aae 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp @@ -1446,7 +1446,6 @@ namespace render { // Uncomment the line below to disable all progressive AA. // maxNumAAPasses = 0; - SLayerRenderPreparationResult thePrepResult; bool hasOffscreenRenderer = GetOffscreenRenderer(); bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f @@ -1506,22 +1505,22 @@ namespace render { maxNumAAPasses = 0; } - thePrepResult = SLayerRenderPreparationResult(SLayerRenderHelper( + m_LayerPrepResult = SLayerRenderPreparationResult(SLayerRenderHelper( theViewport, theScissor, m_Layer.m_Scene->m_Presentation->m_PresentationDimensions, m_Layer, shouldRenderToTexture, m_Renderer.GetQt3DSContext().GetScaleMode(), m_Renderer.GetQt3DSContext().GetStereoMode(), m_Renderer.GetQt3DSContext().GetStereoView(), m_Renderer.GetQt3DSContext().GetStereoEyeSeparation(), m_Renderer.GetQt3DSContext().GetPresentationScaleFactor())); - thePrepResult.m_LastEffect = theLastEffect; - thePrepResult.m_MaxAAPassIndex = maxNumAAPasses; - thePrepResult.m_Flags.SetRequiresDepthTexture(requiresDepthPrepass + m_LayerPrepResult->m_LastEffect = theLastEffect; + m_LayerPrepResult->m_MaxAAPassIndex = maxNumAAPasses; + m_LayerPrepResult->m_Flags.SetRequiresDepthTexture(requiresDepthPrepass || NeedsWidgetTexture()); - thePrepResult.m_Flags.SetShouldRenderToTexture(shouldRenderToTexture); + m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(shouldRenderToTexture); if (m_Renderer.GetContext().GetRenderContextType() != NVRenderContextValues::GLES2) - thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled); + m_LayerPrepResult->m_Flags.SetRequiresSsaoPass(SSAOEnabled); - if (thePrepResult.IsLayerVisible()) { + if (m_LayerPrepResult->IsLayerVisible()) { if (shouldRenderToTexture) { m_Renderer.GetQt3DSContext().GetRenderList().AddRenderTask( CreateRenderToTextureRunnable()); @@ -1530,10 +1529,10 @@ namespace render { m_Renderer.PrepareImageForIbl(*m_Layer.m_LightProbe); wasDataDirty = true; } - if (m_StereoMode != thePrepResult.getStereoMode()) { + if (m_StereoMode != m_LayerPrepResult->getStereoMode()) { // When stereo mode changes we need to mark data dirty // for e.g. temporalAA to render correctly. - m_StereoMode = thePrepResult.getStereoMode(); + m_StereoMode = m_LayerPrepResult->getStereoMode(); wasDataDirty = true; } @@ -1583,10 +1582,10 @@ namespace render { // SetupCameraForRender() sets the camera used for picking and // updates global state e.g. IsGloballyActive() SCameraGlobalCalculationResult theResult = - thePrepResult.SetupCameraForRender(*theCamera); + m_LayerPrepResult->SetupCameraForRender(*theCamera); wasDataDirty = wasDataDirty || theResult.m_WasDirty; if (theCamera->m_Flags.IsGloballyActive()) - m_Camera = thePrepResult.GetCamera(); + m_Camera = m_LayerPrepResult->GetCamera(); if (theResult.m_ComputeFrustumSucceeded == false) { qCCritical(INTERNAL_ERROR, "Failed to calculate camera frustum"); } @@ -1626,7 +1625,7 @@ namespace render { m_Lights.size() - 1, mapSize, mapSize, NVRenderTextureFormats::R16F, 1, mapMode, ShadowFilterValues::NONE); - thePrepResult.m_Flags.SetRequiresShadowMapPass(true); + m_LayerPrepResult->m_Flags.SetRequiresShadowMapPass(true); SetShaderFeature("QT3DS_ENABLE_SSM", true); } } @@ -1695,11 +1694,11 @@ namespace render { m_Camera->CalculateViewProjectionMatrix(m_ViewProjection); if (m_Layer.m_DynamicResize) - calculateDynamicLayerSize(thePrepResult); + calculateDynamicLayerSize(*m_LayerPrepResult); theTextScaleFactor = m_Camera->GetTextScaleFactor( - thePrepResult.GetLayerToPresentationViewport(), - thePrepResult.GetPresentationDesignDimensions()); + m_LayerPrepResult->GetLayerToPresentationViewport(), + m_LayerPrepResult->GetPresentationDesignDimensions()); if (m_Camera->m_EnableFrustumCulling) { SClipPlane nearPlane; QT3DSMat33 theUpper33(m_Camera->m_GlobalTransform.getUpper3x3InverseTranspose()); @@ -1731,16 +1730,16 @@ namespace render { bool renderablesDirty = PrepareRenderablesForRender(m_ViewProjection, m_ClippingFrustum, - theTextScaleFactor, thePrepResult.m_Flags); + theTextScaleFactor, m_LayerPrepResult->m_Flags); wasDataDirty = wasDataDirty || renderablesDirty; - if (thePrepResult.m_Flags.RequiresStencilBuffer()) - thePrepResult.m_Flags.SetShouldRenderToTexture(true); + if (m_LayerPrepResult->m_Flags.RequiresStencilBuffer()) + m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(true); } else { NVRenderRect theViewport = - thePrepResult.GetLayerToPresentationViewport().ToIntegerRect(); + m_LayerPrepResult->GetLayerToPresentationViewport().ToIntegerRect(); bool theScissor = true; NVRenderRect theScissorRect = - thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect(); + m_LayerPrepResult->GetLayerToPresentationScissorRect().ToIntegerRect(); // This happens here because if there are any fancy render steps IRenderList &theRenderList(m_Renderer.GetQt3DSContext().GetRenderList()); NVRenderContext &theContext(m_Renderer.GetContext()); @@ -1770,12 +1769,13 @@ namespace render { wasDataDirty = wasDataDirty || theResult.m_HasChangedSinceLastFrame; } } + } else { + // m_LayerPrepResult must always be set. + m_LayerPrepResult = SLayerRenderPreparationResult(); } wasDirty = wasDirty || wasDataDirty; - thePrepResult.m_Flags.SetWasDirty(wasDirty); - thePrepResult.m_Flags.SetLayerDataDirty(wasDataDirty); - - m_LayerPrepResult = thePrepResult; + m_LayerPrepResult->m_Flags.SetWasDirty(wasDirty); + m_LayerPrepResult->m_Flags.SetLayerDataDirty(wasDataDirty); // Per-frame cache of renderable objects post-sort. GetOpaqueRenderableObjects(); |