1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "uniformblockbuilder_p.h"
#include <QString>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DCore/private/vector_helper_p.h>
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
namespace {
const QString blockArray = QStringLiteral("[%1]");
const int qNodeIdTypeId = qMetaTypeId<QNodeId>();
}
UniformBlockValueBuilder::UniformBlockValueBuilder(
const std::vector<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 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->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 = m_shaderDataManager->lookupResource(nodeId);
if (subShaderData) {
buildActiveUniformNameValueMapStructHelper(subShaderData,
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]
if (Qt3DCore::contains(m_uniformNamesIds, propertyInBlockNameId)) {
activeUniformNamesToValue.insert(propertyInBlockNameId, value->value);
}
}
} 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,
StringToInt::lookupString(propertyNameId));
} else if (m_textureManager->contains(nodeId)) {
activeUniformNamesToValue.insert(propertyInBlockNameId, value->value);
}
} else { // Scalar / Vec
if (Qt3DCore::contains(m_uniformNamesIds, 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(propertyInBlockNameId,
currentShaderData->getTransformedProperty(value, m_viewMatrix));
}
}
}
void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData,
const QString &blockName,
const QString &qmlPropertyName)
{
QString fullBlockName;
fullBlockName.reserve(blockName.size() + 1 + qmlPropertyName.size());
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));
}
}
} // namespace Render
} // namespace Qt3DRender
QT_END_NAMESPACE
|