summaryrefslogtreecommitdiffstats
path: root/src/render/materialsystem/shaderdata.cpp
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2020-05-26 15:49:43 +0200
committerPaul Lemire <paul.lemire@kdab.com>2020-06-08 12:06:39 +0200
commitf0514d4096651b2d798d07989152a4ca74780e94 (patch)
tree540bba3b6d73d387051c21e52a0e323aa3d3456b /src/render/materialsystem/shaderdata.cpp
parentad0df44538f866fe94b17ef6d9ab20363b1907b4 (diff)
Rework ShaderData/UniformBlockValueBuilder to minimize String lookups
We cache the names used for a given Block/Struct for each ShaderData so that we don't have to concatenate strings all the time Also removed the local thread storage which we don't need and update tests. Change-Id: I934c78f7f69cb85017d684ae30e5b0cb632d3fa0 Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/render/materialsystem/shaderdata.cpp')
-rw-r--r--src/render/materialsystem/shaderdata.cpp100
1 files changed, 74 insertions, 26 deletions
diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp
index 6f113d592..1a6b758b5 100644
--- a/src/render/materialsystem/shaderdata.cpp
+++ b/src/render/materialsystem/shaderdata.cpp
@@ -45,6 +45,7 @@
#include <private/qbackendnode_p.h>
#include <private/managers_p.h>
#include <private/nodemanagers_p.h>
+#include <Qt3DRender/private/stringtoint_p.h>
QT_BEGIN_NAMESPACE
@@ -82,6 +83,7 @@ void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (firstTime) {
m_propertyReader = node->propertyReader();
+ m_blockNameToPropertyValues.clear();
const QMetaObject *metaObj = node->metaObject();
const int propertyOffset = QShaderData::staticMetaObject.propertyOffset();
@@ -104,28 +106,35 @@ void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
for (const QString &propertyName : propertyNames) {
if (propertyName == QStringLiteral("data") ||
+ propertyName == QStringLiteral("objectName") ||
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 isNode = false;
bool isTransformed = false;
+ bool isArray = false;
// We check if the property is a QNodeId
- isNested = (propertyValue.userType() == qNodeIdTypeId);
+ isNode = (propertyValue.userType() == qNodeIdTypeId);
// We check if QVector<QNodeId>
if (propertyValue.userType() == QMetaType::QVariantList) {
+ isArray = true;
QVariantList list = propertyValue.value<QVariantList>();
if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId)
- isNested = true;
+ isNode = true;
}
// We check if property is a Transformed property
+ QString transformedPropertyName;
if (propertyValue.userType() == QVariant::Vector3D) {
// if there is a matching QShaderData::TransformType propertyTransformed
- isTransformed = propertyNames.contains(propertyName + QLatin1String("Transformed"));
+ transformedPropertyName = propertyName + QLatin1String("Transformed");
+ isTransformed = propertyNames.contains(transformedPropertyName);
+ if (!isTransformed)
+ transformedPropertyName.clear();
}
- m_originalProperties.insert(propertyName, { propertyValue, isNested, isTransformed });
+ m_originalProperties.insert(propertyName, { propertyValue, isNode, isArray, isTransformed, transformedPropertyName });
}
BackendNode::markDirty(AbstractRenderer::ParameterDirty);
} else {
@@ -149,6 +158,50 @@ void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
}
}
+bool ShaderData::hasPropertyValuesForBlock(int blockName) const
+{
+ std::shared_lock readLocker(m_lock);
+ return m_blockNameToPropertyValues.find(blockName) != m_blockNameToPropertyValues.cend();
+}
+
+const ShaderData::PropertyValuesForBlock &ShaderData::propertyValuesForBlock(int blockName) const
+{
+ std::shared_lock readLocker(m_lock);
+ return m_blockNameToPropertyValues.at(blockName);
+}
+
+void ShaderData::generatePropertyValuesForBlock(const QString &fullBlockName)
+{
+ const QHash<QString, ShaderData::PropertyValue> &props = properties();
+
+ ShaderData::PropertyValuesForBlock valueBlock;
+ valueBlock.reserve(props.size());
+
+ auto it = props.cbegin();
+ const auto end = props.cend();
+ while (it != end) {
+ QString propertyName = it.key();
+ // If we are dealing with a nested value, check if it is an an array
+ if (it->isArray && !it->isNode)
+ propertyName += QLatin1String("[0]");
+
+ QString fullPropertyName;
+ fullPropertyName.reserve(fullBlockName.length() + 1 + it.key().length());
+ fullPropertyName.append(fullBlockName);
+ fullPropertyName.append(QLatin1String("."));
+ fullPropertyName.append(propertyName);
+
+ // We only do this for properties on root level
+ valueBlock.push_back({ StringToInt::lookupId(fullPropertyName),
+ StringToInt::lookupId(propertyName),
+ it.operator ->() });
+ ++it;
+ }
+
+ std::unique_lock writeLocker(m_lock);
+ m_blockNameToPropertyValues[StringToInt::lookupId(fullBlockName)] = std::move(valueBlock);
+}
+
ShaderData *ShaderData::lookupResource(NodeManagers *managers, QNodeId id)
{
return managers->shaderDataManager()->lookupResource(id);
@@ -160,33 +213,28 @@ ShaderData *ShaderData::lookupResource(QNodeId id)
}
// RenderCommand updater jobs
-QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const noexcept
+QVariant ShaderData::getTransformedProperty(const PropertyValue *v, const Matrix4x4 &viewMatrix) const noexcept
{
// Note protecting m_worldMatrix at this point as we assume all world updates
// have been performed when reaching this point
- 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;
- }
+ if (v->isTransformed) {
+ const auto transformedIt = m_originalProperties.constFind(v->transformedPropertyName);
+ 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(v->value.value<QVector3D>()));
+ case ModelToWorld:
+ return QVariant::fromValue(m_worldMatrix * Vector3D(v->value.value<QVector3D>()));
+ case ModelToWorldDirection:
+ return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(v->value.value<QVector3D>(), 0.0f)));
+ case NoTransform:
+ break;
}
}
- return propertyValue.value;
}
- return QVariant();
+ return v->value;
}
// Unit tests only