summaryrefslogtreecommitdiffstats
path: root/src/render/materialsystem
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-10-02 12:45:21 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-10-08 14:40:59 +0200
commitbf437f7da6c57307f93a24162981d4efd989fc53 (patch)
tree5137cbd5ae47d149c911b924ed92a1d3cb3cc826 /src/render/materialsystem
parent417fb3cb1af27313d2b4e1aafb094fee33388328 (diff)
Update QShaderData to use direct sync
Also a bit of cleanup Change-Id: I317fa2dbaa62a55fe371e982ed23976e65696d79 Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/render/materialsystem')
-rw-r--r--src/render/materialsystem/shaderdata.cpp241
-rw-r--r--src/render/materialsystem/shaderdata_p.h31
2 files changed, 118 insertions, 154 deletions
diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp
index 130333898..34d4641e9 100644
--- a/src/render/materialsystem/shaderdata.cpp
+++ b/src/render/materialsystem/shaderdata.cpp
@@ -64,8 +64,6 @@ const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>();
}
-QVector<Qt3DCore::QNodeId> ShaderData::m_updatedShaderData;
-
ShaderData::ShaderData()
: m_managers(nullptr)
{
@@ -80,51 +78,82 @@ void ShaderData::setManagers(NodeManagers *managers)
m_managers = managers;
}
-void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderDataData>>(change);
- const QShaderDataData &data = typedChange->data;
-
- m_propertyReader = data.propertyReader;
-
- for (const QPair<QByteArray, QVariant> &entry : data.properties) {
- if (entry.first == QByteArrayLiteral("data") ||
- entry.first == QByteArrayLiteral("childNodes")) // We don't handle default Node properties
- continue;
- const QVariant &propertyValue = entry.second;
- const QString propertyName = QString::fromLatin1(entry.first);
-
- m_originalProperties.insert(propertyName, propertyValue);
-
- // We check if the property is a QNodeId or QVector<QNodeId> so that we can
- // check nested QShaderData for update
- if (propertyValue.userType() == qNodeIdTypeId) {
- m_nestedShaderDataProperties.insert(propertyName, propertyValue);
- } else if (propertyValue.userType() == QMetaType::QVariantList) {
- QVariantList list = propertyValue.value<QVariantList>();
- if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId)
- m_nestedShaderDataProperties.insert(propertyName, propertyValue);
- }
- }
+ const QShaderData *node = qobject_cast<const QShaderData *>(frontEnd);
+ if (!node)
+ return;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime) {
+ m_propertyReader = node->propertyReader();
+
+ const QMetaObject *metaObj = node->metaObject();
+ const int propertyOffset = QShaderData::staticMetaObject.propertyOffset();
+ const int propertyCount = metaObj->propertyCount();
+ // Dynamic properties names
+ const auto dynamicPropertyNames = node->dynamicPropertyNames();
- // We look for transformed properties once the complete hash of
- // originalProperties is available
- QHash<QString, QVariant>::iterator it = m_originalProperties.begin();
- const QHash<QString, QVariant>::iterator end = m_originalProperties.end();
-
- while (it != end) {
- if (it.value().type() == QVariant::Vector3D) {
- // if there is a matching QShaderData::TransformType propertyTransformed
- QVariant value = m_originalProperties.value(it.key() + QLatin1String("Transformed"));
- // if that's the case, we apply a space transformation to the property
- if (value.isValid() && value.type() == QVariant::Int)
- m_transformedProperties.insert(it.key(), static_cast<TransformType>(value.toInt()));
+ QVector<QString> propertyNames;
+ propertyNames.reserve(propertyCount - propertyOffset + dynamicPropertyNames.size());
+
+ // Statiically defined properties
+ for (int i = propertyOffset; i < propertyCount; ++i) {
+ const QMetaProperty pro = metaObj->property(i);
+ if (pro.isWritable())
+ propertyNames.push_back(QString::fromLatin1(pro.name()));
+ }
+ // Dynamic properties
+ for (const QByteArray &propertyName : dynamicPropertyNames)
+ propertyNames.push_back(QString::fromLatin1(propertyName));
+
+ for (const QString &propertyName : propertyNames) {
+ if (propertyName == QStringLiteral("data") ||
+ propertyName == QStringLiteral("childNodes")) // We don't handle default Node properties
+ continue;
+
+ const QVariant &propertyValue = m_propertyReader->readProperty(node->property(propertyName.toLatin1()));
+ bool isNested = false;
+ bool isTransformed = false;
+
+ // We check if the property is a QNodeId
+ isNested = (propertyValue.userType() == qNodeIdTypeId);
+ // We check if QVector<QNodeId>
+ if (propertyValue.userType() == QMetaType::QVariantList) {
+ QVariantList list = propertyValue.value<QVariantList>();
+ if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId)
+ isNested = true;
+ }
+
+ // We check if property is a Transformed property
+ if (propertyValue.userType() == QVariant::Vector3D) {
+ // if there is a matching QShaderData::TransformType propertyTransformed
+ isTransformed = propertyNames.contains(propertyName + QLatin1String("Transformed"));
+ }
+ m_originalProperties.insert(propertyName, { propertyValue, isNested, isTransformed });
+ }
+ BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ } else {
+ // Updates
+ if (!m_propertyReader.isNull()) {
+ auto it = m_originalProperties.begin();
+ const auto end = m_originalProperties.end();
+
+ while (it != end) {
+ const QVariant newValue = m_propertyReader->readProperty(node->property(it.key().toLatin1()));
+ PropertyValue &propValue = it.value();
+ if (propValue.value != newValue) {
+ // Note we aren't notified about nested QShaderData in this call
+ // only scalar / vec properties
+ propValue.value = newValue;
+ BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ }
+ ++it;
+ }
}
- ++it;
}
}
-
ShaderData *ShaderData::lookupResource(NodeManagers *managers, QNodeId id)
{
return managers->shaderDataManager()->lookupResource(id);
@@ -135,120 +164,62 @@ ShaderData *ShaderData::lookupResource(QNodeId id)
return ShaderData::lookupResource(m_managers, id);
}
-// Call by cleanup job (single thread)
-void ShaderData::clearUpdatedProperties()
-{
- // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
- // const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
- // QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
-
- // while (it != end) {
- // if (it.value().userType() == QMetaType::QVariantList) {
- // const auto values = it.value().value<QVariantList>();
- // for (const QVariant &v : values) {
- // ShaderData *nested = lookupResource(v.value<QNodeId>());
- // if (nested != nullptr)
- // nested->clearUpdatedProperties();
- // }
- // } else {
- // ShaderData *nested = lookupResource(it.value().value<QNodeId>());
- // if (nested != nullptr)
- // nested->clearUpdatedProperties();
- // }
- // ++it;
- // }
-}
-
void ShaderData::cleanup(NodeManagers *managers)
{
Q_UNUSED(managers)
- // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
- // for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) {
- // ShaderData *shaderData = ShaderData::lookupResource(managers, id);
- // if (shaderData)
- // shaderData->clearUpdatedProperties();
- // }
- m_updatedShaderData.clear();
}
+// RenderCommand updater jobs
QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix)
{
// Note protecting m_worldMatrix at this point as we assume all world updates
// have been performed when reaching this point
- auto it = m_transformedProperties.find(name);
- if (it != m_transformedProperties.end()) {
- const TransformType transformType = it.value();
- switch (transformType) {
- case ModelToEye:
- return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(m_originalProperties.value(name).value<QVector3D>()));
- case ModelToWorld:
- return QVariant::fromValue(m_worldMatrix * Vector3D(m_originalProperties.value(it.key()).value<QVector3D>()));
- case ModelToWorldDirection:
- return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f)));
- case NoTransform:
- break;
+ const auto it = m_originalProperties.constFind(name);
+ if (it != m_originalProperties.constEnd()) {
+ const PropertyValue &propertyValue = it.value();
+ if (propertyValue.isTransformed) {
+ const auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed"));
+ if (transformedIt != m_originalProperties.constEnd()) {
+ const PropertyValue &transformedValue = transformedIt.value();
+ const TransformType transformType = static_cast<TransformType>(transformedValue.value.toInt());
+ switch (transformType) {
+ case ModelToEye:
+ return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>()));
+ case ModelToWorld:
+ return QVariant::fromValue(m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>()));
+ case ModelToWorldDirection:
+ return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(propertyValue.value.value<QVector3D>(), 0.0f)));
+ case NoTransform:
+ break;
+ }
+ }
}
+ return propertyValue.value;
}
return QVariant();
}
-// Called by FramePreparationJob or by RenderView when dealing with lights
-void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix)
-{
- QMutexLocker lock(&m_mutex);
- if (m_worldMatrix != worldMatrix) {
- m_worldMatrix = worldMatrix;
- }
-}
-
-// This will add the ShaderData to be cleared from updates at the end of the frame
-// by the cleanup job
-// Called by renderview jobs (several concurrent threads)
-void ShaderData::markDirty()
-{
- QMutexLocker lock(&m_mutex);
- if (!ShaderData::m_updatedShaderData.contains(peerId()))
- ShaderData::m_updatedShaderData.append(peerId());
-}
-
-/*!
- \internal
- Lookup if the current ShaderData or a nested ShaderData has updated properties.
- UpdateProperties contains either the value of the propertie of a QNodeId if it's another ShaderData.
- Transformed properties are updated for all of ShaderData that have ones at the point.
-
- \note This needs to be performed for every top level ShaderData every time it is used.
- As we don't know if the transformed properties use the same viewMatrix for all RenderViews.
- */
-
+// Unit tests only
ShaderData::TransformType ShaderData::propertyTransformType(const QString &name) const
{
- return m_transformedProperties.value(name, TransformType::NoTransform);
+ const auto it = m_originalProperties.constFind(name);
+ if (it != m_originalProperties.constEnd()) {
+ const PropertyValue &propertyValue = it.value();
+ if (propertyValue.isTransformed) {
+ auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed"));
+ if (transformedIt != m_originalProperties.end())
+ return static_cast<TransformType>(transformedIt.value().value.toInt());
+ }
+ }
+ return NoTransform;
}
-void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+// Called by FramePreparationJob or by RenderView when dealing with lights
+void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix)
{
- if (!m_propertyReader.isNull() && e->type() == PropertyUpdated) {
- QString propertyName;
- QVariant propertyValue;
-
- if (auto propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e)) {
- propertyName = QString::fromLatin1(propertyChange->propertyName());
- propertyValue = m_propertyReader->readProperty(propertyChange->value());
- } else if (auto propertyChange = qSharedPointerDynamicCast<QDynamicPropertyUpdatedChange>(e)) {
- propertyName = QString::fromLatin1(propertyChange->propertyName());
- propertyValue = m_propertyReader->readProperty(propertyChange->value());
- } else {
- Q_UNREACHABLE();
- }
-
- // Note we aren't notified about nested QShaderData in this call
- // only scalar / vec properties
- m_originalProperties.insert(propertyName, propertyValue);
- BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ if (m_worldMatrix != worldMatrix) {
+ m_worldMatrix = worldMatrix;
}
-
- BackendNode::sceneChangeEvent(e);
}
RenderShaderDataFunctor::RenderShaderDataFunctor(AbstractRenderer *renderer, NodeManagers *managers)
diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h
index f9c3ecc79..c9cc22939 100644
--- a/src/render/materialsystem/shaderdata_p.h
+++ b/src/render/materialsystem/shaderdata_p.h
@@ -76,49 +76,42 @@ public:
ModelToWorld,
ModelToWorldDirection
};
+ struct PropertyValue {
+ QVariant value;
+ bool isNested;
+ bool isTransformed;
+ };
ShaderData();
~ShaderData();
- QHash<QString, QVariant> properties() const { return m_originalProperties; }
+ QHash<QString, PropertyValue> properties() const { return m_originalProperties; }
// Called by FramePreparationJob
void updateWorldTransform(const Matrix4x4 &worldMatrix);
- // Call by RenderViewJob
- void markDirty();
+ QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix);
+ // Unit tests purposes only
TransformType propertyTransformType(const QString &name) const;
- QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix);
// Called by FrameCleanupJob
static void cleanup(NodeManagers *managers);
void setManagers(NodeManagers *managers);
-protected:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+protected:
PropertyReaderInterfacePtr m_propertyReader;
- // 1 to 1 match with frontend properties, modified only by sceneChangeEvent
- QHash<QString, QVariant> m_originalProperties;
-
- // Contains properties thar are of type ShaderData
- QHash<QString, QVariant> m_nestedShaderDataProperties;
-
- // Contains property that are defined like: postionTransformed: ModelToEye
- QHash<QString, TransformType> m_transformedProperties;
+ // 1 to 1 match with frontend properties
+ QHash<QString, PropertyValue> m_originalProperties;
- QMutex m_mutex;
- static QVector<Qt3DCore::QNodeId> m_updatedShaderData;
Matrix4x4 m_worldMatrix;
- Matrix4x4 m_viewMatrix;
NodeManagers *m_managers;
- void clearUpdatedProperties();
static ShaderData *lookupResource(NodeManagers *managers, Qt3DCore::QNodeId id);
ShaderData *lookupResource(Qt3DCore::QNodeId id);