From c39067f20be926698d9ae32cc2ddd7981594058c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20Str=C3=B8mme?= <christian.stromme@qt.io>
Date: Mon, 26 Oct 2020 21:18:42 +0100
Subject: [PATCH] Remove the shared pointer around the scene manager

Change-Id: Ic5608d0361b23a2ea045b043227838947bd50ece
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
---
 src/quick3d/qquick3ddefaultmaterial.cpp    | 20 +++----
 src/quick3d/qquick3ddefaultmaterial_p.h    |  2 +-
 src/quick3d/qquick3deffect.cpp             |  4 +-
 src/quick3d/qquick3deffect_p.h             |  2 +-
 src/quick3d/qquick3dmaterial.cpp           | 12 ++--
 src/quick3d/qquick3dmaterial_p.h           |  2 +-
 src/quick3d/qquick3dmodel.cpp              | 10 ++--
 src/quick3d/qquick3dmodel_p.h              |  2 +-
 src/quick3d/qquick3dobject.cpp             | 65 +++++++++++-----------
 src/quick3d/qquick3dobject.h               | 17 +++---
 src/quick3d/qquick3dobject_p.h             | 10 ++--
 src/quick3d/qquick3dprincipledmaterial.cpp | 24 ++++----
 src/quick3d/qquick3dprincipledmaterial_p.h |  2 +-
 src/quick3d/qquick3dsceneenvironment.cpp   |  4 +-
 src/quick3d/qquick3dsceneenvironment_p.h   |  2 +-
 src/quick3d/qquick3dscenerenderer.cpp      |  2 +-
 src/quick3d/qquick3dscenerenderer_p.h      |  4 +-
 src/quick3d/qquick3dtexture.cpp            |  4 +-
 src/quick3d/qquick3dtexture_p.h            |  2 +-
 src/quick3d/qquick3dviewport.cpp           | 28 ++++++----
 tools/shadergen/genshaders.cpp             |  2 +-
 tools/shadergen/genshaders.h               |  2 +-
 22 files changed, 114 insertions(+), 108 deletions(-)

diff --git a/src/quick3d/qquick3ddefaultmaterial.cpp b/src/quick3d/qquick3ddefaultmaterial.cpp
index bdda20f2e..62018320c 100644
--- a/src/quick3d/qquick3ddefaultmaterial.cpp
+++ b/src/quick3d/qquick3ddefaultmaterial.cpp
@@ -1000,19 +1000,19 @@ void QQuick3DDefaultMaterial::itemChange(QQuick3DObject::ItemChange change, cons
         updateSceneManager(value.sceneManager);
 }
 
-void QQuick3DDefaultMaterial::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager)
+void QQuick3DDefaultMaterial::updateSceneManager(QQuick3DSceneManager *sceneManager)
 {
     // Check all the resource value's windows, and update as necessary
     if (sceneManager) {
-        QQuick3DObjectPrivate::refSceneManager(m_diffuseMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_emissiveMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_specularReflectionMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_specularMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_roughnessMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_opacityMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_bumpMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_normalMap, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_translucencyMap, sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_diffuseMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_emissiveMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_specularReflectionMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_specularMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_roughnessMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_opacityMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_bumpMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_normalMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_translucencyMap, *sceneManager);
     } else {
         QQuick3DObjectPrivate::derefSceneManager(m_diffuseMap);
         QQuick3DObjectPrivate::derefSceneManager(m_emissiveMap);
diff --git a/src/quick3d/qquick3ddefaultmaterial_p.h b/src/quick3d/qquick3ddefaultmaterial_p.h
index 0d8cd056a..f3617e40a 100644
--- a/src/quick3d/qquick3ddefaultmaterial_p.h
+++ b/src/quick3d/qquick3ddefaultmaterial_p.h
@@ -232,7 +232,7 @@ private:
         LineWidthDirty = 0x00000800
     };
 
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager);
+    void updateSceneManager(QQuick3DSceneManager *sceneManager);
     Lighting m_lighting = FragmentLighting;
     BlendMode m_blendMode = SourceOver;
     QColor m_diffuseColor;
