summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp111
-rw-r--r--src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h28
-rw-r--r--src/plugins/renderers/opengl/renderer/renderview.cpp34
-rw-r--r--src/plugins/renderers/opengl/renderer/renderview_p.h6
-rw-r--r--src/render/materialsystem/shaderdata.cpp100
-rw-r--r--src/render/materialsystem/shaderdata_p.h24
-rw-r--r--tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp197
-rw-r--r--tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp28
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));
}
};