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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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