Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
6.2.2
-
-
d7d44783ce (qt/qtdeclarative/dev) d7d44783ce (qt/tqtc-qtdeclarative/dev) 252181407d (qt/qtdeclarative/6.4) d7d44783ce (qt/qtdeclarative/wip/material3) 252181407d (qt/tqtc-qtdeclarative/6.4)
Description
Sometimes FastBlur and OpacityMask(using ShaderEffect internally) are not be drawn correctly on 2 QQuickWindows
In condition:
- the first window with FastBlur and OpacityMask types don't hide.
- the second window(both isPersistentGraphics and isPersistentSceneGraph are false) is shown and hidden repeatably.
- the first window loads a component which has FastBlur and OpacityMask and unloads repeatably.
How to use the attached example:
- wait for the second window to be shown.
- click the first window after the second window is hidden.
- click the first window at appropriate intervals until this problem is reproduced.
The cause of the problem:
QSGRhiShaderMaterialTypeCache is not managed by each a QQuickWidow(or QSGRenderContext). All QQuickWindows use the same QSGRhiShaderMaterialTypeCache. So, in multi windows environment, if a window clear the QSGRhiShaderMaterialTypeCache at some point, ShaderEffect types of another window may be rendered incorrectly.
The simplest way to resolve this problem is:
don't clear QSGRhiShaderMaterialTypeCache in any cases.
// qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor) { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateGraphics()"); if (!rhi) return; if (!window) { qCWarning(QSG_LOG_RENDERLOOP, "QSGThreadedRenderLoop:QSGRenderThread: no window to make current..."); return; } bool wipeSG = inDestructor || !window->isPersistentSceneGraph(); bool wipeGraphics = inDestructor || (wipeSG && !window->isPersistentGraphics()); bool current = true; if (rhi) rhi->makeThreadLocalNativeContextCurrent(); if (Q_UNLIKELY(!current)) { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- cleanup without an OpenGL context"); } QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window); // The canvas nodes must be cleaned up regardless if we are in the destructor.. if (wipeSG) { dd->cleanupNodesOnShutdown(); - #if QT_CONFIG(quick_shadereffect) - QSGRhiShaderEffectNode::cleanupMaterialTypeCache(); - #endif } else { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent SG, avoiding cleanup"); return; }
any good ideas?