QmlDesigner: Cache graphics pipeline in puppet

Caching the graphics pipeline to disk improves puppet reset speed
somewhat when there are complicated 3d scenes.

Task-number: QTBUG-103802
Change-Id: I49b4f1031ab79bb5f660578e3d82806675f468dc
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Miikka Heikkinen
2023-06-06 17:11:01 +03:00
committed by Tim Jenssen
parent d87e420b39
commit 5d8bbe6f5d
3 changed files with 82 additions and 1 deletions

View File

@@ -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

View File

@@ -41,6 +41,14 @@
#include <QtQuick/private/qquickitem_p.h>
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
#include <QDir>
#include <QFile>
#include <QQuickGraphicsConfiguration>
#include <QStandardPaths>
#include <QTimer>
#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<QQuickItem*> subItems(QQuickItem *parentItem)
@@ -188,6 +211,44 @@ bool Qt5NodeInstanceServer::rootIsRenderable3DObject() const
|| 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)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -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]() {

View File

@@ -59,6 +59,8 @@ protected:
void setupScene(const CreateSceneCommand &command) override;
const QList<QQuickItem*> allItems() const;
bool rootIsRenderable3DObject() const;
void savePipelineCacheData();
void setPipelineCacheConfig(QQuickWindow *w);
struct RenderViewData {
QPointer<QQuickWindow> window = nullptr;
@@ -80,6 +82,9 @@ protected:
private:
RenderViewData m_viewData;
QByteArray m_pipelineCacheData;
QString m_pipelineCacheLocation;
QString m_pipelineCacheFile;
std::unique_ptr<QQuickDesignerSupport> m_designerSupport;
QQmlEngine *m_qmlEngine = nullptr;
};