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 | |
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>
8 files changed, 323 insertions, 205 deletions
diff --git a/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp b/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp index eb1e3dd38..3a7777170 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp +++ b/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp @@ -458,103 +458,98 @@ const int qNodeIdTypeId = qMetaTypeId<QNodeId>(); } -UniformBlockValueBuilder::UniformBlockValueBuilder() - : updatedPropertiesOnly(false) - , shaderDataManager(nullptr) - , textureManager(nullptr) -{ -} - -UniformBlockValueBuilder::~UniformBlockValueBuilder() +UniformBlockValueBuilder::UniformBlockValueBuilder( + const QVector<int> &uniformNamesIds, + ShaderDataManager *shaderDataManager, + TextureManager *textureManager, + const Matrix4x4 &matrix) + : m_uniformNamesIds(uniformNamesIds) + , m_shaderDataManager(shaderDataManager) + , m_textureManager(textureManager) + , m_viewMatrix(matrix) { } void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData, const QString &blockName, - const QString &qmlPropertyName, - const QVariant &value) + const int propertyInBlockNameId, + const int propertyNameId, + const ShaderData::PropertyValue *value) { // In the end, values are either scalar or a scalar array // Composed elements (structs, structs array) are simplified into simple scalars - if (value.userType() == QMetaType::QVariantList) { // Array - QVariantList list = value.value<QVariantList>(); - if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember + if (value->isArray) { // Array + const QVariantList list = value->value.value<QVariantList>(); + if (value->isNode) { // Array of struct qmlPropertyName[i].structMember for (int i = 0; i < list.size(); ++i) { const QVariant variantElement = list.at(i); if (list.at(i).userType() == qNodeIdTypeId) { const auto nodeId = variantElement.value<QNodeId>(); - ShaderData *subShaderData = shaderDataManager->lookupResource(nodeId); + ShaderData *subShaderData = m_shaderDataManager->lookupResource(nodeId); if (subShaderData) { buildActiveUniformNameValueMapStructHelper(subShaderData, - blockName + QLatin1Char('.') + qmlPropertyName + blockArray.arg(i), - QLatin1String("")); + blockName + QLatin1Char('.') + StringToInt::lookupString(propertyNameId) + blockArray.arg(i)); } // Note: we only handle ShaderData as nested container nodes here } } } else { // Array of scalar/vec qmlPropertyName[0] - QString varName; - varName.reserve(blockName.length() + 1 + qmlPropertyName.length() + 3); - varName.append(blockName); - varName.append(QLatin1String(".")); - varName.append(qmlPropertyName); - varName.append(QLatin1String("[0]")); - if (uniforms.contains(varName)) { - qCDebug(Shaders) << "UBO array member " << varName << " set for update"; - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value); + if (m_uniformNamesIds.contains(propertyInBlockNameId)) { + activeUniformNamesToValue.insert(propertyInBlockNameId, value->value); } } - } else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember - const auto nodeId = value.value<QNodeId>(); - ShaderData *rSubShaderData = shaderDataManager->lookupResource(nodeId); + } else if (value->isNode) { // Struct qmlPropertyName.structMember + const auto nodeId = value->value.value<QNodeId>(); + ShaderData *rSubShaderData = m_shaderDataManager->lookupResource(nodeId); if (rSubShaderData) { buildActiveUniformNameValueMapStructHelper(rSubShaderData, blockName, - qmlPropertyName); - } else if (textureManager->contains(nodeId)) { - const auto varId = StringToInt::lookupId(blockName + QLatin1Char('.') + qmlPropertyName); - activeUniformNamesToValue.insert(varId, value); + StringToInt::lookupString(propertyNameId)); + } else if (m_textureManager->contains(nodeId)) { + activeUniformNamesToValue.insert(propertyInBlockNameId, value->value); } } else { // Scalar / Vec - QString varName; - varName.reserve(blockName.length() + 1 + qmlPropertyName.length()); - varName.append(blockName); - varName.append(QLatin1String(".")); - varName.append(qmlPropertyName); - if (uniforms.contains(varName)) { - qCDebug(Shaders) << "UBO scalar member " << varName << " set for update"; - + if (m_uniformNamesIds.contains(propertyInBlockNameId)) { // If the property needs to be transformed, we transform it here as // the shaderdata cannot hold transformed properties for multiple // thread contexts at once - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), - currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix)); + activeUniformNamesToValue.insert(propertyInBlockNameId, + currentShaderData->getTransformedProperty(value, m_viewMatrix)); } } } -void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(const ShaderData *rShaderData, +void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) { - const QHash<QString, ShaderData::PropertyValue> &properties = rShaderData->properties(); - auto it = properties.begin(); - const auto end = properties.end(); - - while (it != end) { - QString fullBlockName; - fullBlockName.reserve(blockName.length() + 1 + qmlPropertyName.length()); - fullBlockName.append(blockName); - if (!qmlPropertyName.isEmpty()) { - fullBlockName.append(QLatin1String(".")); - fullBlockName.append(qmlPropertyName); - } - buildActiveUniformNameValueMapHelper(rShaderData, fullBlockName, - it.key(), it.value().value); - ++it; + QString fullBlockName; + fullBlockName.reserve(blockName.length() + 1 + qmlPropertyName.length()); + fullBlockName.append(blockName); + if (!qmlPropertyName.isEmpty()) { + fullBlockName.append(QLatin1String(".")); + fullBlockName.append(qmlPropertyName); + } + + // Retrieve set of {NameId -> PropertyValue} for Block + const int fullBlockNameId = StringToInt::lookupId(fullBlockName); + if (!rShaderData->hasPropertyValuesForBlock(fullBlockNameId)) + rShaderData->generatePropertyValuesForBlock(fullBlockName); + const ShaderData::PropertyValuesForBlock &propertiesForBlock = rShaderData->propertyValuesForBlock(fullBlockNameId); + + for (const auto &nameIdPropertyPair : propertiesForBlock) { + buildActiveUniformNameValueMapHelper(rShaderData, + fullBlockName, + // Block.Property Name + std::get<0>(nameIdPropertyPair), + // Property Name + std::get<1>(nameIdPropertyPair), + // PropertyValue + std::get<2>(nameIdPropertyPair)); } } + ParameterInfo::ParameterInfo(const int nameId, const HParameter &handle) : nameId(nameId) , handle(handle) diff --git a/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h b/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h index bd745e7a3..64e98993b 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h +++ b/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h @@ -59,6 +59,7 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/handle_types_p.h> #include <Qt3DRender/private/aligned_malloc_p.h> +#include <Qt3DRender/private/shaderdata_p.h> #include <shadervariables_p.h> QT_BEGIN_NAMESPACE @@ -77,7 +78,6 @@ class TechniqueFilter; class RenderPassFilter; class NodeManagers; class ShaderDataManager; -class ShaderData; class TextureManager; class RenderStateManager; class RenderStateCollection; @@ -157,25 +157,27 @@ typedef QHash<int, QVariant> UniformBlockValueBuilderHash; struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder { - UniformBlockValueBuilder(); - ~UniformBlockValueBuilder(); - - QT3D_ALIGNED_MALLOC_AND_FREE() + explicit UniformBlockValueBuilder(const QVector<int> &uniformNamesIds, + ShaderDataManager *shaderDataManager, + TextureManager *textureManager, + const Matrix4x4 &matrix); void buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData, const QString &blockName, - const QString &qmlPropertyName, - const QVariant &value); - void buildActiveUniformNameValueMapStructHelper(const ShaderData *rShaderData, + const int propertyInBlockNameId, + const int propertyNameId, + const ShaderData::PropertyValue *value); + void buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName = QString()); - bool updatedPropertiesOnly; - QHash<QString, ShaderUniform> uniforms; UniformBlockValueBuilderHash activeUniformNamesToValue; - ShaderDataManager *shaderDataManager; - TextureManager *textureManager; - Matrix4x4 viewMatrix; + +private: + const QVector<int> &m_uniformNamesIds; + ShaderDataManager *m_shaderDataManager = nullptr; + TextureManager *m_textureManager = nullptr; + const Matrix4x4 &m_viewMatrix; }; } // namespace OpenGL diff --git a/src/plugins/renderers/opengl/renderer/renderview.cpp b/src/plugins/renderers/opengl/renderer/renderview.cpp index 7854c0ec5..5e4278bb8 100644 --- a/src/plugins/renderers/opengl/renderer/renderview.cpp +++ b/src/plugins/renderers/opengl/renderer/renderview.cpp @@ -72,6 +72,7 @@ #include <graphicscontext_p.h> #include <submissioncontext_p.h> #include <glresourcemanagers_p.h> +#include <renderviewjobutils_p.h> #include <Qt3DCore/qentity.h> #include <QtGui/qsurface.h> #include <algorithm> @@ -825,14 +826,6 @@ EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Ent void RenderView::updateRenderCommand(const EntityRenderCommandDataSubView &subView) { - // Note: since many threads can be building render commands - // we need to ensure that the UniformBlockValueBuilder they are using - // is only accessed from the same thread - UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); - builder->shaderDataManager = m_manager->shaderDataManager(); - builder->textureManager = m_manager->textureManager(); - m_localData.setLocalData(builder); - subView.forEach([this] (const Entity *entity, const RenderPassParameterData &passData, RenderCommand &command) { @@ -855,9 +848,6 @@ void RenderView::updateRenderCommand(const EntityRenderCommandDataSubView &subVi passData.parameterInfo, entity); }); - - // We reset the local data once we are done with it - m_localData.setLocalData(nullptr); } void RenderView::updateMatrices() @@ -962,23 +952,19 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, const GLShader *shader, - const ShaderData *shaderData, + ShaderData *shaderData, const QString &structName) const { - UniformBlockValueBuilder *builder = m_localData.localData(); - builder->activeUniformNamesToValue.clear(); - - // Set the view matrix to be used to transform "Transformed" properties in the ShaderData - builder->viewMatrix = m_viewMatrix; - // Force to update the whole block - builder->updatedPropertiesOnly = false; - // Retrieve names and description of each active uniforms in the uniform block - builder->uniforms = shader->activeUniformsForUniformBlock(-1); + UniformBlockValueBuilder builder(shader->uniformsNamesIds(), + m_manager->shaderDataManager(), + m_manager->textureManager(), + m_viewMatrix); + // Build name-value map for the block - builder->buildActiveUniformNameValueMapStructHelper(shaderData, structName); + builder.buildActiveUniformNameValueMapStructHelper(shaderData, structName); // Set uniform values for each entrie of the block name-value map - QHash<int, QVariant>::const_iterator activeValuesIt = builder->activeUniformNamesToValue.constBegin(); - const QHash<int, QVariant>::const_iterator activeValuesEnd = builder->activeUniformNamesToValue.constEnd(); + QHash<int, QVariant>::const_iterator activeValuesIt = builder.activeUniformNamesToValue.constBegin(); + const QHash<int, QVariant>::const_iterator activeValuesEnd = builder.activeUniformNamesToValue.constEnd(); // TO DO: Make the ShaderData store UniformValue while (activeValuesIt != activeValuesEnd) { diff --git a/src/plugins/renderers/opengl/renderer/renderview_p.h b/src/plugins/renderers/opengl/renderer/renderview_p.h index df326a15b..9765c9976 100644 --- a/src/plugins/renderers/opengl/renderer/renderview_p.h +++ b/src/plugins/renderers/opengl/renderer/renderview_p.h @@ -69,8 +69,6 @@ #include <Qt3DRender/private/aligned_malloc_p.h> #include <renderer_p.h> -// TODO: Move out once this is all refactored -#include <renderviewjobutils_p.h> #include <QVector> #include <QSurface> @@ -289,8 +287,6 @@ private: void updateLightUniforms(RenderCommand *command, const Entity *entity) const; - mutable QThreadStorage<UniformBlockValueBuilder*> m_localData; - Renderer *m_renderer = nullptr; NodeManagers *m_manager = nullptr; EntityRenderCommandDataViewPtr m_renderCommandDataView; @@ -386,7 +382,7 @@ private: const UniformValue &value) const; void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, const GLShader *shader, - const ShaderData *shaderData, + ShaderData *shaderData, const QString &structName) const; void applyParameter(const Parameter *param, RenderCommand *command, 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 diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h index a1491b328..06b0794ed 100644 --- a/src/render/materialsystem/shaderdata_p.h +++ b/src/render/materialsystem/shaderdata_p.h @@ -53,8 +53,10 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/qshaderdata.h> -#include <QMutex> #include <Qt3DCore/private/matrix4x4_p.h> +#include <mutex> +#include <shared_mutex> +#include <unordered_map> QT_BEGIN_NAMESPACE @@ -77,8 +79,10 @@ public: }; struct PropertyValue { QVariant value; - bool isNested; + bool isNode; + bool isArray; bool isTransformed; + QString transformedPropertyName; }; ShaderData(); @@ -89,7 +93,7 @@ public: // Called by FramePreparationJob void updateWorldTransform(const Matrix4x4 &worldMatrix); - QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const noexcept; + QVariant getTransformedProperty(const PropertyValue *v, const Matrix4x4 &viewMatrix) const noexcept; // Unit tests purposes only TransformType propertyTransformType(const QString &name) const; @@ -103,13 +107,22 @@ public: void cleanup() {} #endif + // Block.Property nameId, property nameId, PropertyValue * + using PropertyValuesForBlock = std::vector<std::tuple<int, int, const PropertyValue *>>; + + bool hasPropertyValuesForBlock(int blockNameId) const; + const PropertyValuesForBlock &propertyValuesForBlock(int blockNameId) const; + void generatePropertyValuesForBlock(const QString &blockName); + protected: PropertyReaderInterfacePtr m_propertyReader; - // 1 to 1 match with frontend properties QHash<QString, PropertyValue> m_originalProperties; + // BlockNameId to array of pair of BlockName+PropertyName PropertyValue + std::unordered_map<int, PropertyValuesForBlock> m_blockNameToPropertyValues; + Matrix4x4 m_worldMatrix; NodeManagers *m_managers; @@ -117,6 +130,9 @@ protected: ShaderData *lookupResource(Qt3DCore::QNodeId id); friend class RenderShaderDataFunctor; + +private: + mutable std::shared_mutex m_lock; }; class RenderShaderDataFunctor : public Qt3DCore::QBackendNodeMapper diff --git a/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp index add519b91..39e196b0e 100644 --- a/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp @@ -34,6 +34,7 @@ #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/stringtoint_p.h> #include <Qt3DRender/qshaderdata.h> +#include <QVariant> #include "testrenderer.h" #include "testarbiter.h" @@ -116,6 +117,16 @@ public: return uniforms; } + QVector<int> buildUniformMapNameIds(const QString &blockName) const + { + QVector<int> ids; + + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + QStringLiteral(".scalar"))); + + return ids; + } + + Q_SIGNALS: void scalarChanged(); @@ -157,6 +168,15 @@ public: return uniforms; } + QVector<int> buildUniformMapNameIds(const QString &blockName) const + { + QVector<int> ids; + + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + QStringLiteral(".texture"))); + + return ids; + } + Q_SIGNALS: void textureChanged(); @@ -198,6 +218,15 @@ public: return uniforms; } + QVector<int> buildUniformMapNameIds(const QString &blockName) const + { + QVector<int> ids; + + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + QStringLiteral(".array[0]"))); + + return ids; + } + Q_SIGNALS: void arrayChanged(); @@ -264,6 +293,17 @@ public: return uniforms; } + QVector<int> buildUniformMapNameIds(const QString &blockName) const + { + QVector<int> ids; + + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + QStringLiteral(".scalar"))); + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + QStringLiteral(".array[0]"))); + + return ids; + } + + Q_SIGNALS: void scalarChanged(); void arrayChanged(); @@ -337,6 +377,26 @@ public: return uniformsValues; } + QVector<int> buildUniformMapNameIds(const QString &blockName) const + { + QVector<int> ids; + QHash<QString, Qt3DRender::Render::OpenGL::ShaderUniform> innerUniforms; + + StructShaderData *innerData = nullptr; + if ((innerData = qobject_cast<StructShaderData *>(m_inner)) != nullptr) + innerUniforms = innerData->buildUniformMap(QStringLiteral(".inner")); + + QHash<QString, Qt3DRender::Render::OpenGL::ShaderUniform>::const_iterator it = innerUniforms.begin(); + const QHash<QString, Qt3DRender::Render::OpenGL::ShaderUniform>::const_iterator end = innerUniforms.end(); + + while (it != end) { + ids.push_back(Qt3DRender::Render::StringToInt::lookupId(blockName + it.key())); + ++it; + } + + return ids; + } + Q_SIGNALS: void innerChanged(); @@ -361,10 +421,11 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() QVERIFY(backendShaderData != nullptr); // WHEB - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; + const Matrix4x4 v; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder({}, + manager.data(), + textureManager.data(), + v); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); @@ -390,16 +451,16 @@ void tst_RenderViewUtils::topLevelScalarValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + const Matrix4x4 v; + const auto nameIds = shaderData->buildUniformMapNameIds(QStringLiteral("MyBlock")); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(nameIds, + manager.data(), + textureManager.data(), + v); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN @@ -408,7 +469,6 @@ void tst_RenderViewUtils::topLevelScalarValue() while (it != end) { // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), QVariant(shaderData->scalar())); ++it; } @@ -431,11 +491,12 @@ void tst_RenderViewUtils::topLevelTextureValueNoUniforms() Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); - // WHEB - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; + // WHEN + const Matrix4x4 v; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder({}, + manager.data(), + textureManager.data(), + v); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); @@ -463,16 +524,17 @@ void tst_RenderViewUtils::topLevelTextureValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + const Matrix4x4 v; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(shaderData->buildUniformMapNameIds(QStringLiteral("MyBlock")), + manager.data(), + textureManager.data(), + v); + + // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN @@ -481,7 +543,6 @@ void tst_RenderViewUtils::topLevelTextureValue() while (it != end) { // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), QVariant::fromValue(shaderData->texture()->id())); ++it; } @@ -505,16 +566,16 @@ void tst_RenderViewUtils::topLevelArrayValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + const Matrix4x4 v; + const auto nameIds = shaderData->buildUniformMapNameIds(QStringLiteral("MyBlock")); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(nameIds, + manager.data(), + textureManager.data(), + v); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN @@ -523,7 +584,6 @@ void tst_RenderViewUtils::topLevelArrayValue() while (it != end) { // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), QVariant(arrayValues)); ++it; } @@ -570,29 +630,31 @@ void tst_RenderViewUtils::nestedShaderDataValue() QVERIFY(backendShaderData3 != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); + const Matrix4x4 v; + const QVector<int> nameIds = { + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.array[0].scalar")), + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.array[1].scalar")), + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.array[2].scalar")), + }; + + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(nameIds, + manager.data(), + textureManager.data(), + v); + // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendArrayShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 3); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); // WHEN - auto it = blockBuilder.uniforms.cbegin(); - const auto end = blockBuilder.uniforms.cend(); + auto it = blockBuilder.activeUniformNamesToValue.cbegin(); + const auto end = blockBuilder.activeUniformNamesToValue.cend(); while (it != end) { // THEN - const int nameId = Qt3DRender::Render::StringToInt::lookupId(it.key()); - QVERIFY(blockBuilder.activeUniformNamesToValue.contains(nameId)); - QCOMPARE(blockBuilder.activeUniformNamesToValue[nameId], scalarValues.value(it.key())); + QCOMPARE(it.value(), scalarValues.value(Qt3DRender::Render::StringToInt::lookupString(it.key()))); ++it; } } @@ -646,17 +708,19 @@ void tst_RenderViewUtils::topLevelStructValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(blockName); + const Matrix4x4 v; + const auto nameIds = shaderData->buildUniformMapNameIds(blockName); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(nameIds, + manager.data(), + textureManager.data(), + v); + const QHash<QString, QVariant> expectedValues = shaderData->buildUniformMapValues(blockName); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, blockName); // THEN - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), blockBuilder.uniforms.count()); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), shaderData->buildUniformMapNameIds(blockName).size()); // WHEN Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); @@ -664,7 +728,6 @@ void tst_RenderViewUtils::topLevelStructValue() while (it != end) { // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QVERIFY(expectedValues.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), expectedValues.value(Qt3DRender::Render::StringToInt::lookupString(it.key()))); ++it; @@ -692,18 +755,20 @@ void tst_RenderViewUtils::topLevelDynamicProperties() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::OpenGL::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::OpenGL::ShaderUniform()); + const Matrix4x4 v; + const QVector<int> nameIds = { + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.scalar")), + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.array[0]")), + Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("MyBlock.texture")), + }; + + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder(nameIds, + manager.data(), + textureManager.data(), + v); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); - // THEN - QVERIFY(blockBuilder.uniforms.count() == 3); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.scalar")), @@ -756,10 +821,16 @@ void tst_RenderViewUtils::transformedProperties() // WHEN backendShaderData->updateWorldTransform(worldMatrix); - const Vector3D position1Value = backendShaderData->getTransformedProperty(QStringLiteral("position1"), viewMatrix).value<Vector3D>(); - const Vector3D position2Value = backendShaderData->getTransformedProperty(QStringLiteral("position2"), viewMatrix).value<Vector3D>(); - const Vector3D position3Value = backendShaderData->getTransformedProperty(QStringLiteral("position3"), viewMatrix).value<Vector3D>(); - const QVariant position0Value = backendShaderData->getTransformedProperty(QStringLiteral("position0"), viewMatrix); + const QHash<QString, Qt3DRender::Render::ShaderData::PropertyValue> &props = backendShaderData->properties(); + const Qt3DRender::Render::ShaderData::PropertyValue propPos1 = props[QStringLiteral("position1")]; + const Qt3DRender::Render::ShaderData::PropertyValue propPos2 = props[QStringLiteral("position2")]; + const Qt3DRender::Render::ShaderData::PropertyValue propPos3 = props[QStringLiteral("position3")]; + const Qt3DRender::Render::ShaderData::PropertyValue propPos0 = props[QStringLiteral("position0")]; + + const Vector3D position1Value = backendShaderData->getTransformedProperty(&propPos1, viewMatrix).value<Vector3D>(); + const Vector3D position2Value = backendShaderData->getTransformedProperty(&propPos2, viewMatrix).value<Vector3D>(); + const Vector3D position3Value = backendShaderData->getTransformedProperty(&propPos3, viewMatrix).value<Vector3D>(); + const QVariant position0Value = backendShaderData->getTransformedProperty(&propPos0, viewMatrix); // THEN QCOMPARE(position0Value, positionQt); diff --git a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp index 006226a7b..025138f3c 100644 --- a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp +++ b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp @@ -203,14 +203,15 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::ShaderData *backendShaderData = collection.backendShaderData.first(); + const QHash<QString, Qt3DRender::Render::ShaderData::PropertyValue> &props = backendShaderData->properties(); // THEN - QCOMPARE(backendShaderData->properties().size(), 3); - QVERIFY(backendShaderData->properties().contains(QStringLiteral("eyePosition"))); - QVERIFY(backendShaderData->properties().contains(QStringLiteral("eyePositionTransformed"))); + QCOMPARE(props.size(), 3); + QVERIFY(props.contains(QStringLiteral("eyePosition"))); + QVERIFY(props.contains(QStringLiteral("eyePositionTransformed"))); - QCOMPARE(backendShaderData->properties()[QStringLiteral("eyePosition")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f)); - QCOMPARE(backendShaderData->properties()[QStringLiteral("eyePositionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToEye)); + QCOMPARE(props[QStringLiteral("eyePosition")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(props[QStringLiteral("eyePositionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToEye)); // WHEN Qt3DRender::Render::UpdateShaderDataTransformJob backendUpdateShaderDataTransformJob; @@ -219,7 +220,8 @@ private Q_SLOTS: // THEN // See scene file to find translation - QCOMPARE(backendShaderData->getTransformedProperty(QStringLiteral("eyePosition"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(), + const Qt3DRender::Render::ShaderData::PropertyValue propertyValue = props[QStringLiteral("eyePosition")]; + QCOMPARE(backendShaderData->getTransformedProperty(&propertyValue, Matrix4x4(camera->viewMatrix())).value<Vector3D>(), Matrix4x4(camera->viewMatrix()) * (Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(0.0f, 5.0f, 0.0f))); } @@ -244,14 +246,15 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::ShaderData *backendShaderData = collection.backendShaderData.first(); + const QHash<QString, Qt3DRender::Render::ShaderData::PropertyValue> &props = backendShaderData->properties(); // THEN - QCOMPARE(backendShaderData->properties().size(), 3); - QVERIFY(backendShaderData->properties().contains(QStringLiteral("position"))); - QVERIFY(backendShaderData->properties().contains(QStringLiteral("positionTransformed"))); + QCOMPARE(props.size(), 3); + QVERIFY(props.contains(QStringLiteral("position"))); + QVERIFY(props.contains(QStringLiteral("positionTransformed"))); - QCOMPARE(backendShaderData->properties()[QStringLiteral("position")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f)); - QCOMPARE(backendShaderData->properties()[QStringLiteral("positionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToWorld)); + QCOMPARE(props[QStringLiteral("position")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(props[QStringLiteral("positionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToWorld)); // WHEN Qt3DRender::Render::UpdateShaderDataTransformJob backendUpdateShaderDataTransformJob; @@ -260,7 +263,8 @@ private Q_SLOTS: // THEN // See scene file to find translation - QCOMPARE(backendShaderData->getTransformedProperty(QStringLiteral("position"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(), + const Qt3DRender::Render::ShaderData::PropertyValue propertyValue = props[QStringLiteral("position")]; + QCOMPARE(backendShaderData->getTransformedProperty(&propertyValue, Matrix4x4(camera->viewMatrix())).value<Vector3D>(), Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(5.0f, 5.0f, 5.0f)); } }; |