1// Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "uniformblockbuilder_p.h"
5#include <QString>
6#include <Qt3DRender/private/nodemanagers_p.h>
7#include <Qt3DRender/private/managers_p.h>
8#include <Qt3DRender/private/stringtoint_p.h>
9#include <Qt3DCore/private/vector_helper_p.h>
10
11QT_BEGIN_NAMESPACE
12
13using namespace Qt3DCore;
14
15namespace Qt3DRender {
16namespace Render {
17
18namespace {
19
20const QString blockArray = QStringLiteral("[%1]");
21const int qNodeIdTypeId = qMetaTypeId<QNodeId>();
22
23}
24
25UniformBlockValueBuilder::UniformBlockValueBuilder(
26 const std::vector<int> &uniformNamesIds,
27 ShaderDataManager *shaderDataManager,
28 TextureManager *textureManager,
29 const Matrix4x4 &matrix)
30 : m_uniformNamesIds(uniformNamesIds)
31 , m_shaderDataManager(shaderDataManager)
32 , m_textureManager(textureManager)
33 , m_viewMatrix(matrix)
34{
35}
36
37void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData,
38 const QString &blockName,
39 const int propertyInBlockNameId,
40 const int propertyNameId,
41 const ShaderData::PropertyValue *value)
42{
43 // In the end, values are either scalar or a scalar array
44 // Composed elements (structs, structs array) are simplified into simple scalars
45 if (value->isArray) { // Array
46 const QVariantList list = value->value.value<QVariantList>();
47 if (value->isNode) { // Array of struct qmlPropertyName[i].structMember
48 for (int i = 0; i < list.size(); ++i) {
49 const QVariant variantElement = list.at(i);
50 if (list.at(i).userType() == qNodeIdTypeId) {
51 const auto nodeId = variantElement.value<QNodeId>();
52 ShaderData *subShaderData = m_shaderDataManager->lookupResource(id: nodeId);
53 if (subShaderData) {
54 buildActiveUniformNameValueMapStructHelper(rShaderData: subShaderData,
55 blockName: blockName + QLatin1Char('.') + StringToInt::lookupString(idx: propertyNameId) + blockArray.arg(a: i));
56 }
57 // Note: we only handle ShaderData as nested container nodes here
58 }
59 }
60 } else { // Array of scalar/vec qmlPropertyName[0]
61 if (Qt3DCore::contains(destination: m_uniformNamesIds, element: propertyInBlockNameId)) {
62 activeUniformNamesToValue.insert(key: propertyInBlockNameId, value: value->value);
63 }
64 }
65 } else if (value->isNode) { // Struct qmlPropertyName.structMember
66 const auto nodeId = value->value.value<QNodeId>();
67 ShaderData *rSubShaderData = m_shaderDataManager->lookupResource(id: nodeId);
68 if (rSubShaderData) {
69 buildActiveUniformNameValueMapStructHelper(rShaderData: rSubShaderData,
70 blockName,
71 qmlPropertyName: StringToInt::lookupString(idx: propertyNameId));
72 } else if (m_textureManager->contains(id: nodeId)) {
73 activeUniformNamesToValue.insert(key: propertyInBlockNameId, value: value->value);
74 }
75 } else { // Scalar / Vec
76 if (Qt3DCore::contains(destination: m_uniformNamesIds, element: propertyInBlockNameId)) {
77 // If the property needs to be transformed, we transform it here as
78 // the shaderdata cannot hold transformed properties for multiple
79 // thread contexts at once
80 activeUniformNamesToValue.insert(key: propertyInBlockNameId,
81 value: currentShaderData->getTransformedProperty(v: value, viewMatrix: m_viewMatrix));
82 }
83 }
84}
85
86void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData,
87 const QString &blockName,
88 const QString &qmlPropertyName)
89{
90 QString fullBlockName;
91 fullBlockName.reserve(asize: blockName.size() + 1 + qmlPropertyName.size());
92 fullBlockName.append(s: blockName);
93 if (!qmlPropertyName.isEmpty()) {
94 fullBlockName.append(s: QLatin1String("."));
95 fullBlockName.append(s: qmlPropertyName);
96 }
97
98 // Retrieve set of {NameId -> PropertyValue} for Block
99 const int fullBlockNameId = StringToInt::lookupId(str: fullBlockName);
100 if (!rShaderData->hasPropertyValuesForBlock(blockNameId: fullBlockNameId))
101 rShaderData->generatePropertyValuesForBlock(blockName: fullBlockName);
102 const ShaderData::PropertyValuesForBlock &propertiesForBlock = rShaderData->propertyValuesForBlock(blockNameId: fullBlockNameId);
103
104 for (const auto &nameIdPropertyPair : propertiesForBlock) {
105 buildActiveUniformNameValueMapHelper(currentShaderData: rShaderData,
106 blockName: fullBlockName,
107 // Block.Property Name
108 propertyInBlockNameId: std::get<0>(t: nameIdPropertyPair),
109 // Property Name
110 propertyNameId: std::get<1>(t: nameIdPropertyPair),
111 // PropertyValue
112 value: std::get<2>(t: nameIdPropertyPair));
113 }
114}
115
116
117} // namespace Render
118} // namespace Qt3DRender
119
120QT_END_NAMESPACE
121

source code of qt3d/src/render/jobs/uniformblockbuilder.cpp