diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 0d7b4fa215c..01d5fcd4f60 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -179,6 +179,7 @@ void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url, #else viewData.renderControl = new QQuickRenderControl; viewData.window = new QQuickWindow(viewData.renderControl); + setPipelineCacheConfig(viewData.window); viewData.renderControl->initialize(); #endif QQmlComponent component(engine()); @@ -1130,6 +1131,16 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() m_render3DEditViewTimer.start(17); // 16.67ms = ~60fps, rounds up to 17 --m_need3DEditViewRender; } +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) + else { + static bool pipelineSaved = false; + if (!pipelineSaved) { + // Store pipeline cache for quicker initialization in future + savePipelineCacheData(); + pipelineSaved = true; + } + } +#endif #ifdef FPS_COUNTER // Force constant rendering for accurate fps count diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index 74481d150fc..e5cda877894 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -41,6 +41,14 @@ #include #endif +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) +#include +#include +#include +#include +#include +#endif + namespace QmlDesigner { Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) @@ -90,6 +98,7 @@ void Qt5NodeInstanceServer::initializeView() #else m_viewData.renderControl = new QQuickRenderControl; m_viewData.window = new QQuickWindow(m_viewData.renderControl); + setPipelineCacheConfig(m_viewData.window); m_viewData.renderControl->initialize(); m_qmlEngine = new QQmlEngine; #endif @@ -160,6 +169,20 @@ void Qt5NodeInstanceServer::setupScene(const CreateSceneCommand &command) setupInstances(command); resizeCanvasToRootItem(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) + if (!m_pipelineCacheLocation.isEmpty()) { + QString fileId = command.fileUrl.toLocalFile(); + fileId.remove(':'); + fileId.remove('/'); + fileId.remove('.'); + m_pipelineCacheFile = QStringLiteral("%1/%2").arg(m_pipelineCacheLocation, fileId); + + QFile cacheFile(m_pipelineCacheFile); + if (cacheFile.open(QIODevice::ReadOnly)) + m_pipelineCacheData = cacheFile.readAll(); + } +#endif } QList subItems(QQuickItem *parentItem) @@ -185,7 +208,45 @@ const QList Qt5NodeInstanceServer::allItems() const bool Qt5NodeInstanceServer::rootIsRenderable3DObject() const { return rootNodeInstance().isSubclassOf("QQuick3DNode") - || rootNodeInstance().isSubclassOf("QQuick3DMaterial"); + || rootNodeInstance().isSubclassOf("QQuick3DMaterial"); +} + +void Qt5NodeInstanceServer::savePipelineCacheData() +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) + if (!m_viewData.rhi) + return; + + const QByteArray pipelineData = m_viewData.rhi->pipelineCacheData(); + + if (pipelineData.isEmpty()) + return; + + m_pipelineCacheData = pipelineData; + + QTimer::singleShot(0, this, [this]() { + QFile file(m_pipelineCacheFile); + if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) + file.write(m_pipelineCacheData); + }); +#endif +} + +void Qt5NodeInstanceServer::setPipelineCacheConfig(QQuickWindow *w) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) + // This dummy file is not actually used for cache as we manage cache save/load ourselves, + // but some file needs to be set to enable pipeline caching + const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + m_pipelineCacheLocation = QStringLiteral("%1/%2").arg(cachePath, "pipecache"); + QDir(m_pipelineCacheLocation).mkpath("."); + const QString dummyCache = m_pipelineCacheLocation + "/dummycache"; + + QQuickGraphicsConfiguration config = w->graphicsConfiguration(); + config.setPipelineCacheSaveFile(dummyCache); + config.setAutomaticPipelineCache(false); + w->setGraphicsConfiguration(config); +#endif } bool Qt5NodeInstanceServer::initRhi([[maybe_unused]] RenderViewData &viewData) @@ -204,6 +265,10 @@ bool Qt5NodeInstanceServer::initRhi([[maybe_unused]] RenderViewData &viewData) qWarning() << __FUNCTION__ << "Rhi is null"; return false; } +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1) + if (!m_pipelineCacheData.isEmpty()) + viewData.rhi->setPipelineCacheData(m_pipelineCacheData); +#endif } auto cleanRhiResources = [&viewData]() { diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h index ccbcc5c1e39..b76e639897a 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h @@ -59,6 +59,8 @@ protected: void setupScene(const CreateSceneCommand &command) override; const QList allItems() const; bool rootIsRenderable3DObject() const; + void savePipelineCacheData(); + void setPipelineCacheConfig(QQuickWindow *w); struct RenderViewData { QPointer window = nullptr; @@ -80,6 +82,9 @@ protected: private: RenderViewData m_viewData; + QByteArray m_pipelineCacheData; + QString m_pipelineCacheLocation; + QString m_pipelineCacheFile; std::unique_ptr m_designerSupport; QQmlEngine *m_qmlEngine = nullptr; };