diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-03-27 13:07:28 +0200 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@qt.io> | 2019-03-28 04:17:15 +0000 |
commit | fbb0642d7da044d3f61382e6e2d74e1529dc81e6 (patch) | |
tree | c1826e38741a4fd539eb543dbfb83c8933c4b68a | |
parent | 92079605819c10de4d950ed4a5254da8546b140a (diff) |
Fix async loading
Protect some shared resources with mutexes.
Task-number: QT3DS-3226
Change-Id: I270457f9df336592227b343e0e3c39dab9965410
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r-- | src/runtime/q3dsengine.cpp | 45 | ||||
-rw-r--r-- | src/runtime/q3dsengine_p.h | 3 | ||||
-rw-r--r-- | src/runtime/shadergenerator/q3dsshadermanager.cpp | 2 | ||||
-rw-r--r-- | src/runtime/shadergenerator/q3dsshadermanager_p.h | 2 |
4 files changed, 40 insertions, 12 deletions
diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp index 329a214..ef72f00 100644 --- a/src/runtime/q3dsengine.cpp +++ b/src/runtime/q3dsengine.cpp @@ -903,12 +903,18 @@ void Q3DSEngine::beginAsyncLoad(Q3DSSubPresentation &sp, SceneLoaderAsync *loade qCDebug(lcScene, "Subpresentation %s loaded in %lld ms", qPrintable(loader->pres->subPres.id), timer.elapsed()); }); + QMutexLocker locker(&m_asyncLoadLock); m_asyncSceneLoaders.push_back(loader); } void Q3DSEngine::finishAsyncLoadForSubpresentation(const QString &name) { - for (auto &item : qAsConst(m_asyncSceneLoaders)) { + QVector<SceneLoaderAsync *> loaders; + { + QMutexLocker locker(&m_asyncLoadLock); + loaders = m_asyncSceneLoaders; + } + for (auto &item : qAsConst(loaders)) { if (item->done == false && item->pres->subPres.id == name) { item->future.waitForFinished(); item->done = true; @@ -920,25 +926,35 @@ void Q3DSEngine::finishAsyncLoadForSubpresentation(const QString &name) void Q3DSEngine::finishAsyncLoad(bool wait) { + QThread *currentThread = QThread::currentThread(); + QVector<SceneLoaderAsync *> loaders; + { + QMutexLocker locker(&m_asyncLoadLock); + loaders = m_asyncSceneLoaders; + } if (wait) { - QElapsedTimer timer; - timer.start(); { QFutureSynchronizer<void> sync; - for (auto &item : qAsConst(m_asyncSceneLoaders)) { + for (auto &item : qAsConst(loaders)) { if (item->done == false) sync.addFuture(item->future); } } - for (auto &item : qAsConst(m_asyncSceneLoaders)) { - item->done = true; - item->function(); + for (auto &item : qAsConst(loaders)) { + // Finalize only in target thread to make reparenting events succeed + if (item->targetThread == currentThread) { + item->done = true; + item->function(); + } } } else { - for (auto &item : qAsConst(m_asyncSceneLoaders)) { + for (auto &item : qAsConst(loaders)) { if (!item->done && item->future.isFinished()) { - item->done = true; - item->function(); + // Finalize only in target thread to make reparenting events succeed + if (item->targetThread == currentThread) { + item->done = true; + item->function(); + } } } } @@ -946,8 +962,13 @@ void Q3DSEngine::finishAsyncLoad(bool wait) void Q3DSEngine::loadSlideResources(Q3DSSlide *slide, Q3DSUipPresentation *presentation) { - m_resourceReferenceCounter.handleLoadSlide(slide, presentation); - Q3DSImageManager::instance().beginImageLoad(m_resourceReferenceCounter.createSet); + QSet<QUrl> createSet; + { + QMutexLocker locker(&m_slideResourceMutex); + m_resourceReferenceCounter.handleLoadSlide(slide, presentation); + createSet = m_resourceReferenceCounter.createSet; + } + Q3DSImageManager::instance().beginImageLoad(createSet); } void Q3DSEngine::unloadSlideResources(Q3DSSlide *slide, Q3DSUipPresentation *presentation) diff --git a/src/runtime/q3dsengine_p.h b/src/runtime/q3dsengine_p.h index f72191e..ae76bb4 100644 --- a/src/runtime/q3dsengine_p.h +++ b/src/runtime/q3dsengine_p.h @@ -42,6 +42,7 @@ // #include <QObject> +#include <QThread> #include <QElapsedTimer> #include <QSurfaceFormat> #include <Qt3DCore/QAspectEngine> @@ -471,6 +472,8 @@ private: QVector<SceneLoaderAsync *> m_asyncSceneLoaders; SlideResourceCounter m_resourceReferenceCounter; + QMutex m_slideResourceMutex; + QMutex m_asyncLoadLock; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Q3DSEngine::Flags) diff --git a/src/runtime/shadergenerator/q3dsshadermanager.cpp b/src/runtime/shadergenerator/q3dsshadermanager.cpp index b0ca6ce..a9bfcee 100644 --- a/src/runtime/shadergenerator/q3dsshadermanager.cpp +++ b/src/runtime/shadergenerator/q3dsshadermanager.cpp @@ -56,6 +56,7 @@ Qt3DRender::QShaderProgram *Q3DSShaderManager::generateShaderProgram(Q3DSDefault bool hasTransparency, const Q3DSShaderFeatureSet &featureSet) { + QMutexLocker locker(&m_generatorMutex); Q3DSSubsetMaterialVertexPipeline pipeline(*m_materialShaderGenerator, *m_shaderProgramGenerator, false); return m_materialShaderGenerator->generateShader(material, referencedMaterial, pipeline, featureSet, lights, hasTransparency, QString(QLatin1String("default material %1")).arg(QString::fromLatin1(material.id()))); @@ -68,6 +69,7 @@ Qt3DRender::QShaderProgram *Q3DSShaderManager::generateShaderProgram(Q3DSCustomM const Q3DSShaderFeatureSet &featureSet, const QString &shaderName) { + QMutexLocker locker(&m_generatorMutex); Q3DSCustomMaterialVertexPipeline pipeline(*m_materialShaderGenerator, *m_shaderProgramGenerator, false); return m_customMaterialShaderGenerator->generateShader(material, referencedMaterial, pipeline, featureSet, lights, hasTransparency, shaderName); } diff --git a/src/runtime/shadergenerator/q3dsshadermanager_p.h b/src/runtime/shadergenerator/q3dsshadermanager_p.h index e38ae69..cd7baaa 100644 --- a/src/runtime/shadergenerator/q3dsshadermanager_p.h +++ b/src/runtime/shadergenerator/q3dsshadermanager_p.h @@ -47,6 +47,7 @@ #include "q3dsuippresentation_p.h" #include <Qt3DRender/QShaderProgram> #include <QMap> +#include <QMutex> QT_BEGIN_NAMESPACE @@ -121,6 +122,7 @@ private: QMap<int, Qt3DRender::QShaderProgram *> m_blendOverlayShader; QMap<int, Qt3DRender::QShaderProgram *> m_blendColorBurnShader; QMap<int, Qt3DRender::QShaderProgram *> m_blendColorDodgeShader; + QMutex m_generatorMutex; }; QT_END_NAMESPACE |