diff --git a/src/quick3d/qquick3deffect.cpp b/src/quick3d/qquick3deffect.cpp
index b3a942d13..829432e23 100644
--- a/src/quick3d/qquick3deffect.cpp
+++ b/src/quick3d/qquick3deffect.cpp
@@ -1040,11 +1040,11 @@ void QQuick3DEffect::markDirty(QQuick3DEffect::Dirty type)
     }
 }
 
-void QQuick3DEffect::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager)
+void QQuick3DEffect::updateSceneManager(QQuick3DSceneManager *sceneManager)
 {
     if (sceneManager) {
         for (auto it : m_dynamicTextureMaps)
-            QQuick3DObjectPrivate::refSceneManager(it, sceneManager);
+            QQuick3DObjectPrivate::refSceneManager(it, *sceneManager);
     } else {
         for (auto it : m_dynamicTextureMaps)
             QQuick3DObjectPrivate::derefSceneManager(it);
diff --git a/src/quick3d/qquick3deffect_p.h b/src/quick3d/qquick3deffect_p.h
index f35c1da17..d81da180a 100644
--- a/src/quick3d/qquick3deffect_p.h
+++ b/src/quick3d/qquick3deffect_p.h
@@ -91,7 +91,7 @@ private:
 
     quint32 m_dirtyAttributes = 0xffffffff;
 
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager);
+    void updateSceneManager(QQuick3DSceneManager *sceneManager);
 
     friend class QQuick3DSceneRenderer;
     QVector<QQuick3DShaderUtilsRenderPass *> m_passes;
diff --git a/src/quick3d/qquick3dmaterial.cpp b/src/quick3d/qquick3dmaterial.cpp
index 332522485..7ac2f5ae0 100644
--- a/src/quick3d/qquick3dmaterial.cpp
+++ b/src/quick3d/qquick3dmaterial.cpp
@@ -287,15 +287,15 @@ void QQuick3DMaterial::setDynamicTextureMap(QQuick3DTexture *textureMap, const Q
     update();
 }
 
-void QQuick3DMaterial::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager)
+void QQuick3DMaterial::updateSceneManager(QQuick3DSceneManager *sceneManager)
 {
     if (sceneManager) {
-        QQuick3DObjectPrivate::refSceneManager(m_lightmapIndirect, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_lightmapRadiosity, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_lightmapShadow, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_iblProbe, sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_lightmapIndirect, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_lightmapRadiosity, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_lightmapShadow, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_iblProbe, *sceneManager);
         for (auto it : m_dynamicTextureMaps)
-            QQuick3DObjectPrivate::refSceneManager(it, sceneManager);
+            QQuick3DObjectPrivate::refSceneManager(it, *sceneManager);
     } else {
        QQuick3DObjectPrivate::derefSceneManager(m_lightmapIndirect);
        QQuick3DObjectPrivate::derefSceneManager(m_lightmapRadiosity);
diff --git a/src/quick3d/qquick3dmaterial_p.h b/src/quick3d/qquick3dmaterial_p.h
index 68047bc24..4b499dd46 100644
--- a/src/quick3d/qquick3dmaterial_p.h
+++ b/src/quick3d/qquick3dmaterial_p.h
@@ -110,7 +110,7 @@ protected:
 public:
     void setDynamicTextureMap(QQuick3DTexture *textureMap, const QByteArray &name);
 private:
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager);
+    void updateSceneManager(QQuick3DSceneManager *sceneManager);
     QQuick3DTexture *m_lightmapIndirect = nullptr;
     QQuick3DTexture *m_lightmapRadiosity = nullptr;
     QQuick3DTexture *m_lightmapShadow = nullptr;
diff --git a/src/quick3d/qquick3dmodel.cpp b/src/quick3d/qquick3dmodel.cpp
index cfb2d9049..f5e75c87d 100644
--- a/src/quick3d/qquick3dmodel.cpp
+++ b/src/quick3d/qquick3dmodel.cpp
@@ -501,16 +501,16 @@ void QQuick3DModel::markDirty(QQuick3DModel::QSSGModelDirtyType type)
     }
 }
 
