summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJanne Kangas <janne.kangas@qt.io>2019-07-16 14:51:45 +0300
committerJanne Kangas <janne.kangas@qt.io>2019-08-09 13:46:54 +0300
commit2ac5dc0fcd1503fa11a90e17054f1d4ea370b6d6 (patch)
tree1beb0052a95c70ce5880966b1de8208b83ccb627 /src
parentbb6fff1b707c15853f137b5a7b8797fa9415d33f (diff)
Batch datainput value changes per-frame for QML context
Group all changes in datainput values on QML side together and send a single per-frame command. This ameliorates the performance cost of frequent value updates, especially for projects with large amount of datainputs. Change-Id: Ib398f405dedb50ad3f5429f42024b3f490114dab Task-id: QT3DS-3759 Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/api/studio3d/q3dscommandqueue.cpp9
-rw-r--r--src/api/studio3d/q3dscommandqueue_p.h1
-rw-r--r--src/api/studio3d/q3dsdatainput.cpp7
-rw-r--r--src/api/studio3d/q3dsdatainput_p.h3
-rw-r--r--src/api/studio3d/q3dspresentation.cpp23
-rw-r--r--src/api/studio3d/q3dspresentation_p.h3
-rw-r--r--src/api/studio3dqml/q3dsrenderer.cpp13
-rw-r--r--src/api/studio3dqml/q3dsstudio3d.cpp5
8 files changed, 61 insertions, 3 deletions
diff --git a/src/api/studio3d/q3dscommandqueue.cpp b/src/api/studio3d/q3dscommandqueue.cpp
index e9eed29..102441b 100644
--- a/src/api/studio3d/q3dscommandqueue.cpp
+++ b/src/api/studio3d/q3dscommandqueue.cpp
@@ -240,6 +240,11 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue,
source.m_variantValue, source.m_intValues[0]);
break;
+ case CommandType_SetDataInputBatch:
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue,
+ source.m_data);
+ fromQueue.commandAt(i).m_data = nullptr; // This queue takes ownership of data
+ break;
case CommandType_SetAttribute:
queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue,
source.m_variantValue);
@@ -328,6 +333,10 @@ void CommandQueue::clear(bool deleteCommandData)
delete static_cast<QHash<QString, Q3DSViewer::MeshData> *>(cmd.m_data);
break;
}
+ case CommandType_SetDataInputBatch: {
+ delete static_cast<QVector<QPair<QString, QVariant>> *>(cmd.m_data);
+ break;
+ }
default:
Q_ASSERT(false); // Should never come here
break;
diff --git a/src/api/studio3d/q3dscommandqueue_p.h b/src/api/studio3d/q3dscommandqueue_p.h
index effb72e..a519ce7 100644
--- a/src/api/studio3d/q3dscommandqueue_p.h
+++ b/src/api/studio3d/q3dscommandqueue_p.h
@@ -68,6 +68,7 @@ enum CommandType {
CommandType_KeyRelease,
CommandType_SetGlobalAnimationTime,
CommandType_SetDataInputValue,
+ CommandType_SetDataInputBatch,
CommandType_CreateElements,
CommandType_DeleteElements,
CommandType_CreateMaterials,
diff --git a/src/api/studio3d/q3dsdatainput.cpp b/src/api/studio3d/q3dsdatainput.cpp
index 2a52963..bfd8b43 100644
--- a/src/api/studio3d/q3dsdatainput.cpp
+++ b/src/api/studio3d/q3dsdatainput.cpp
@@ -357,6 +357,11 @@ void Q3DSDataInputPrivate::setPresentation(Q3DSPresentation *presentation)
m_presentation = presentation;
}
+void Q3DSDataInputPrivate::setDirty(bool dirty)
+{
+ m_dirty = dirty;
+}
+
Q3DSDataInputPrivate::Q3DSDataInputPrivate(Q3DSDataInput *parent)
: q_ptr(parent)
{
@@ -371,6 +376,8 @@ Q3DSDataInputPrivate::~Q3DSDataInputPrivate()
void Q3DSDataInputPrivate::setValue(const QVariant &value, Q3DSDataInput::ValueRole valueRole)
{
m_value = value;
+ setDirty(true);
+
if (m_presentation)
m_presentation->setDataInputValue(m_name, m_value, valueRole);
}
diff --git a/src/api/studio3d/q3dsdatainput_p.h b/src/api/studio3d/q3dsdatainput_p.h
index 19b06f9..b5e0cc5 100644
--- a/src/api/studio3d/q3dsdatainput_p.h
+++ b/src/api/studio3d/q3dsdatainput_p.h
@@ -61,6 +61,7 @@ public:
void setViewerApp(Q3DSViewer::Q3DSViewerApp *app);
void setCommandQueue(CommandQueue *queue);
void setPresentation(Q3DSPresentation *presentation);
+ void setDirty(bool dirty);
protected:
Q3DSDataInput *q_ptr;
@@ -74,6 +75,8 @@ protected:
float m_max = 0;
float m_min = 0;
+ bool m_dirty = false;
+
// Note: Qt3d Runtime allows metadata to be both read and set, therefore requiring
// internal representation of both keys and values to be QVariant as per API convention.
// OpenGL Runtime, in contrast, only allows metadata to be read. As metadata now can only
diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp
index cd9ecfa..3863fa3 100644
--- a/src/api/studio3d/q3dspresentation.cpp
+++ b/src/api/studio3d/q3dspresentation.cpp
@@ -848,12 +848,13 @@ void Q3DSPresentation::setGlobalAnimationTime(qint64 milliseconds)
void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &value,
Q3DSDataInput::ValueRole valueRole)
{
+ // If we do not have viewerApp i.e. if this is a QML client context, do not send
+ // datainput set commands to the queue. They are batched and sent out at frameUpdate signal.
if (d_ptr->m_viewerApp) {
d_ptr->m_viewerApp->SetDataInputValue(name, value,
(qt3ds::runtime::DataInputValueRole)valueRole);
- } else if (d_ptr->m_commandQueue) {
- d_ptr->m_commandQueue->queueCommand(QString(), CommandType_SetDataInputValue,
- name, value, static_cast<int>(valueRole));
+ } else {
+ d_ptr->m_dataInputsChanged = true;
}
}
@@ -1512,6 +1513,7 @@ Q3DSPresentationPrivate::Q3DSPresentationPrivate(Q3DSPresentation *q)
, m_commandQueue(nullptr)
, m_streamProxy(nullptr)
, m_delayedLoading(false)
+ , m_dataInputsChanged(false)
{
}
@@ -1917,6 +1919,21 @@ bool Q3DSPresentationPrivate::isValidDataOutput(const Q3DSDataOutput *dataOutput
return m_viewerApp->dataOutputs().contains(dataOutput->name());
}
+void Q3DSPresentationPrivate::setDataInputValueBatch()
+{
+ // Allocated here, deleted after queue command has been processed.
+ QVector<QPair<QString, QVariant>> *theProperties = new QVector<QPair<QString, QVariant>>();
+ for (const auto &di : qAsConst(m_dataInputs)) {
+ if (di->d_ptr->m_dirty) {
+ theProperties->append({di->name(), di->value()});
+ di->d_ptr->m_dirty = false;
+ }
+ }
+
+ if (!theProperties->empty() && m_commandQueue)
+ m_commandQueue->queueCommand({}, CommandType_SetDataInputBatch, {}, theProperties);
+}
+
Q3DStudio::EKeyCode Q3DSPresentationPrivate::getScanCode(QKeyEvent *e)
{
enum {
diff --git a/src/api/studio3d/q3dspresentation_p.h b/src/api/studio3d/q3dspresentation_p.h
index 59b9f38..a68d0ee 100644
--- a/src/api/studio3d/q3dspresentation_p.h
+++ b/src/api/studio3d/q3dspresentation_p.h
@@ -90,6 +90,8 @@ public:
QVector<Q3DSDataInput *> dataInputs(const QString &key) const;
bool isValidDataOutput(const Q3DSDataOutput *dataOutput) const;
+ void setDataInputValueBatch();
+
ViewerQmlStreamProxy *streamProxy();
Q3DStudio::EKeyCode getScanCode(QKeyEvent *e);
@@ -118,6 +120,7 @@ private:
QStringList m_createdElements;
QStringList m_createdMaterials;
QStringList m_createdMeshes;
+ bool m_dataInputsChanged;
friend class Q3DSStudio3D;
};
diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp
index 4d48a93..12f2e4d 100644
--- a/src/api/studio3dqml/q3dsrenderer.cpp
+++ b/src/api/studio3dqml/q3dsrenderer.cpp
@@ -370,6 +370,19 @@ void Q3DSRenderer::processCommands()
cmd.m_stringValue, cmd.m_variantValue,
static_cast<qt3ds::runtime::DataInputValueRole>(cmd.m_intValues[0]));
break;
+ case CommandType_SetDataInputBatch: {
+ const QVector<QPair<QString, QVariant>> diValues
+ = *static_cast<QVector<QPair<QString, QVariant>> *>(cmd.m_data);
+
+ for (const auto &di : diValues) {
+ m_runtime->SetDataInputValue(di.first, di.second,
+ qt3ds::runtime::DataInputValueRole::Value);
+ }
+ // No need for data after this, delete.
+ auto &command = m_commands.commandAt(i);
+ delete static_cast<QVector<QPair<QString, QVariant>> *>(command.m_data);
+ break;
+ }
case CommandType_CreateElements: {
m_runtime->createElements(
cmd.m_elementPath, cmd.m_stringValue,
diff --git a/src/api/studio3dqml/q3dsstudio3d.cpp b/src/api/studio3dqml/q3dsstudio3d.cpp
index 38d32d4..8183d7b 100644
--- a/src/api/studio3dqml/q3dsstudio3d.cpp
+++ b/src/api/studio3dqml/q3dsstudio3d.cpp
@@ -454,6 +454,11 @@ void Q3DSStudio3D::tick()
*/
void Q3DSStudio3D::getCommands(bool emitInitialize, CommandQueue &renderQueue)
{
+ if (m_presentation->d_ptr->m_dataInputsChanged) {
+ m_presentation->d_ptr->setDataInputValueBatch();
+ m_presentation->d_ptr->m_dataInputsChanged = false;
+ }
+
if (emitInitialize)
m_emitRunningChange = true;