summaryrefslogtreecommitdiffstats
path: root/src/api/studio3d/q3dspresentation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/studio3d/q3dspresentation.cpp')
-rw-r--r--src/api/studio3d/q3dspresentation.cpp259
1 files changed, 251 insertions, 8 deletions
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