-void QQuick3DModel::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager)
+void QQuick3DModel::updateSceneManager(QQuick3DSceneManager *sceneManager)
 {
     if (sceneManager) {
         sceneManager->dirtyBoundingBoxList.append(this);
-        QQuick3DObjectPrivate::refSceneManager(m_skeleton, sceneManager);
-        QQuick3DObjectPrivate::refSceneManager(m_geometry, sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_skeleton, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_geometry, *sceneManager);
         for (Material &mat : m_materials) {
             if (!mat.material->parentItem() && !QQuick3DObjectPrivate::get(mat.material)->sceneManager) {
                 if (!mat.refed) {
-                    QQuick3DObjectPrivate::refSceneManager(mat.material, sceneManager);
+                    QQuick3DObjectPrivate::refSceneManager(mat.material, *sceneManager);
                     mat.refed = true;
                 }
             }
@@ -557,7 +557,7 @@ void QQuick3DModel::qmlAppendMaterial(QQmlListProperty<QQuick3DMaterial> *list,
         } else { // If no valid parent was found, make sure the material refs our scene manager
             const auto &sceneManager = QQuick3DObjectPrivate::get(self)->sceneManager;
             if (sceneManager) {
-                QQuick3DObjectPrivate::get(material)->refSceneManager(sceneManager);
+                QQuick3DObjectPrivate::get(material)->refSceneManager(*sceneManager);
                 // Have to keep track if we called refSceneManager because we
                 // can end up in double deref attempts when a model is going
                 // away, due to updateSceneManager() being called on
diff --git a/src/quick3d/qquick3dmodel_p.h b/src/quick3d/qquick3dmodel_p.h
index 75b2a9f4d..7fb7c9af3 100644
--- a/src/quick3d/qquick3dmodel_p.h
+++ b/src/quick3d/qquick3dmodel_p.h
@@ -165,7 +165,7 @@ private:
 
     quint32 m_dirtyAttributes = 0xffffffff; // all dirty by default
     void markDirty(QSSGModelDirtyType type);
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &sceneManager);
+    void updateSceneManager(QQuick3DSceneManager *sceneManager);
 
     static void qmlAppendMaterial(QQmlListProperty<QQuick3DMaterial> *list, QQuick3DMaterial *material);
     static QQuick3DMaterial *qmlMaterialAt(QQmlListProperty<QQuick3DMaterial> *list, int index);
diff --git a/src/quick3d/qquick3dobject.cpp b/src/quick3d/qquick3dobject.cpp
index 0eb571b4f..5158d1758 100644
--- a/src/quick3d/qquick3dobject.cpp
+++ b/src/quick3d/qquick3dobject.cpp
@@ -104,13 +104,6 @@ QQuick3DObject::QQuick3DObject(QQuick3DObject *parent)
 QQuick3DObject::~QQuick3DObject()
 {
     Q_D(QQuick3DObject);
-    if (d->windowRefCount > 1)
-        d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
-    if (d->parentItem)
-        setParentItem(nullptr);
-    else if (d->sceneManager)
-        QQuick3DObjectPrivate::derefSceneManager(this);
-
     // XXX todo - optimize
     while (!d->childItems.isEmpty())
         d->childItems.constFirst()->setParentItem(nullptr);
@@ -119,6 +112,17 @@ QQuick3DObject::~QQuick3DObject()
     d->_stateGroup = nullptr;
     delete d->contentItem2d;
     d->contentItem2d = nullptr;
+
+    if (d->parentItem)
+        setParentItem(nullptr);
+
+    if (d->sceneRefCount > 1) {
+        qWarning("Unexpected ref. count %d\n", d->sceneRefCount);
+        d->sceneRefCount = 1; // Make sure the scene is set to null in next call to derefSceneManager().
+    }
+
+    if (!d->parentItem && d->sceneManager)
+        QQuick3DObjectPrivate::derefSceneManager(this);
 }
 
 void QQuick3DObject::update()
@@ -192,7 +196,7 @@ void QQuick3DObject::setParentItem(QQuick3DObject *parentItem)
             QQuick3DObjectPrivate::derefSceneManager(this);
         d->parentItem = parentItem;
         if (parentSceneManager)
-            QQuick3DObjectPrivate::refSceneManager(this, parentSceneManager);
+            QQuick3DObjectPrivate::refSceneManager(this, *parentSceneManager);
     }
 
     d->dirty(QQuick3DObjectPrivate::ParentChanged);
@@ -279,14 +283,14 @@ void QQuick3DObject::preSync()
 
 void QQuick3DObjectPrivate::updatePropertyListener(QQuick3DObject *newO,
                                                    QQuick3DObject *oldO,
-                                                   const QSharedPointer<QQuick3DSceneManager> &window,
+                                                   QQuick3DSceneManager *sceneManager,
                                                    const QByteArray &propertyKey,
                                                    ConnectionMap &connections,
                                                    const std::function<void(QQuick3DObject *)> &callFn)
 {
     // disconnect previous destruction listener
     if (oldO) {
-        if (window)
+        if (sceneManager)
             QQuick3DObjectPrivate::derefSceneManager(oldO);
 
         auto connection = connections.find(propertyKey);
@@ -298,8 +302,8 @@ void QQuick3DObjectPrivate::updatePropertyListener(QQuick3DObject *newO,
 
     // listen for new map's destruction
     if (newO) {
-        if (window)
-            QQuick3DObjectPrivate::refSceneManager(newO, window);
+        if (sceneManager)
+            QQuick3DObjectPrivate::refSceneManager(newO, *sceneManager);
         auto connection = QObject::connect(newO, &QObject::destroyed, [callFn](){
             callFn(nullptr);
         });
@@ -313,7 +317,7 @@ QQuick3DObjectPrivate::QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type t)
     , nextDirtyItem(nullptr)
     , prevDirtyItem(nullptr)
     , sceneManager(nullptr)
-    , windowRefCount(0)
+    , sceneRefCount(0)
     , parentItem(nullptr)
     , sortedChildItems(&childItems)
     , subFocusItem(nullptr)
@@ -978,28 +982,27 @@ void QQuick3DObjectPrivate::markSortedChildrenDirty(QQuick3DObject *child)
     Q_UNUSED(child);
 }
 
-void QQuick3DObjectPrivate::refSceneManager(const QSharedPointer<QQuick3DSceneManager> &c)
+void QQuick3DObjectPrivate::refSceneManager(QQuick3DSceneManager &c)
 {
-    // An item needs a window if it is referenced by another item which has a window.
+    // An item needs a scene manager if it is referenced by another item which has a scene manager.
     // Typically the item is referenced by a parent, but can also be referenced by a
-    // ShaderEffect or ShaderEffectSource. 'windowRefCount' counts how many items with
-    // a window is referencing this item. When the reference count goes from zero to one,
-    // or one to zero, the window of this item is updated and propagated to the children.
-    // As long as the reference count stays above zero, the window is unchanged.
-    // refWindow() increments the reference count.
-    // derefWindow() decrements the reference count.
+    // ShaderEffect or ShaderEffectSource. 'sceneRefCount' counts how many items with
+    // a scene manager is referencing this item. When the reference count goes from zero to one,
+    // or one to zero, the scene manager of this item is updated and propagated to the children.
+    // As long as the reference count stays above zero, the scene manager is unchanged.
+    // refSceneManager() increments the reference count.
+    // derefSceneManager() decrements the reference count.
 
     Q_Q(QQuick3DObject);
-    Q_ASSERT((sceneManager != nullptr) == (windowRefCount > 0));
-    Q_ASSERT(c);
-    if (++windowRefCount > 1) {
-        if (c != sceneManager)
+    Q_ASSERT((sceneManager != nullptr) == (sceneRefCount > 0));
+    if (++sceneRefCount > 1) {
+        if (&c != sceneManager)
             qWarning("QSSGObject: Cannot use same item on different windows at the same time.");
         return; // Window already set.
     }
 
     Q_ASSERT(sceneManager == nullptr);
-    sceneManager = c;
+    sceneManager = &c;
 
     //    if (polishScheduled)
     //        QSSGWindowPrivate::get(window)->itemsToPolish.append(q);
@@ -1014,7 +1017,7 @@ void QQuick3DObjectPrivate::refSceneManager(const QSharedPointer<QQuick3DSceneMa
 
     dirty(Window);
 
-    itemChange(QQuick3DObject::ItemSceneChange, c);
+    itemChange(QQuick3DObject::ItemSceneChange, &c);
 }
 
 void QQuick3DObjectPrivate::derefSceneManager()
@@ -1024,8 +1027,8 @@ void QQuick3DObjectPrivate::derefSceneManager()
     if (!sceneManager)
         return; // This can happen when destroying recursive shader effect sources.
 
-    if (--windowRefCount > 0)
-        return; // There are still other references, so don't set window to null yet.
+    if (--sceneRefCount > 0)
+        return; // There are still other references, so don't set the scene manager to null yet.
 
     removeFromDirtyList();
     if (sceneManager) {
@@ -1038,8 +1041,6 @@ void QQuick3DObjectPrivate::derefSceneManager()
     if (!parentItem)
         sceneManager->parentlessItems.remove(q);
 
-    sceneManager.reset();
-
     spatialNode = nullptr;
 
     for (int ii = 0; ii < childItems.count(); ++ii) {
@@ -1047,6 +1048,8 @@ void QQuick3DObjectPrivate::derefSceneManager()
         QQuick3DObjectPrivate::derefSceneManager(child);
     }
 
+    sceneManager = nullptr;
+
     dirty(Window);
 
     itemChange(QQuick3DObject::ItemSceneChange, sceneManager);
diff --git a/src/quick3d/qquick3dobject.h b/src/quick3d/qquick3dobject.h
index c19b3d5e9..759d43627 100644
--- a/src/quick3d/qquick3dobject.h
+++ b/src/quick3d/qquick3dobject.h
@@ -82,19 +82,16 @@ public:
         ItemEnabledHasChanged // value.boolValue
     };
 
-    struct ItemChangeData {
+    union ItemChangeData {
         ItemChangeData(QQuick3DObject *v) : item(v) {}
-        ItemChangeData(const QSharedPointer<QQuick3DSceneManager> &v) : sceneManager(v) {}
+        ItemChangeData(QQuick3DSceneManager *v) : sceneManager(v) {}
         ItemChangeData(qreal v) : realValue(v) {}
         ItemChangeData(bool v) : boolValue(v) {}
-        ~ItemChangeData() {}
-
-        QSharedPointer<QQuick3DSceneManager> sceneManager;
-        union {
-            QQuick3DObject *item;
-            qreal realValue;
-            bool boolValue;
-        };
+
+        QQuick3DObject *item;
+        QQuick3DSceneManager *sceneManager;
+        qreal realValue;
+        bool boolValue;
     };
 
     explicit QQuick3DObject(QQuick3DObject *parent = nullptr);
diff --git a/src/quick3d/qquick3dobject_p.h b/src/quick3d/qquick3dobject_p.h
index 542a5708c..d86e9afc6 100644
--- a/src/quick3d/qquick3dobject_p.h
+++ b/src/quick3d/qquick3dobject_p.h
@@ -94,7 +94,7 @@ public:
 
     static void updatePropertyListener(QQuick3DObject *newO,
                                        QQuick3DObject *oldO,
-                                       const QSharedPointer<QQuick3DSceneManager> &window,
+                                       QQuick3DSceneManager *sceneManager,
                                        const QByteArray &propertyKey,
                                        ConnectionMap &connections,
                                        const std::function<void(QQuick3DObject *o)> &callFn);
@@ -233,8 +233,8 @@ public:
 
     void setCulled(bool);
 
-    QSharedPointer<QQuick3DSceneManager> sceneManager;
-    int windowRefCount;
+    QQuick3DSceneManager *sceneManager = nullptr;
+    int sceneRefCount;
 
     QQuick3DObject *parentItem;
 
@@ -247,10 +247,10 @@ public:
 
     void markSortedChildrenDirty(QQuick3DObject *child);
 
-    void refSceneManager(const QSharedPointer<QQuick3DSceneManager> &);
+    void refSceneManager(QQuick3DSceneManager &);
     void derefSceneManager();
 
-    static void refSceneManager(QQuick3DObject *obj,const QSharedPointer<QQuick3DSceneManager> &mgr)
+    static void refSceneManager(QQuick3DObject *obj, QQuick3DSceneManager &mgr)
     {
         if (obj)
             QQuick3DObjectPrivate::get(obj)->refSceneManager(mgr);
diff --git a/src/quick3d/qquick3dprincipledmaterial.cpp b/src/quick3d/qquick3dprincipledmaterial.cpp
index a75cbfc31..bf4bea46d 100644
--- a/src/quick3d/qquick3dprincipledmaterial.cpp
+++ b/src/quick3d/qquick3dprincipledmaterial.cpp
@@ -1007,19 +1007,19 @@ void QQuick3DPrincipledMaterial::itemChange(QQuick3DObject::ItemChange change, c
         updateSceneManager(value.sceneManager);
 }
 
-void QQuick3DPrincipledMaterial::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &window)
+void QQuick3DPrincipledMaterial::updateSceneManager(QQuick3DSceneManager *sceneManager)
 {
-    // Check all the resource value's windows, and update as necessary
-    if (window) {
-        QQuick3DObjectPrivate::refSceneManager(m_baseColorMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_emissiveMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_specularReflectionMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_specularMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_roughnessMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_opacityMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_normalMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_metalnessMap, window);
-        QQuick3DObjectPrivate::refSceneManager(m_occlusionMap, window);
+    // Check all the resource value's scene manager, and update as necessary.
+    if (sceneManager) {
+        QQuick3DObjectPrivate::refSceneManager(m_baseColorMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_emissiveMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_specularReflectionMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_specularMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_roughnessMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_opacityMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_normalMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_metalnessMap, *sceneManager);
+        QQuick3DObjectPrivate::refSceneManager(m_occlusionMap, *sceneManager);
     } else {
         QQuick3DObjectPrivate::derefSceneManager(m_baseColorMap);
         QQuick3DObjectPrivate::derefSceneManager(m_emissiveMap);
diff --git a/src/quick3d/qquick3dprincipledmaterial_p.h b/src/quick3d/qquick3dprincipledmaterial_p.h
index b9aa518f7..da9870fb2 100644
--- a/src/quick3d/qquick3dprincipledmaterial_p.h
+++ b/src/quick3d/qquick3dprincipledmaterial_p.h
@@ -231,7 +231,7 @@ private:
         LineWidthDirty = 0x00001000
     };
 
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &window);
+    void updateSceneManager(QQuick3DSceneManager *window);
 
     // Note: The default values for properties that are also present in
     // QSSGShaderCustomMaterialAdapter must match the values there, because a
diff --git a/src/quick3d/qquick3dsceneenvironment.cpp b/src/quick3d/qquick3dsceneenvironment.cpp
index 92106b2d1..b1c654158 100644
--- a/src/quick3d/qquick3dsceneenvironment.cpp
+++ b/src/quick3d/qquick3dsceneenvironment.cpp
@@ -680,10 +680,10 @@ void QQuick3DSceneEnvironment::itemChange(QQuick3DObject::ItemChange change, con
         updateSceneManager(value.sceneManager);
 }
 
-void QQuick3DSceneEnvironment::updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &manager)
+void QQuick3DSceneEnvironment::updateSceneManager(QQuick3DSceneManager *manager)
 {
     if (manager)
-        QQuick3DObjectPrivate::refSceneManager(m_lightProbe, manager);
+        QQuick3DObjectPrivate::refSceneManager(m_lightProbe, *manager);
     else
         QQuick3DObjectPrivate::derefSceneManager(m_lightProbe);
 }
diff --git a/src/quick3d/qquick3dsceneenvironment_p.h b/src/quick3d/qquick3dsceneenvironment_p.h
index 61a775708..cb12019fa 100644
--- a/src/quick3d/qquick3dsceneenvironment_p.h
+++ b/src/quick3d/qquick3dsceneenvironment_p.h
@@ -218,7 +218,7 @@ private:
     static int qmlEffectsCount(QQmlListProperty<QQuick3DEffect> *list);
     static void qmlClearEffects(QQmlListProperty<QQuick3DEffect> *list);
 
-    void updateSceneManager(const QSharedPointer<QQuick3DSceneManager> &manager);
+    void updateSceneManager(QQuick3DSceneManager *manager);
 
     QQuick3DEnvironmentAAModeValues m_antialiasingMode = NoAA;
     QQuick3DEnvironmentAAQualityValues m_antialiasingQuality = High;
diff --git a/src/quick3d/qquick3dscenerenderer.cpp b/src/quick3d/qquick3dscenerenderer.cpp
index fe3058ec5..ab6f03d03 100644
--- a/src/quick3d/qquick3dscenerenderer.cpp
+++ b/src/quick3d/qquick3dscenerenderer.cpp
@@ -565,7 +565,7 @@ void QQuick3DSceneRenderer::synchronize(QQuick3DViewport *item, const QSize &siz
         m_importSceneManager->updateBoundingBoxes(m_sgContext->bufferManager());
         m_importSceneManager->updateDirtyNodes();
     } else {
-        m_importSceneManager.clear();
+        m_importSceneManager = nullptr;
     }
 
     // Generate layer node
diff --git a/src/quick3d/qquick3dscenerenderer_p.h b/src/quick3d/qquick3dscenerenderer_p.h
index 89396cd9a..92659b646 100644
--- a/src/quick3d/qquick3dscenerenderer_p.h
+++ b/src/quick3d/qquick3dscenerenderer_p.h
@@ -86,8 +86,8 @@ private:
     void addNodeToLayer(QSSGRenderNode *node);
     void removeNodeFromLayer(QSSGRenderNode *node);
     QSSGRef<QSSGRenderContextInterface> m_sgContext;
-    QSharedPointer<QQuick3DSceneManager> m_sceneManager;
-    QSharedPointer<QQuick3DSceneManager> m_importSceneManager;
+    QQuick3DSceneManager *m_sceneManager = nullptr;
+    QQuick3DSceneManager *m_importSceneManager = nullptr;
     QSSGRenderLayer *m_layer = nullptr;
     QSize m_surfaceSize;
     void *data = nullptr;
diff --git a/src/quick3d/qquick3dtexture.cpp b/src/quick3d/qquick3dtexture.cpp
index 172101ce1..24fb76bf9 100644
--- a/src/quick3d/qquick3dtexture.cpp
+++ b/src/quick3d/qquick3dtexture.cpp
@@ -983,7 +983,7 @@ void QQuick3DTexture::itemChange(QQuick3DObject::ItemChange change, const QQuick
         if (m_textureData) {
             const auto &sceneManager = value.sceneManager;
             if (sceneManager)
-                QQuick3DObjectPrivate::refSceneManager(m_textureData, sceneManager);
+                QQuick3DObjectPrivate::refSceneManager(m_textureData, *sceneManager);
             else
                 QQuick3DObjectPrivate::derefSceneManager(m_textureData);
         }
@@ -1037,7 +1037,7 @@ void QQuick3DTexture::createLayerTexture()
     connect(
             layer,
             &QObject::destroyed,
-            manager.data(),
+            manager,
             [manager, layer]() {
                 // this is on the render thread so all borked threading-wise (all data here is gui thread stuff...) but will survive
                 manager->qsgDynamicTextures.removeAll(layer);
diff --git a/src/quick3d/qquick3dtexture_p.h b/src/quick3d/qquick3dtexture_p.h
index 15ca5274c..f7c342bb7 100644
--- a/src/quick3d/qquick3dtexture_p.h
+++ b/src/quick3d/qquick3dtexture_p.h
@@ -221,7 +221,7 @@ private:
                               | DirtyFlags(DirtyFlag::TextureDataDirty);
     QMetaObject::Connection m_textureProviderConnection;
     QMetaObject::Connection m_textureUpdateConnection;
-    QSharedPointer<QQuick3DSceneManager> m_sceneManagerForLayer;
+    QQuick3DSceneManager *m_sceneManagerForLayer = nullptr;
     QQuickItem *m_initializedSourceItem = nullptr;
     void trySetSourceParent();
     QHash<QByteArray, QMetaObject::Connection> m_connections;
diff --git a/src/quick3d/qquick3dviewport.cpp b/src/quick3d/qquick3dviewport.cpp
index 58db81e6b..a3ddf3ab3 100644
--- a/src/quick3d/qquick3dviewport.cpp
+++ b/src/quick3d/qquick3dviewport.cpp
@@ -100,9 +100,10 @@ QQuick3DViewport::QQuick3DViewport(QQuickItem *parent)
     m_sceneRoot = new QQuick3DSceneRootNode(this);
     m_environment = new QQuick3DSceneEnvironment(m_sceneRoot);
     m_renderStats = new QQuick3DRenderStats(m_sceneRoot);
-    QSharedPointer<QQuick3DSceneManager> sceneManager(new QQuick3DSceneManager(m_sceneRoot));
-    QQuick3DObjectPrivate::get(m_sceneRoot)->refSceneManager(sceneManager);
-    connect(QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager.data(), &QQuick3DSceneManager::needsUpdate,
+    QQuick3DSceneManager *sceneManager = new QQuick3DSceneManager(m_sceneRoot);
+    QQuick3DObjectPrivate::get(m_sceneRoot)->refSceneManager(*sceneManager);
+    Q_ASSERT(sceneManager == QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager);
+    connect(sceneManager, &QQuick3DSceneManager::needsUpdate,
             this, &QQuickItem::update);
 }
 
@@ -110,11 +111,14 @@ QQuick3DViewport::~QQuick3DViewport()
 {
     for (const auto &connection : qAsConst(m_connections))
         disconnect(connection);
-    // Do not delete scenemanager along with sceneroot
-    auto &sceneManager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager;
+    auto sceneManager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager;
     if (sceneManager)
         sceneManager->setParent(nullptr);
+
     delete m_sceneRoot;
+    m_sceneRoot = nullptr;
+
+    delete sceneManager;
 
     // m_directRenderer must be destroyed on the render thread at the proper time, not here.
     // That's handled in releaseResources() + upon sceneGraphInvalidated
@@ -501,15 +505,17 @@ void QQuick3DViewport::setImportScene(QQuick3DNode *inScene)
 
     m_importScene = inScene;
     if (m_importScene) {
-        // If the referenced scene doesn't have a manager, add one (scenes defined outside of an view3d)
+        // If the referenced scene doesn't have a manager use the one from the sceen root (scenes defined outside of an view3d)
         auto privateObject = QQuick3DObjectPrivate::get(m_importScene);
         if (!privateObject->sceneManager) {
-            QSharedPointer<QQuick3DSceneManager> manager(new QQuick3DSceneManager);
-            manager->setWindow(window());
-            privateObject->refSceneManager(manager);
+            if (QQuick3DSceneManager *manager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager) {
+                manager->setWindow(window());
+                privateObject->refSceneManager(*manager);
+            }
+            Q_ASSERT(privateObject->sceneManager);
         }
 
-        connect(privateObject->sceneManager.data(), &QQuick3DSceneManager::needsUpdate,
+        connect(privateObject->sceneManager, &QQuick3DSceneManager::needsUpdate,
                 this, &QQuickItem::update);
 
         QQuick3DNode *scene = inScene;
@@ -518,7 +524,7 @@ void QQuick3DViewport::setImportScene(QQuick3DNode *inScene)
             scene = rn ? rn->view3D()->importScene() : nullptr;
 
             if (scene) {
-                connect(QQuick3DObjectPrivate::get(scene)->sceneManager.data(),
+                connect(QQuick3DObjectPrivate::get(scene)->sceneManager,
                         &QQuick3DSceneManager::needsUpdate,
                         this, &QQuickItem::update);
             }
diff --git a/tools/shadergen/genshaders.cpp b/tools/shadergen/genshaders.cpp
index b5df490ba..c8d985cd7 100644
--- a/tools/shadergen/genshaders.cpp
+++ b/tools/shadergen/genshaders.cpp
@@ -77,7 +77,7 @@ static QQsbShaderFeatureSet toQsbShaderFeatureSet(const ShaderFeatureSetList &fe
 
 GenShaders::GenShaders(const QString &sourceDir)
 {
-    sceneManager.reset(new QQuick3DSceneManager);
+    sceneManager = new QQuick3DSceneManager;
 
     rhi = QRhi::create(QRhi::Null, nullptr);
     QRhiCommandBuffer *cb;
diff --git a/tools/shadergen/genshaders.h b/tools/shadergen/genshaders.h
index 6ec249c0c..ec458f152 100644
--- a/tools/shadergen/genshaders.h
+++ b/tools/shadergen/genshaders.h
@@ -56,7 +56,7 @@ struct GenShaders
     QRhi *rhi = nullptr;
     QSSGRef<QSSGRenderContextInterface> renderContext;
 
-    QSharedPointer<QQuick3DSceneManager> sceneManager;
+    QQuick3DSceneManager *sceneManager = nullptr;
 
     static void processFoo(const QSSGRef<QSSGRenderContextInterface> &renderContext, const MaterialParser::SceneData &sceneData);
 };
-- 
GitLab