diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-05-26 15:49:43 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-06-08 12:06:39 +0200 |
commit | f0514d4096651b2d798d07989152a4ca74780e94 (patch) | |
tree | 540bba3b6d73d387051c21e52a0e323aa3d3456b /src/render/materialsystem/shaderdata.cpp | |
parent | ad0df44538f866fe94b17ef6d9ab20363b1907b4 (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.cpp | 100 |
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 |