diff options
author | Antti Määttä <antti.maatta@qt.io> | 2019-05-20 15:34:05 +0300 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2019-05-22 13:32:14 +0300 |
commit | a32488dcdcd84eea08b3070395009a8af6caedec (patch) | |
tree | 2ff3289f66e80e857748156d57fa158be0592f91 | |
parent | 5f7a8fba3b56ec0fc44e2cd3ba4fc91195054fed (diff) |
Load slide images in background thread
Use the existing batch loading to load images in a slide in the
background.
Task-number: QT3DS-3385
Change-Id: I68097afb94f643696d0783c9980553c31c80d6cb
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Jari Karppinen <jari.karppinen@qt.io>
Reviewed-by: Jere Tuliniemi <jere.tuliniemi@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
10 files changed, 97 insertions, 29 deletions
diff --git a/src/Authoring/Studio/Render/StudioRendererTranslation.cpp b/src/Authoring/Studio/Render/StudioRendererTranslation.cpp index d2e92f67..82678986 100644 --- a/src/Authoring/Studio/Render/StudioRendererTranslation.cpp +++ b/src/Authoring/Studio/Render/StudioRendererTranslation.cpp @@ -2439,7 +2439,7 @@ void STranslation::Render(int inWidgetId, bool inDrawGuides, bool scenePreviewPa if (m_Scene) { // Note that begin frame is called before we allocate the bounding box and axis widgets so // that we can take advantage of the renderer's per-frame-allocator. - m_Context.BeginFrame(); + m_Context.BeginFrame(true); qt3dsdm::TInstanceHandleList theHandles = m_Doc.GetSelectedValue().GetSelectedInstances(); diff --git a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp index 1ffb7141..2c15e0e5 100644 --- a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp +++ b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp @@ -200,6 +200,11 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene qt3ds::NVAllocatorCallback &allocator() override { return m_LoadData->m_AutoAllocator; } Q3DStudio::IPresentation &GetPresentation() override { return *m_RuntimePresentation; } + bool preferKtx() const override + { + return m_Presentation->m_preferKTX; + } + // Update really just adds objects to the dirty set bool Update() { @@ -1555,7 +1560,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, return theResult; } - Q3DStudio::BOOL RenderPresentation(Q3DStudio::IPresentation *inPresentation) override + Q3DStudio::BOOL RenderPresentation(Q3DStudio::IPresentation *inPresentation, + bool firstFrame) override { Qt3DSRenderScene *theFirstScene = nullptr; for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx) @@ -1584,7 +1590,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, (QT3DSU32)theFirstScene->m_Presentation->m_PresentationDimensions.y)); } - m_Context->m_Context->BeginFrame(); + m_Context->m_Context->BeginFrame(firstFrame); m_Context->m_RenderContext->ResetBlendState(); // How exactly does this work, I have no idea. diff --git a/src/Runtime/Source/runtime/Qt3DSApplication.cpp b/src/Runtime/Source/runtime/Qt3DSApplication.cpp index 1b518e9f..3549957f 100644 --- a/src/Runtime/Source/runtime/Qt3DSApplication.cpp +++ b/src/Runtime/Source/runtime/Qt3DSApplication.cpp @@ -79,6 +79,7 @@ #include "Qt3DSQmlElementHelper.h" #include "Qt3DSRenderBufferManager.h" #include "Qt3DSRenderRenderList.h" +#include "Qt3DSRenderImageBatchLoader.h" #include <QtCore/qlibraryinfo.h> #include <QtCore/qpair.h> #include <QtCore/qdir.h> @@ -303,40 +304,85 @@ struct SSlideResourceCounter } }; -struct STextureUploadRenderTask : public IRenderTask +struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener { + IImageBatchLoader &m_batchLoader; IBufferManager &m_bufferManager; + NVRenderContextType m_type; + bool m_preferKtx; QSet<QString> m_uploadSet; + QSet<QString> m_uploadWaitSet; QSet<QString> m_deleteSet; QMutex m_updateMutex; + QHash<QT3DSU32, QSet<QString>> m_batches; + volatile QT3DSI32 mRefCount; - STextureUploadRenderTask(IBufferManager &mgr) - : m_bufferManager(mgr) + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_bufferManager.GetStringTable() + .GetAllocator()) + + STextureUploadRenderTask(IImageBatchLoader &loader, IBufferManager &mgr, + NVRenderContextType type, bool preferKtx) + : m_batchLoader(loader), m_bufferManager(mgr), m_type(type), m_preferKtx(preferKtx), + mRefCount(0) { } void Run() override { QMutexLocker loc(&m_updateMutex); - m_bufferManager.loadSet(m_uploadSet); + if (!m_uploadSet.isEmpty()) { + nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(), + "TempSourcePathList"); + for (auto &s : qAsConst(m_uploadSet)) + sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s)); + QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(), + this, m_type, m_preferKtx); + if (id) + m_batches[id] = m_uploadSet; + } + if (!m_uploadWaitSet.isEmpty()) { + nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(), + "TempSourcePathList"); + for (auto &s : qAsConst(m_uploadWaitSet)) + sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s)); + QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(), + this, m_type, m_preferKtx); + if (id) { + m_batchLoader.BlockUntilLoaded(id); + m_bufferManager.loadSet(m_uploadWaitSet); + } + } m_bufferManager.unloadSet(m_deleteSet); } - void add(const QSet<QString> &set) + void add(const QSet<QString> &set, bool wait) { QMutexLocker loc(&m_updateMutex); - m_uploadSet.unite(set); + if (wait) + m_uploadWaitSet.unite(set); + else + m_uploadSet.unite(set); m_deleteSet.subtract(set); } void remove(const QSet<QString> &set) { QMutexLocker loc(&m_updateMutex); m_uploadSet.subtract(set); + m_uploadWaitSet.subtract(set); m_deleteSet.unite(set); } bool persistent() const override { return true; } + void OnImageLoadComplete(CRegisteredString inPath, ImageLoadResult::Enum inResult) override + { + Q_UNUSED(inPath); + Q_UNUSED(inResult); + } + void OnImageBatchComplete(QT3DSU64 inBatch) override + { + m_bufferManager.loadSet(m_batches[inBatch]); + } }; struct SApp; @@ -562,7 +608,7 @@ struct SApp : public IApplication // the name of the file without extension. eastl::string m_Filename; Q3DSVariantConfig m_variantConfig; - QScopedPointer<STextureUploadRenderTask> m_uploadRenderTask; + NVScopedRefCounted<STextureUploadRenderTask> m_uploadRenderTask; qt3ds::foundation::NVScopedReleasable<IRuntimeMetaData> m_MetaData; nvvector<eastl::pair<SBehaviorAsset, bool>> m_Behaviors; @@ -598,6 +644,8 @@ struct SApp : public IApplication DataInputMap m_dataInputDefs; + bool m_initialFrame = true; + SSlideResourceCounter m_resourceCounter; QSet<QString> m_createSet; @@ -958,8 +1006,11 @@ struct SApp : public IApplication { SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(), "Render"); CPresentation *pres = GetPrimaryPresentation(); - if (pres) - m_LastRenderWasDirty = m_RuntimeFactory->GetSceneManager().RenderPresentation(pres); + if (pres) { + m_LastRenderWasDirty = m_RuntimeFactory->GetSceneManager() + .RenderPresentation(pres, m_initialFrame); + m_initialFrame = false; + } } void ResetDirtyCounter() { m_DirtyCountdown = 5; } @@ -1049,7 +1100,7 @@ struct SApp : public IApplication //////////////////////////////////////////////////////////////////////////////// void loadComponentSlideResources(TElement *component, CPresentation *presentation, int index, - const QString slideName) + const QString slideName, bool wait) { if (m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager() .isReloadableResourcesEnabled()) { @@ -1063,7 +1114,7 @@ struct SApp : public IApplication qCInfo(PERF_INFO) << "Load component slide resources: " << completeName; m_resourceCounter.handleLoadSlide(completeName, key, slidesystem); if (m_uploadRenderTask) - m_uploadRenderTask->add(m_resourceCounter.createSet); + m_uploadRenderTask->add(m_resourceCounter.createSet, wait); else m_createSet.unite(m_resourceCounter.createSet); } @@ -1141,7 +1192,7 @@ struct SApp : public IApplication QVector<TElement *> components; thePresentation->GetRoot()->findComponents(components); for (auto &component : qAsConst(components)) - loadComponentSlideResources(component, thePresentation, 0, "Master"); + loadComponentSlideResources(component, thePresentation, 0, "Master", true); return true; } @@ -1448,7 +1499,7 @@ struct SApp : public IApplication QString slideName; int index; if (presentationComponentSlide(slide, pres, component, slideName, index)) - loadComponentSlideResources(component, pres, index, slideName); + loadComponentSlideResources(component, pres, index, slideName, false); } void unloadSlide(const QString &slide) override @@ -1472,7 +1523,7 @@ struct SApp : public IApplication const QString &elementPath, int slideIndex, const QString &slideName) override { - loadComponentSlideResources(component, presentation, slideIndex, slideName); + loadComponentSlideResources(component, presentation, slideIndex, slideName, true); } void ComponentSlideExited(Q3DStudio::CPresentation *presentation, @@ -1556,9 +1607,13 @@ struct SApp : public IApplication m_AudioPlayer.SetPlayer(inAudioPlayer); - m_uploadRenderTask.reset(new STextureUploadRenderTask( - m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager())); - m_uploadRenderTask->add(m_createSet); + auto &rc = m_RuntimeFactory->GetQt3DSRenderContext(); + m_uploadRenderTask = QT3DS_NEW(m_CoreFactory->GetFoundation().getAllocator(), + STextureUploadRenderTask(rc.GetImageBatchLoader(), + rc.GetBufferManager(), + rc.GetRenderContext().GetRenderContextType(), + GetPrimaryPresentation()->GetScene()->preferKtx())); + m_uploadRenderTask->add(m_createSet, true); m_RuntimeFactory->GetQt3DSRenderContext().GetRenderList() .AddRenderTask(*m_uploadRenderTask); m_createSet.clear(); diff --git a/src/Runtime/Source/runtime/Qt3DSIScene.h b/src/Runtime/Source/runtime/Qt3DSIScene.h index 83347e11..7494ab0f 100644 --- a/src/Runtime/Source/runtime/Qt3DSIScene.h +++ b/src/Runtime/Source/runtime/Qt3DSIScene.h @@ -157,6 +157,8 @@ public: // Base Interface virtual void Release() = 0; + virtual bool preferKtx() const = 0; + virtual qt3ds::NVAllocatorCallback &allocator() = 0; }; diff --git a/src/Runtime/Source/runtime/Qt3DSSceneManager.h b/src/Runtime/Source/runtime/Qt3DSSceneManager.h index 7b8a4aab..7d8297f4 100644 --- a/src/Runtime/Source/runtime/Qt3DSSceneManager.h +++ b/src/Runtime/Source/runtime/Qt3DSSceneManager.h @@ -143,7 +143,7 @@ public: // Presentations public: // Update Cycle virtual BOOL Update() = 0; - virtual BOOL RenderPresentation(IPresentation *inPresentation) = 0; + virtual BOOL RenderPresentation(IPresentation *inPresentation, bool firstFrame) = 0; virtual void OnViewResize(INT32 inViewWidth, INT32 inViewHeight) = 0; virtual void GetViewSize(INT32 &outWidth, INT32 &outHeight) = 0; diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp index d41454e6..33e1bf6c 100644 --- a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp +++ b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp @@ -623,7 +623,7 @@ struct SRenderContext : public IQt3DSRenderContext // Trying to avoid duplicate code as much as possible. SBeginFrameResult m_BeginFrameResult; - void BeginFrame() override + void BeginFrame(bool firstFrame) override { m_PreRenderPresentationDimensions = m_PresentationDimensions; QSize thePresentationDimensions(m_PreRenderPresentationDimensions); @@ -682,7 +682,7 @@ struct SRenderContext : public IQt3DSRenderContext m_TextRenderer->BeginFrame(); if (m_TextTextureCache) m_TextTextureCache->BeginFrame(); - m_ImageBatchLoader->BeginFrame(); + m_ImageBatchLoader->BeginFrame(firstFrame); } QT3DSVec2 GetPresentationScaleFactor() const override { return m_PresentationScale; } diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h index d5e54fb2..302571d2 100644 --- a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h +++ b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h @@ -207,7 +207,7 @@ namespace render { // and the topmost presentation dimensions. Expects there to be exactly one presentation // dimension pushed at this point. // This also starts a render target in the render graph. - virtual void BeginFrame() = 0; + virtual void BeginFrame(bool firstFrame) = 0; // This runs through the added tasks in reverse order. This is used to render dependencies // before rendering to the main render target. diff --git a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp index 8f1cb14f..e2cfbed1 100644 --- a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp +++ b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp @@ -323,7 +323,7 @@ struct SBatchLoader : public IImageBatchLoader theBatch->m_LoadEvent.wait(200); theBatch->m_LoadEvent.reset(); } - BeginFrame(); + BeginFrame(true); } } void ImageLoaded(SLoadingImage &inImage, SLoadedTexture *inTexture) @@ -335,7 +335,7 @@ struct SBatchLoader : public IImageBatchLoader inImage.m_Batch->m_LoadEvent.set(); } // These are called by the render context, users don't need to call this. - void BeginFrame() override + void BeginFrame(bool firstFrame) override { TScopedLock __loaderLock(m_LoaderMutex); // Pass 1 - send out all image loaded signals @@ -346,8 +346,13 @@ struct SBatchLoader : public IImageBatchLoader m_LoadedImages[idx].m_Batch->IncrementFinalizedImageCount(); if (m_LoadedImages[idx].m_Batch->IsFinalizedFinished()) m_FinishedBatches.push_back(m_LoadedImages[idx].m_Batch->m_BatchId); + if (!firstFrame) + break; } - m_LoadedImages.clear(); + if (firstFrame) + m_LoadedImages.clear(); + else if (m_LoadedImages.size()) + m_LoadedImages.erase(m_LoadedImages.begin()); // pass 2 - clean up any existing batches. for (QT3DSU32 idx = 0, end = m_FinishedBatches.size(); idx < end; ++idx) { TImageLoaderBatchMap::iterator theIter = m_Batches.find(m_FinishedBatches[idx]); diff --git a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h index d45123f1..bc1773ce 100644 --- a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h +++ b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h @@ -82,7 +82,7 @@ namespace render { virtual void BlockUntilLoaded(TImageBatchId inId) = 0; // These are called by the render context, users don't need to call this. - virtual void BeginFrame() = 0; + virtual void BeginFrame(bool firstFrame) = 0; virtual void EndFrame() = 0; static IImageBatchLoader &CreateBatchLoader(NVFoundationBase &inFoundation, diff --git a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp index b1993021..11762733 100644 --- a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp +++ b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp @@ -682,7 +682,7 @@ SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &in NVScopedRefCounted<IRefCountedInputStream> theStream( inFactory.GetStreamForFile(preferKTX ? ktxSource : inPath, true)); if (!theStream.mPtr) { - if (!preferKTX) + if (preferKTX) theStream = inFactory.GetStreamForFile(inPath, true); else return nullptr; |