diff options
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/studio3d/q3dscommandqueue.cpp | 49 | ||||
-rw-r--r-- | src/api/studio3d/q3dscommandqueue_p.h | 59 | ||||
-rw-r--r-- | src/api/studio3d/q3dspresentation.cpp | 259 | ||||
-rw-r--r-- | src/api/studio3d/q3dspresentation.h | 8 | ||||
-rw-r--r-- | src/api/studio3d/q3dspresentation_p.h | 10 | ||||
-rw-r--r-- | src/api/studio3d/q3dssurfaceviewer.cpp | 1 | ||||
-rw-r--r-- | src/api/studio3dqml/q3dsrenderer.cpp | 26 | ||||
-rw-r--r-- | src/api/studio3dqml/q3dsruntimeInitializerthread.cpp | 5 | ||||
-rw-r--r-- | src/api/studio3dqml/q3dsruntimeInitializerthread_p.h | 3 | ||||
-rw-r--r-- | src/api/studio3dqml/q3dsstudio3d.cpp | 25 |
10 files changed, 364 insertions, 81 deletions
diff --git a/src/api/studio3d/q3dscommandqueue.cpp b/src/api/studio3d/q3dscommandqueue.cpp index 8ec07ee..06bd73f 100644 --- a/src/api/studio3d/q3dscommandqueue.cpp +++ b/src/api/studio3d/q3dscommandqueue.cpp @@ -46,27 +46,6 @@ QString ElementCommand::toString() const } CommandQueue::CommandQueue() - : m_visibleChanged(false) - , m_scaleModeChanged(false) - , m_stereoModeChanged(false) - , m_stereoEyeSeparationChanged(false) - , m_shadeModeChanged(false) - , m_showRenderStatsChanged(false) - , m_matteColorChanged(false) - , m_sourceChanged(false) - , m_variantListChanged(false) - , m_globalAnimationTimeChanged(false) - , m_delayedLoadingChanged(false) - , m_visible(false) - , m_scaleMode(Q3DSViewerSettings::ScaleModeCenter) - , m_stereoMode(Q3DSViewerSettings::StereoModeMono) - , m_stereoEyeSeparation(0.4) - , m_shadeMode(Q3DSViewerSettings::ShadeModeShaded) - , m_showRenderStats(false) - , m_matteColor(Qt::black) - , m_delayedLoading(false) - , m_matteEnabled(false) - , m_size(0) { qRegisterMetaType<CommandType>(); } @@ -212,6 +191,25 @@ ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandTy return cmd; } +ElementCommand &CommandQueue::queueCommand(CommandType commandType) +{ + ElementCommand &cmd = nextFreeCommand(); + + cmd.m_commandType = commandType; + + return cmd; +} + +ElementCommand &CommandQueue::queueCommand(CommandType commandType, bool value) +{ + ElementCommand &cmd = nextFreeCommand(); + + cmd.m_commandType = commandType; + cmd.m_boolValue = value; + + return cmd; +} + void CommandQueue::copyCommands(CommandQueue &fromQueue) { m_visibleChanged = m_visibleChanged || fromQueue.m_visibleChanged; @@ -228,6 +226,7 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue) = m_globalAnimationTimeChanged || fromQueue.m_globalAnimationTimeChanged; m_delayedLoadingChanged = m_delayedLoadingChanged || fromQueue.m_delayedLoadingChanged; m_matteEnabledChanged = m_matteEnabledChanged || fromQueue.m_matteEnabledChanged; + m_shaderCacheFileChanged = m_shaderCacheFileChanged || fromQueue.m_shaderCacheFileChanged; if (fromQueue.m_visibleChanged) m_visible = fromQueue.m_visible; @@ -253,6 +252,8 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue) m_delayedLoading = fromQueue.m_delayedLoading; if (fromQueue.m_matteEnabledChanged) m_matteEnabled = fromQueue.m_matteEnabled; + if (fromQueue.m_shaderCacheFileChanged) + m_shaderCacheFile = fromQueue.m_shaderCacheFile; // Pending queue may be synchronized multiple times between queue processing, so let's append // to the existing queue rather than clearing it. @@ -313,9 +314,12 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue) case CommandType_RequestSlideInfo: case CommandType_UnloadSlide: case CommandType_PreloadSlide: + queueCommand(source.m_elementPath, source.m_commandType); + break; case CommandType_RequestDataInputs: case CommandType_RequestDataOutputs: - queueCommand(source.m_elementPath, source.m_commandType); + case CommandType_RequestExportShaderCache: + queueCommand(source.m_commandType, source.m_boolValue); break; default: queueCommand(QString(), CommandType_Invalid, false); @@ -339,6 +343,7 @@ void CommandQueue::clear(bool deleteCommandData) m_globalAnimationTimeChanged = false; m_delayedLoadingChanged = false; m_matteEnabledChanged = false; + m_shaderCacheFileChanged = false; if (deleteCommandData) { for (int i = 0; i < m_size; ++i) { diff --git a/src/api/studio3d/q3dscommandqueue_p.h b/src/api/studio3d/q3dscommandqueue_p.h index de1f2b1..2f98ed6 100644 --- a/src/api/studio3d/q3dscommandqueue_p.h +++ b/src/api/studio3d/q3dscommandqueue_p.h @@ -75,13 +75,14 @@ enum CommandType { CommandType_DeleteMaterials, CommandType_CreateMeshes, CommandType_DeleteMeshes, + CommandType_PreloadSlide, + CommandType_UnloadSlide, // Requests CommandType_RequestSlideInfo, CommandType_RequestDataInputs, - CommandType_PreloadSlide, - CommandType_UnloadSlide, - CommandType_RequestDataOutputs + CommandType_RequestDataOutputs, + CommandType_RequestExportShaderCache }; class Q_STUDIO3D_EXPORT ElementCommand @@ -132,34 +133,38 @@ public: ElementCommand &queueCommand(const QString &elementPath, CommandType commandType); ElementCommand &queueCommand(const QString &elementPath, CommandType commandType, void *commandData); + ElementCommand &queueCommand(CommandType commandType); + ElementCommand &queueCommand(CommandType commandType, bool value); void copyCommands(CommandQueue &fromQueue); - bool m_visibleChanged; - bool m_scaleModeChanged; - bool m_stereoModeChanged; - bool m_stereoEyeSeparationChanged; - bool m_shadeModeChanged; - bool m_showRenderStatsChanged; - bool m_matteColorChanged; - bool m_sourceChanged; - bool m_variantListChanged; - bool m_globalAnimationTimeChanged; - bool m_delayedLoadingChanged; - bool m_matteEnabledChanged; - - bool m_visible; - Q3DSViewerSettings::ScaleMode m_scaleMode; - Q3DSViewerSettings::StereoMode m_stereoMode; - double m_stereoEyeSeparation; - Q3DSViewerSettings::ShadeMode m_shadeMode; - bool m_showRenderStats; - QColor m_matteColor; + bool m_visibleChanged = false; + bool m_scaleModeChanged = false; + bool m_stereoModeChanged = false; + bool m_stereoEyeSeparationChanged = false; + bool m_shadeModeChanged = false; + bool m_showRenderStatsChanged = false; + bool m_matteColorChanged = false; + bool m_sourceChanged = false; + bool m_variantListChanged = false; + bool m_globalAnimationTimeChanged = false; + bool m_delayedLoadingChanged = false; + bool m_matteEnabledChanged = false; + bool m_shaderCacheFileChanged = false; + + bool m_visible = false; + Q3DSViewerSettings::ScaleMode m_scaleMode = Q3DSViewerSettings::ScaleModeCenter; + Q3DSViewerSettings::StereoMode m_stereoMode = Q3DSViewerSettings::StereoModeMono; + double m_stereoEyeSeparation = 0.4; + Q3DSViewerSettings::ShadeMode m_shadeMode = Q3DSViewerSettings::ShadeModeShaded; + bool m_showRenderStats = false; + QColor m_matteColor = QColor(Qt::black); QUrl m_source; QStringList m_variantList; - qint64 m_globalAnimationTime; - bool m_delayedLoading; - bool m_matteEnabled; + qint64 m_globalAnimationTime = 0; + bool m_delayedLoading = false; + bool m_matteEnabled = false; + QUrl m_shaderCacheFile; void clear(bool deleteCommandData); int size() const { return m_size; } @@ -170,7 +175,7 @@ private: ElementCommand &nextFreeCommand(); CommandList m_elementCommands; - int m_size; + int m_size = 0; }; QT_END_NAMESPACE diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp index beb0394..e782cfe 100644 --- a/src/api/studio3d/q3dspresentation.cpp +++ b/src/api/studio3d/q3dspresentation.cpp @@ -34,10 +34,15 @@ #include "q3dsdatainput_p.h" #include "q3dsdataoutput_p.h" #include "q3dsgeometry_p.h" +#include "studioutils_p.h" #include <QtCore/qdebug.h> #include <QtCore/qsettings.h> #include <QtCore/qcoreapplication.h> +#include <QtCore/qsavefile.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qdir.h> #include <QtGui/qevent.h> QT_BEGIN_NAMESPACE @@ -607,6 +612,161 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath) } /*! + \qmlmethod Presentation::exportShaderCache(url shaderCacheFile, bool binaryShaders) + + Writes the shaders currently in use to the file specified by \a shaderCacheFile URL. + If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise, + the shader source code is exported. + + Exporting shader cache is an asynchronous operation. + The shaderCacheExported signal is emitted when the export is complete. + + Exporting shader cache should be done at the point of application execution where all the + shaders that should be initialized at application startup have been initialized. + + \note Exporting shader cache is only supported if no shaders have been originally loaded + from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file + with shaderCacheFile property allows shader generation. + + \sa shaderCacheFile, shaderCacheExported + */ +/*! + Writes the shaders currently in use to the file specified by \a shaderCacheFile URL. + If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise, + the shader source code is exported. + + The shaderCacheExported signal is emitted when the export is complete. + + Exporting shader cache should be done at the point of application execution where all the + shaders that should be initialized at application startup have been initialized. + + \note Exporting shader cache is only supported if no shaders have been originally loaded + from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file + with shaderCacheFile property allows shader generation. + + \sa shaderCacheFile, shaderCacheExported + */ +void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binaryShaders) +{ + d_ptr->exportShaderCache(binaryShaders, false); + if (d_ptr->m_commandQueue) + d_ptr->m_shaderCacheWritePending = shaderCacheFile; + else + d_ptr->writeShaderCache(shaderCacheFile); +} + +/*! + \qmlmethod Presentation::exportShaderCache(bool binaryShaders) + + Exports the shaders currently in use and dumps the resulting cache encoded with base64 into + stderr. This function is provided as a means to extract the shader cache from environments + without a writable disk. The base64 output needs to be converted back to binary + representation to be usable as a shader cache file. The Qt 3D Studio Viewer provides + a command line parameter \c --convert-shader-cache to do this conversion. + + If \a binaryShaders property is \c{true}, precompiled shaders are exported. + Otherwise, the shader source code is exported. + + Exporting shader cache is an asynchronous operation. + The shaderCacheExported signal is emitted when the export is complete. + + Exporting shader cache should be done at the point of application execution where all the + shaders that should be initialized at application startup have been initialized. + + \note Exporting shader cache is only supported if no shaders have been originally loaded + from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file + with shaderCacheFile property allows shader generation. + + \sa shaderCacheFile, shaderCacheExported + */ +/*! + Exports the shaders currently in use and dumps the resulting cache encoded with base64 into + stderr. This function is provided as a means to extract the shader cache from environments + without a writable disk. The base64 output needs to be converted back to binary + representation to be usable as a shader cache file. The Qt 3D Studio Viewer provides + a command line parameter \c --convert-shader-cache to do this conversion. + + If \a binaryShaders property is \c{true}, precompiled shaders are exported. + Otherwise, the shader source code is exported. + + The shaderCacheExported signal is emitted when the export is complete. + + Exporting shader cache should be done at the point of application execution where all the + shaders that should be initialized at application startup have been initialized. + + \note Exporting shader cache is only supported if no shaders have been originally loaded + from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file + with shaderCacheFile property allows shader generation. + + \sa shaderCacheFile, shaderCacheExported + */ +void Q3DSPresentation::exportShaderCache(bool binaryShaders) +{ + d_ptr->exportShaderCache(binaryShaders, true); +} + +/*! + \qmlproperty url Presentation::shaderCacheFile + + Specifies the shader cache file to be used for initial shader initialization. + This property value must be set before the presentation is shown. + Using cached shaders improves presentation initialization speed. + + If this property is not set, all shaders are generated normally. + + If this property points to a valid shader cache file, new shader cache generation is not + supported. + + The default value is an empty url. + + \sa exportShaderCache(), shaderCacheExport + */ +/*! + Specifies the shader cache file to be used for initial shader initialization. + This property value must be set before the presentation is shown. + Using cached shaders improves presentation initialization speed. + + If this property is not set, all shaders are generated normally. + + If this property points to a valid shader cache file, new shader cache generation is not + supported. + + The default value is an empty url. + + \sa exportShaderCache(), shaderCacheExport + */ +QUrl Q3DSPresentation::shaderCacheFile() const +{ + return d_ptr->m_shaderCacheFile; +} + +void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName) +{ + if (d_ptr->m_shaderCacheFile != fileName) { + d_ptr->setShaderCacheFile(fileName); + Q_EMIT shaderCacheFileChanged(fileName); + } +} + +/*! + \qmlsignal Presentation::shaderCacheExported(bool success) + + Emitted when a shader cache export is completed. The parameter \a success indicates whether + or not the export was successful. + + \sa shaderCacheExport(), shaderCacheFile + */ + +/*! + \fn Q3DSPresentation::shaderCacheExported(bool success) + + Emitted when a shader cache export is completed. The parameter \a success indicates whether + or not the export was successful. + + \sa shaderCacheExport(), shaderCacheFile + */ + +/*! This function is for backwards compatibility. We recommend using \l{DataInput}s to control slide changes. \l{DataInput} provides stronger contract between the design and code as it avoids use of elementPath (a reference to design's internal structure). @@ -1626,11 +1786,12 @@ void Q3DSPresentationPrivate::setCommandQueue(CommandQueue *queue) if (m_commandQueue) { setDelayedLoading(m_delayedLoading); setVariantList(m_variantList); + setShaderCacheFile(m_shaderCacheFile); // Queue a request ASAP for datainputs and outputs defined in UIA file so that // getDataInputs has up-to-date info at the earliest and that data outputs // connect from source to destination - m_commandQueue->queueCommand({}, CommandType_RequestDataInputs); - m_commandQueue->queueCommand({}, CommandType_RequestDataOutputs); + m_commandQueue->queueCommand(CommandType_RequestDataInputs); + m_commandQueue->queueCommand(CommandType_RequestDataOutputs); setSource(m_source); } } @@ -1655,12 +1816,21 @@ void Q3DSPresentationPrivate::setDataInputDirty(const QString &name, bool dirty) m_dataInputs[name]->d_ptr->setDirty(dirty); } +void Q3DSPresentationPrivate::setShaderCacheFile(const QUrl &fileName) +{ + m_shaderCacheFile = fileName; + if (m_commandQueue) { + m_commandQueue->m_shaderCacheFile = fileName; + m_commandQueue->m_shaderCacheFileChanged = true; + } +} + void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, void *requestData) { + QVariantList *response = reinterpret_cast<QVariantList *>(requestData); + switch (commandType) { case CommandType_RequestDataInputs: { - QVariantList *response = reinterpret_cast<QVariantList *>(requestData); - for (int i = 0; i < response->size(); ++i) { // Check and append to QML-side list if the (UIA) presentation has additional datainputs // that are not explicitly defined in QML code. @@ -1680,27 +1850,100 @@ void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, vo m_dataInputs[receivedDI->name()]->d_ptr->m_metadata = receivedDI->d_ptr->m_metadata; } } - delete response; Q_EMIT q_ptr->dataInputsReady(); break; } case CommandType_RequestDataOutputs: { - QVariantList *response = reinterpret_cast<QVariantList *>(requestData); - for (int i = 0; i < response->size(); ++i) { // Check and append to QML-side list if the (UIA) presentation has additional // dataoutputs that are not explicitly defined in QML code. if (!m_dataOutputs.contains(response->at(i).value<QString>())) registerDataOutput(new Q3DSDataOutput(response->at(i).value<QString>(), nullptr)); } - delete response; Q_EMIT q_ptr->dataOutputsReady(); break; } + case CommandType_RequestExportShaderCache: { + if (response->size() > 0) + m_shaderCacheExport = response->at(0).toByteArray(); + if (!m_shaderCacheExport.isEmpty()) + m_shaderCacheExport = qCompress(m_shaderCacheExport); + if (!m_shaderCacheWritePending.isEmpty()) { + writeShaderCache(m_shaderCacheWritePending); + m_shaderCacheWritePending.clear(); + } + if (m_shaderCacheDumpPending) { + m_shaderCacheDumpPending = false; + dumpShaderCache(); + } + break; + } default: Q_ASSERT(false); break; } + delete response; +} + +// Writes current shader cache to the specified file in UTF-8 format +void Q3DSPresentationPrivate::writeShaderCache(const QUrl &shaderCacheFile) +{ + if (m_shaderCacheExport.isEmpty()) + return; // Warning is already printed by export function + const QString filePath = shaderCacheFile.toLocalFile(); + QSaveFile file(filePath); + QFileInfo(filePath).dir().mkpath(QStringLiteral(".")); + bool success = false; + if (file.open(QIODevice::WriteOnly) && file.write(m_shaderCacheExport) != -1) { + file.commit(); + success = true; + } else { + qWarning() << __FUNCTION__ << "Warning: Failed to write shader cache:" + << shaderCacheFile << file.errorString(); + } + Q_EMIT q_ptr->shaderCacheExported(success); +} + +QByteArray Q3DSPresentationPrivate::loadShaderCache() const +{ + if (!m_shaderCacheFile.isEmpty()) { + QFile file(Q3DSUtils::urlToLocalFileOrQrc(m_shaderCacheFile)); + if (file.open(QIODevice::ReadOnly)) + return qUncompress(file.readAll()); + + qWarning() << __FUNCTION__ << "Warning: Failed to read shader cache:" + << m_shaderCacheFile << file.errorString(); + } + return {}; +} + +void Q3DSPresentationPrivate::exportShaderCache(bool binaryShaders, bool dumpCache) +{ + if (m_viewerApp) { + m_shaderCacheExport = m_viewerApp->exportShaderCache(binaryShaders); + if (!m_shaderCacheExport.isEmpty()) + m_shaderCacheExport = qCompress(m_shaderCacheExport); + if (dumpCache) + dumpShaderCache(); + } else if (m_commandQueue) { + m_commandQueue->queueCommand(CommandType_RequestExportShaderCache, binaryShaders); + m_shaderCacheDumpPending = dumpCache; + } +} + +void Q3DSPresentationPrivate::dumpShaderCache() +{ + if (!m_shaderCacheExport.isEmpty()) { + // Can't just dump the whole thing into a single qWarning() call, since at least on + // windows long strings are not printed out. qWarning() is used to make the dump go to + // stderr, which is less likely to get cluttered with other messages. + qWarning() << "-- Shader cache base64 dump start --"; + const QString cacheDump = QString::fromLatin1(m_shaderCacheExport.toBase64()); + for (int i = 0; i < cacheDump.size(); i += 100) + qWarning().noquote() << cacheDump.mid(i, 100); + qWarning() << "-- Shader cache base64 dump end --"; + } + Q_EMIT q_ptr->shaderCacheExported(!m_shaderCacheExport.isEmpty()); } // Doc note: The ownership of the registered scenes remains with the caller, who needs to diff --git a/src/api/studio3d/q3dspresentation.h b/src/api/studio3d/q3dspresentation.h index 91e76c5..af84073 100644 --- a/src/api/studio3d/q3dspresentation.h +++ b/src/api/studio3d/q3dspresentation.h @@ -58,6 +58,7 @@ class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject Q_PROPERTY(QStringList createdElements READ createdElements NOTIFY elementsCreated) Q_PROPERTY(QStringList createdMaterials READ createdMaterials NOTIFY materialsCreated) Q_PROPERTY(QStringList createdMeshes READ createdMeshes NOTIFY meshesCreated) + Q_PROPERTY(QUrl shaderCacheFile READ shaderCacheFile WRITE setShaderCacheFile NOTIFY shaderCacheFileChanged ) public: explicit Q3DSPresentation(QObject *parent = nullptr); @@ -90,6 +91,10 @@ public: Q_INVOKABLE void preloadSlide(const QString &elementPath); Q_INVOKABLE void unloadSlide(const QString &elementPath); + Q_INVOKABLE void exportShaderCache(const QUrl &shaderCacheFile, bool binaryShaders); + Q_INVOKABLE void exportShaderCache(bool binaryShaders); + QUrl shaderCacheFile() const; + // Input event handlers void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); @@ -131,6 +136,7 @@ public Q_SLOTS: void fireEvent(const QString &elementPath, const QString &eventName); void setGlobalAnimationTime(qint64 milliseconds); void setDataInputValue(const QString &name, const QVariant &value, bool force = false); + void setShaderCacheFile(const QUrl &fileName); Q_SIGNALS: void variantListChanged(const QStringList &variantList); @@ -144,6 +150,8 @@ Q_SIGNALS: void elementsCreated(const QStringList &elementPaths, const QString &error); void materialsCreated(const QStringList &materialNames, const QString &error); void meshesCreated(const QStringList &meshNames, const QString &error); + void shaderCacheFileChanged(const QUrl &fileName); + void shaderCacheExported(bool success); private: Q_DISABLE_COPY(Q3DSPresentation) diff --git a/src/api/studio3d/q3dspresentation_p.h b/src/api/studio3d/q3dspresentation_p.h index 5ade08e..45231b4 100644 --- a/src/api/studio3d/q3dspresentation_p.h +++ b/src/api/studio3d/q3dspresentation_p.h @@ -73,6 +73,7 @@ public: void setDelayedLoading(bool enable); void setDataInputsChanged(bool changed); void setDataInputDirty(const QString &name, bool dirty); + void setShaderCacheFile(const QUrl &fileName); void registerElement(Q3DSElement *element); void unregisterElement(Q3DSElement *element); @@ -100,6 +101,11 @@ public: void requestResponseHandler(CommandType commandType, void *requestData); + void writeShaderCache(const QUrl &shaderCacheFile); + QByteArray loadShaderCache() const; + void exportShaderCache(bool binaryShaders, bool dumpCache); + void dumpShaderCache(); + public Q_SLOTS: void handleSlideEntered(const QString &elementPath, unsigned int index, const QString &name); void handleDataOutputValueUpdate(const QString &name, const QVariant &newValue); @@ -124,6 +130,10 @@ private: QStringList m_createdMaterials; QStringList m_createdMeshes; bool m_dataInputsChanged; + QUrl m_shaderCacheFile; + QByteArray m_shaderCacheExport; + QUrl m_shaderCacheWritePending; + bool m_shaderCacheDumpPending = false; friend class Q3DSStudio3D; }; diff --git a/src/api/studio3d/q3dssurfaceviewer.cpp b/src/api/studio3d/q3dssurfaceviewer.cpp index 1ffad89..e885a4b 100644 --- a/src/api/studio3d/q3dssurfaceviewer.cpp +++ b/src/api/studio3d/q3dssurfaceviewer.cpp @@ -662,6 +662,7 @@ bool Q3DSSurfaceViewerPrivate::initializeRuntime() m_context->format(), int(m_fboId), localSource, m_presentation->variantList(), m_presentation->delayedLoading(), true, + m_presentation->d_ptr->loadShaderCache(), m_presentation->d_ptr->streamProxy())) { setError(m_viewerApp->error()); releaseRuntime(); diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp index 274c691..5a99aad 100644 --- a/src/api/studio3dqml/q3dsrenderer.cpp +++ b/src/api/studio3dqml/q3dsrenderer.cpp @@ -104,8 +104,11 @@ void Q3DSRenderer::synchronize(QQuickFramebufferObject *inView) m_presentation->setVariantList(m_commands.m_variantList); m_presentation->setSource(m_commands.m_source); m_presentation->setDelayedLoading(m_commands.m_delayedLoading); + m_presentation->setShaderCacheFile(m_commands.m_shaderCacheFile); m_commands.m_sourceChanged = false; m_commands.m_variantListChanged = false; + m_commands.m_delayedLoadingChanged = false; + m_commands.m_shaderCacheFileChanged = false; m_initialized = false; m_initializationFailure = false; m_error.clear(); @@ -243,7 +246,7 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo) m_runtime, theWidth, theHeight, QOpenGLContext::currentContext()->format(), int(inFbo->handle()), localSource, m_presentation->variantList(), m_presentation->delayedLoading(), m_visitor, context, - m_asyncInitSurface); + m_asyncInitSurface, m_presentation->d_ptr->loadShaderCache()); connect(m_runtimeInitializerThread, &Q3DSRuntimeInitializerThread::initDone, this, &Q3DSRenderer::handleRuntimeInitializedAsync, Qt::QueuedConnection); context->moveToThread(m_runtimeInitializerThread); @@ -254,6 +257,7 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo) int(inFbo->handle()), localSource, m_presentation->variantList(), m_presentation->delayedLoading(), true, + m_presentation->d_ptr->loadShaderCache(), m_visitor)) { m_error = m_runtime->error(); releaseRuntime(); @@ -472,6 +476,12 @@ void Q3DSRenderer::processCommands() command.m_data = nullptr; break; } + case CommandType_PreloadSlide: + m_runtime->preloadSlide(cmd.m_elementPath); + break; + case CommandType_UnloadSlide: + m_runtime->unloadSlide(cmd.m_elementPath); + break; case CommandType_RequestSlideInfo: { int current = 0; int previous = 0; @@ -486,7 +496,6 @@ void Q3DSRenderer::processCommands() requestData->append(QVariant(previousName)); Q_EMIT requestResponse(cmd.m_elementPath, cmd.m_commandType, requestData); - break; } case CommandType_RequestDataInputs: { @@ -518,12 +527,15 @@ void Q3DSRenderer::processCommands() Q_EMIT requestResponse(cmd.m_elementPath, cmd.m_commandType, requestData); break; } - case CommandType_PreloadSlide: - m_runtime->preloadSlide(cmd.m_elementPath); - break; - case CommandType_UnloadSlide: - m_runtime->unloadSlide(cmd.m_elementPath); + case CommandType_RequestExportShaderCache: { + QByteArray shaderCache = m_runtime->exportShaderCache(cmd.m_boolValue); + QVariantList *requestData = new QVariantList(); + requestData->append(QVariant(shaderCache)); + + Q_EMIT requestResponse({}, cmd.m_commandType, requestData); break; + } + default: qWarning() << __FUNCTION__ << "Unrecognized CommandType in command list!"; } diff --git a/src/api/studio3dqml/q3dsruntimeInitializerthread.cpp b/src/api/studio3dqml/q3dsruntimeInitializerthread.cpp index 677b61a..bc021aa 100644 --- a/src/api/studio3dqml/q3dsruntimeInitializerthread.cpp +++ b/src/api/studio3dqml/q3dsruntimeInitializerthread.cpp @@ -39,7 +39,7 @@ Q3DSRuntimeInitializerThread::Q3DSRuntimeInitializerThread( Q3DSViewer::Q3DSViewerApp *runtime, int width, int height, const QSurfaceFormat &format, int offscreenID, const QString &source, const QStringList &variantList, bool delayedLoading, qt3ds::Qt3DSAssetVisitor *assetVisitor, - QOpenGLContext *context, QSurface *surface) + QOpenGLContext *context, QSurface *surface, const QByteArray &shaderCache) : m_runtime(runtime) , m_width(width) , m_height(height) @@ -51,6 +51,7 @@ Q3DSRuntimeInitializerThread::Q3DSRuntimeInitializerThread( , m_assetVisitor(assetVisitor) , m_context(context) , m_surface(surface) + , m_shaderCache(shaderCache) { } @@ -60,7 +61,7 @@ void Q3DSRuntimeInitializerThread::run() m_context->makeCurrent(m_surface); m_success = m_runtime->InitializeApp(m_width, m_height, m_format, m_offscreenId, m_source, m_variantList, m_delayedLoading, false, - m_assetVisitor); + m_shaderCache, m_assetVisitor); m_context->doneCurrent(); delete m_context; diff --git a/src/api/studio3dqml/q3dsruntimeInitializerthread_p.h b/src/api/studio3dqml/q3dsruntimeInitializerthread_p.h index 42dcf67..9aba691 100644 --- a/src/api/studio3dqml/q3dsruntimeInitializerthread_p.h +++ b/src/api/studio3dqml/q3dsruntimeInitializerthread_p.h @@ -64,7 +64,7 @@ public: int offscreenID, const QString &source, const QStringList &variantList, bool delayedLoading, qt3ds::Qt3DSAssetVisitor *assetVisitor, QOpenGLContext *context, - QSurface *surface); + QSurface *surface, const QByteArray &shaderCache); void run() override; @@ -86,6 +86,7 @@ private: qt3ds::Qt3DSAssetVisitor *m_assetVisitor; QOpenGLContext *m_context; QSurface *m_surface; + QByteArray m_shaderCache; bool m_success = false; }; diff --git a/src/api/studio3dqml/q3dsstudio3d.cpp b/src/api/studio3dqml/q3dsstudio3d.cpp index 19cf09b..4cb0850 100644 --- a/src/api/studio3dqml/q3dsstudio3d.cpp +++ b/src/api/studio3dqml/q3dsstudio3d.cpp @@ -366,7 +366,11 @@ void Q3DSStudio3D::reset() m_pendingCommands.m_sourceChanged = true; m_pendingCommands.m_source = m_presentation ? m_presentation->source() : QString(); m_pendingCommands.m_variantListChanged = true; - m_pendingCommands.m_variantList = m_presentation ? m_presentation->variantList() : QStringList(); + m_pendingCommands.m_variantList = m_presentation ? m_presentation->variantList() + : QStringList(); + m_pendingCommands.m_shaderCacheFileChanged = true; + m_pendingCommands.m_shaderCacheFile = m_presentation ? m_presentation->shaderCacheFile() + : QString(); } /*! @@ -385,23 +389,16 @@ void Q3DSStudio3D::requestResponseHandler(const QString &elementPath, CommandTyp qWarning() << __FUNCTION__ << "RequestSlideInfo response got for unregistered scene."; break; } - case CommandType_RequestDataInputs: { + case CommandType_RequestDataInputs: + case CommandType_RequestDataOutputs: + case CommandType_RequestExportShaderCache: + { Q3DSPresentation *handler = qobject_cast<Q3DSPresentation *>(m_presentation); if (handler) { handler->d_ptr->requestResponseHandler(commandType, requestData); } else { - qWarning() << __FUNCTION__ - << "RequestDataInputs response got for invalid presentation."; - } - break; - } - case CommandType_RequestDataOutputs: { - Q3DSPresentation *handler = qobject_cast<Q3DSPresentation *>(m_presentation); - if (handler) { - handler->d_ptr->requestResponseHandler(commandType, requestData); - } else { - qWarning() << __FUNCTION__ - << "RequestDataOutputs response got for invalid presentation."; + qWarning() << __FUNCTION__ << "Command " << commandType + << "response got for invalid presentation."; } break; } |