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 "rhishader_p.h"
5#include <QMutexLocker>
6#include <Qt3DCore/private/vector_helper_p.h>
7#include <Qt3DRender/private/stringtoint_p.h>
8#include <submissioncontext_p.h>
9#include <logging_p.h>
10#include <QRegularExpression>
11
12QT_BEGIN_NAMESPACE
13
14namespace Qt3DRender {
15
16namespace Render {
17
18namespace Rhi {
19
20RHIShader::RHIShader() : m_isLoaded(false)
21{
22 m_shaderCode.resize(new_size: static_cast<int>(QShaderProgram::Compute) + 1);
23}
24
25const std::vector<QString> &RHIShader::uniformsNames() const
26{
27 return m_uniformsNames;
28}
29
30const std::vector<QString> &RHIShader::attributesNames() const
31{
32 return m_attributesNames;
33}
34
35const std::vector<QString> &RHIShader::uniformBlockNames() const
36{
37 return m_uniformBlockNames;
38}
39
40const std::vector<QString> &RHIShader::storageBlockNames() const
41{
42 return m_shaderStorageBlockNames;
43}
44
45const std::vector<QString> &RHIShader::samplerNames() const
46{
47 return m_samplerNames;
48}
49
50const std::vector<QString> &RHIShader::imagesNames() const
51{
52 return m_imageNames;
53}
54
55const std::vector<QByteArray> &RHIShader::shaderCode() const
56{
57 return m_shaderCode;
58}
59
60namespace {
61
62static constexpr int rhiTypeSize(QShaderDescription::VariableType type)
63{
64 switch (type) {
65 case QShaderDescription::Unknown:
66 return 0;
67
68 case QShaderDescription::Float:
69 return 1;
70 case QShaderDescription::Vec2:
71 return 2;
72 case QShaderDescription::Vec3:
73 return 3;
74 case QShaderDescription::Vec4:
75 return 4;
76 case QShaderDescription::Mat2:
77 return 2 * 2;
78 case QShaderDescription::Mat2x3:
79 return 2 * 3;
80 case QShaderDescription::Mat2x4:
81 return 2 * 4;
82 case QShaderDescription::Mat3:
83 return 3 * 3;
84 case QShaderDescription::Mat3x2:
85 return 3 * 2;
86 case QShaderDescription::Mat3x4:
87 return 3 * 4;
88 case QShaderDescription::Mat4:
89 return 4 * 4;
90 case QShaderDescription::Mat4x2:
91 return 4 * 2;
92 case QShaderDescription::Mat4x3:
93 return 4 * 3;
94
95 case QShaderDescription::Int:
96 return 1;
97 case QShaderDescription::Int2:
98 return 2;
99 case QShaderDescription::Int3:
100 return 3;
101 case QShaderDescription::Int4:
102 return 4;
103
104 case QShaderDescription::Uint:
105 return 1;
106 case QShaderDescription::Uint2:
107 return 2;
108 case QShaderDescription::Uint3:
109 return 3;
110 case QShaderDescription::Uint4:
111 return 4;
112
113 case QShaderDescription::Bool:
114 return 1;
115 case QShaderDescription::Bool2:
116 return 2;
117 case QShaderDescription::Bool3:
118 return 3;
119 case QShaderDescription::Bool4:
120 return 4;
121
122 case QShaderDescription::Double:
123 return 1;
124 case QShaderDescription::Double2:
125 return 2;
126 case QShaderDescription::Double3:
127 return 3;
128 case QShaderDescription::Double4:
129 return 4;
130 case QShaderDescription::DMat2:
131 return 2 * 2;
132 case QShaderDescription::DMat2x3:
133 return 2 * 3;
134 case QShaderDescription::DMat2x4:
135 return 2 * 4;
136 case QShaderDescription::DMat3:
137 return 3 * 3;
138 case QShaderDescription::DMat3x2:
139 return 3 * 2;
140 case QShaderDescription::DMat3x4:
141 return 3 * 4;
142 case QShaderDescription::DMat4:
143 return 4 * 4;
144 case QShaderDescription::DMat4x2:
145 return 4 * 2;
146 case QShaderDescription::DMat4x3:
147 return 4 * 3;
148
149 case QShaderDescription::Sampler1D:
150 return 0;
151 case QShaderDescription::Sampler2D:
152 return 0;
153 case QShaderDescription::Sampler2DMS:
154 return 0;
155 case QShaderDescription::Sampler3D:
156 return 0;
157 case QShaderDescription::SamplerCube:
158 return 0;
159 case QShaderDescription::Sampler1DArray:
160 return 0;
161 case QShaderDescription::Sampler2DArray:
162 return 0;
163 case QShaderDescription::Sampler2DMSArray:
164 return 0;
165 case QShaderDescription::Sampler3DArray:
166 return 0;
167 case QShaderDescription::SamplerCubeArray:
168 return 0;
169 case QShaderDescription::SamplerRect:
170 return 0;
171 case QShaderDescription::SamplerBuffer:
172 return 0;
173
174 case QShaderDescription::Image1D:
175 return 0;
176 case QShaderDescription::Image2D:
177 return 0;
178 case QShaderDescription::Image2DMS:
179 return 0;
180 case QShaderDescription::Image3D:
181 return 0;
182 case QShaderDescription::ImageCube:
183 return 0;
184 case QShaderDescription::Image1DArray:
185 return 0;
186 case QShaderDescription::Image2DArray:
187 return 0;
188 case QShaderDescription::Image2DMSArray:
189 return 0;
190 case QShaderDescription::Image3DArray:
191 return 0;
192 case QShaderDescription::ImageCubeArray:
193 return 0;
194 case QShaderDescription::ImageRect:
195 return 0;
196 case QShaderDescription::ImageBuffer:
197 return 0;
198
199 case QShaderDescription::Struct:
200 return 0;
201 default:
202 return 0;
203 }
204}
205
206template<typename T, typename Pred>
207std::vector<T> stableRemoveDuplicates(std::vector<T> in, Pred predicate)
208{
209 std::vector<T> out;
210 for (const auto &element : in) {
211 if (std::none_of(out.begin(), out.end(),
212 [&](T &other) { return predicate(element, other); }))
213 out.push_back(element);
214 }
215 return out;
216}
217
218// Utility function to enumerate an array of dimensions
219// Given dims == [0, 3, 2] and maxs == [4, 4, 4]
220// changes dims into [0, 3, 3]
221// Given dims == [0, 3, 3] and maxs == [4, 4, 4]
222// changes dims into [1, 0, 0]
223bool incrementArray(QVarLengthArray<int> &dims, const QList<int> &maxs)
224{
225 const int n = dims.size();
226 int i = n;
227 for (; i-- > 0;) {
228 if (dims[i] == maxs[i] - 1) {
229 if (i == 0) {
230 // we're done
231 return false;
232 }
233 continue;
234
235 } else {
236 dims[i]++;
237 for (int j = i + 1; j < n; j++) {
238 dims[j] = 0;
239 }
240 return true;
241 }
242 }
243 return false;
244}
245
246// Call a function with a string such as [0][3][2]
247// for all valable array values, given an array of dimension sizes.
248// Dimensions must all be >= 1
249template<typename F>
250void forEachArrayAccessor(const QList<int> &maxs, F f)
251{
252 if (std::any_of(maxs.begin(), maxs.end(), [](int v) { return v <= 0; }))
253 return;
254
255 QVarLengthArray<int> dims;
256 dims.resize(sz: maxs.size());
257
258 // QVarLengthArray does not initialize ints
259 std::fill(first: dims.begin(), last: dims.end(), value: 0);
260
261 QString str;
262
263 do {
264 str.resize(size: 0);
265 for (int k : dims) {
266 str += QStringLiteral("[%1]").arg(a: k);
267 }
268 f(str);
269 } while (incrementArray(dims, maxs));
270}
271}
272
273void RHIShader::recordAllUniforms(UBO_Member &uboMember,
274 QString parentName)
275{
276 const QShaderDescription::BlockVariable &member = uboMember.blockVariable;
277 const bool isStruct = !member.structMembers.empty();
278 const bool isArray = !member.arrayDims.empty();
279
280 // "foo.bar"
281 const QString fullMemberName = parentName + member.name;
282 m_unqualifiedUniformNames << fullMemberName;
283
284 if (isStruct && !isArray) {
285 m_structNames.push_back(x: fullMemberName);
286 m_structNamesIds.push_back(x: StringToInt::lookupId(str: fullMemberName));
287
288 for (const QShaderDescription::BlockVariable& bv : member.structMembers) {
289 UBO_Member innerMember {.nameId: StringToInt::lookupId(str: fullMemberName), .blockVariable: bv, .structMembers: {}};
290 // recordAllUniforms("baz", "foo.bar.")
291 const QString structMemberNamePrefix = fullMemberName + QLatin1Char('.');
292 recordAllUniforms(uboMember&: innerMember, parentName: structMemberNamePrefix);
293 uboMember.structMembers.push_back(x: innerMember);
294 }
295 } else if (!isStruct && isArray) {
296 // We iterate through all the [l][n][m] by building [0][0][0] and incrementing
297 forEachArrayAccessor(maxs: member.arrayDims, f: [&](const QString &str) {
298 // "foo.bar[1][2]"
299 const QString unqualifiedMemberName = (fullMemberName + str);
300 m_unqualifiedUniformNames << unqualifiedMemberName;
301
302 // Record as an individual uniform
303 m_uniformsNames.push_back(x: unqualifiedMemberName);
304 const int nameId = StringToInt::lookupId(str: unqualifiedMemberName);
305 m_uniformsNamesIds.push_back(x: nameId);
306
307 // Question : does it make sense to also record foo[0], foo[0][0], etc...
308 // if there are e.g. 3 dimensions ?
309 });
310 }
311 else if (isStruct && isArray) {
312 // Record the struct names
313 forEachArrayAccessor(maxs: member.arrayDims, f: [&] (const QString& str) {
314 m_structNames.push_back(x: fullMemberName + str);
315 m_structNamesIds.push_back(x: StringToInt::lookupId(str: m_structNames.back()));
316 });
317
318 // Record the array times the struct members => entry[i].struct_member
319 forEachArrayAccessor(maxs: member.arrayDims, f: [&] (const QString& str) {
320 UBO_Member arrayMember {.nameId: StringToInt::lookupId(str: fullMemberName + str), .blockVariable: {}, .structMembers: {}};
321 // Record all struct member into the array member[i]
322 for (const QShaderDescription::BlockVariable& bv : member.structMembers) {
323 //recordAllUniforms("baz", "foo.bar[1][2].")
324 const QString structMemberNamePrefix = fullMemberName + str + QLatin1Char('.');
325 UBO_Member innerMember {.nameId: StringToInt::lookupId(str: structMemberNamePrefix), .blockVariable: bv, .structMembers: {}};
326 recordAllUniforms(uboMember&: innerMember, parentName: structMemberNamePrefix);
327 arrayMember.structMembers.push_back(x: innerMember);
328 }
329 // When dealing with an array of structs, we treat structMembers as arrayMembers
330 uboMember.structMembers.push_back(x: arrayMember);
331 });
332 } else {
333 // Final member (not array or struct)
334 // Replace nameId with final nameId name
335 uboMember.nameId = StringToInt::lookupId(str: fullMemberName);
336
337 // Record as an individual uniform
338 m_uniformsNames.push_back(x: fullMemberName);
339 const int nameId = StringToInt::lookupId(str: fullMemberName);
340 m_uniformsNamesIds.push_back(x: nameId);
341 }
342}
343
344namespace {
345// Function to check whether the array conforms to the regex
346// "_[0-9]+" - except QRegularExpression does not support QByteArray
347bool isGeneratedUBOName(const QByteArray& arr)
348{
349 if (arr.size() < 2)
350 return false;
351 if (!arr.startsWith(c: '_'))
352 return false;
353 for (qsizetype i = 1, N = arr.size(); i < N; i++) {
354 if (arr[i] < '0' || arr[i] > '9')
355 return false;
356 }
357 return true;
358}
359}
360
361void RHIShader::introspect()
362{
363 std::vector<QShaderDescription::UniformBlock> rhiUBO;
364 std::vector<QShaderDescription::StorageBlock> rhiSSBO;
365
366 std::vector<ShaderUniformBlock> uniformBlocks;
367 std::vector<ShaderStorageBlock> storageBlocks;
368 std::vector<ShaderAttribute> attributes;
369 std::vector<ShaderAttribute> samplers;
370 std::vector<ShaderAttribute> images;
371
372 if (m_stages[QShader::ComputeStage].isValid()) {
373 const QShaderDescription &comp = m_stages[QShader::ComputeStage].description();
374
375 Qt3DCore::append(destination&: rhiUBO, source: comp.uniformBlocks());
376 Qt3DCore::append(destination&: rhiSSBO, source: comp.storageBlocks());
377 }
378 else
379 {
380 // Introspect shader vertex input
381 if (m_stages[QShader::VertexStage].isValid()) {
382 const QShaderDescription &vtx = m_stages[QShader::VertexStage].description();
383
384 for (const QShaderDescription::InOutVariable &input : vtx.inputVariables()) {
385 attributes.push_back(x: ShaderAttribute { .m_name: input.name, .m_nameId: StringToInt::lookupId(str: input.name),
386 .m_type: input.type, .m_size: rhiTypeSize(type: input.type),
387 .m_location: input.location });
388 }
389
390 Qt3DCore::append(destination&: rhiUBO, source: vtx.uniformBlocks());
391 Qt3DCore::append(destination&: rhiSSBO, source: vtx.storageBlocks());
392 }
393
394 // Introspect shader uniforms
395 if (m_stages[QShader::FragmentStage].isValid()) {
396 const QShaderDescription &frag = m_stages[QShader::FragmentStage].description();
397 for (const QShaderDescription::InOutVariable &sampler : frag.combinedImageSamplers()) {
398 samplers.push_back(x: ShaderAttribute { .m_name: sampler.name, .m_nameId: StringToInt::lookupId(str: sampler.name),
399 .m_type: sampler.type, .m_size: rhiTypeSize(type: sampler.type),
400 .m_location: sampler.binding });
401 }
402 for (const QShaderDescription::InOutVariable &image : frag.storageImages()) {
403 images.push_back(x: ShaderAttribute { .m_name: image.name, .m_nameId: StringToInt::lookupId(str: image.name),
404 .m_type: image.type, .m_size: rhiTypeSize(type: image.type),
405 .m_location: image.binding });
406 }
407
408 Qt3DCore::append(destination&: rhiUBO, source: frag.uniformBlocks());
409 Qt3DCore::append(destination&: rhiSSBO, source: frag.storageBlocks());
410 }
411 }
412
413 rhiUBO = stableRemoveDuplicates(in: rhiUBO,
414 predicate: [](const QShaderDescription::UniformBlock &lhs,
415 const QShaderDescription::UniformBlock &rhs) {
416 return lhs.blockName == rhs.blockName;
417 });
418 rhiSSBO = stableRemoveDuplicates(in: rhiSSBO,
419 predicate: [](const QShaderDescription::StorageBlock &lhs,
420 const QShaderDescription::StorageBlock &rhs) {
421 return lhs.blockName == rhs.blockName;
422 });
423
424 for (const QShaderDescription::UniformBlock &ubo : rhiUBO) {
425 uniformBlocks.push_back(x: ShaderUniformBlock { .m_name: ubo.blockName,
426 .m_nameId: StringToInt::lookupId(str: ubo.blockName), .m_index: -1,
427 .m_binding: ubo.binding, .m_activeUniformsCount: int(ubo.members.size()), .m_size: ubo.size });
428 const bool addUnqualifiedUniforms = isGeneratedUBOName(arr: ubo.structName);
429
430 // Parse Uniform Block members so that we can later on map a Parameter name to an actual
431 m_uniformsNames.reserve(n: m_uniformsNames.size() + ubo.members.size());
432 m_uniformsNamesIds.reserve(n: m_uniformsNames.size());
433
434 std::vector<UBO_Member> uboMembers;
435 uboMembers.reserve(n: ubo.members.size());
436
437 for (const QShaderDescription::BlockVariable &member : std::as_const(t: ubo.members)) {
438 m_uniformsNames.push_back(x: member.name);
439 const int nameId = StringToInt::lookupId(str: member.name);
440 m_uniformsNamesIds.push_back(x: nameId);
441
442 UBO_Member uboMember {.nameId: nameId, .blockVariable: member, .structMembers: {}};
443 if (addUnqualifiedUniforms)
444 recordAllUniforms(uboMember, QStringLiteral(""));
445 uboMembers.push_back(x: uboMember);
446 }
447
448 m_uboBlocks.push_back(x: UBO_Block{ .block: uniformBlocks.back(), .members: uboMembers });
449 }
450
451 for (const QShaderDescription::StorageBlock &ssbo : rhiSSBO) {
452 storageBlocks.push_back(x: ShaderStorageBlock { .m_name: ssbo.blockName, .m_nameId: -1, .m_index: -1, .m_binding: ssbo.binding, .m_size: 0, .m_activeVariablesCount: 0 });
453 }
454
455 initializeAttributes(attributesDescription: attributes);
456 initializeUniformBlocks(uniformBlockDescription: uniformBlocks);
457 initializeShaderStorageBlocks(shaderStorageBlockDescription: storageBlocks);
458 initializeSamplers(samplerDescription: samplers);
459 initializeImages(imageDescription: images);
460
461 qCDebug(Shaders) << "Block Names" << m_uniformBlockNames;
462 qCDebug(Shaders) << "Uniform Names" << m_uniformsNames;
463 qCDebug(Shaders) << "SSBO Names" << m_shaderStorageBlockNames;
464 qCDebug(Shaders) << "Attribute Names" << m_attributesNames;
465
466}
467
468QHash<QString, ShaderUniform> RHIShader::activeUniformsForUniformBlock(int blockIndex) const
469{
470 return m_uniformBlockIndexToShaderUniforms.value(key: blockIndex);
471}
472
473ShaderUniformBlock RHIShader::uniformBlockForBlockIndex(int blockIndex) const noexcept
474{
475 for (size_t i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
476 if (m_uniformBlocks[i].m_index == blockIndex) {
477 return m_uniformBlocks[i];
478 }
479 }
480 return ShaderUniformBlock();
481}
482
483ShaderUniformBlock RHIShader::uniformBlockForBlockNameId(int blockNameId) const noexcept
484{
485 for (size_t i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
486 if (m_uniformBlocks[i].m_nameId == blockNameId) {
487 return m_uniformBlocks[i];
488 }
489 }
490 return ShaderUniformBlock();
491}
492
493ShaderUniformBlock RHIShader::uniformBlockForBlockName(const QString &blockName) const noexcept
494{
495 for (size_t i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
496 if (m_uniformBlocks[i].m_name == blockName) {
497 return m_uniformBlocks[i];
498 }
499 }
500 return ShaderUniformBlock();
501}
502
503ShaderUniformBlock RHIShader::uniformBlockForInstanceName(const QString &instanceName) const noexcept
504{
505 return uniformBlockForInstanceNameId(instanceNameId: StringToInt::lookupId(str: instanceName));
506}
507
508ShaderUniformBlock RHIShader::uniformBlockForInstanceNameId(int instanceNameId) const noexcept
509{
510 for (size_t i = 0, m = m_uboBlocks.size(); i < m; ++i) {
511 const UBO_Block &b = m_uboBlocks[i];
512 for (const UBO_Member &member : b.members) {
513 if (member.nameId == instanceNameId)
514 return b.block;
515 }
516 }
517 return ShaderUniformBlock();
518}
519
520ShaderStorageBlock RHIShader::storageBlockForBlockIndex(int blockIndex) const noexcept
521{
522 for (size_t i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
523 if (m_shaderStorageBlocks[i].m_index == blockIndex)
524 return m_shaderStorageBlocks[i];
525 }
526 return ShaderStorageBlock();
527}
528
529ShaderStorageBlock RHIShader::storageBlockForBlockNameId(int blockNameId) const noexcept
530{
531 for (size_t i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
532 if (m_shaderStorageBlocks[i].m_nameId == blockNameId)
533 return m_shaderStorageBlocks[i];
534 }
535 return ShaderStorageBlock();
536}
537
538ShaderStorageBlock RHIShader::storageBlockForBlockName(const QString &blockName) const noexcept
539{
540 for (size_t i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
541 if (m_shaderStorageBlocks[i].m_name == blockName)
542 return m_shaderStorageBlocks[i];
543 }
544 return ShaderStorageBlock();
545}
546
547RHIShader::ParameterKind RHIShader::categorizeVariable(int nameId) const noexcept
548{
549 if (Qt3DCore::contains(destination: m_uniformBlockNamesIds, element: nameId))
550 return ParameterKind::UBO;
551 else if (Qt3DCore::contains(destination: m_shaderStorageBlockNamesIds, element: nameId))
552 return ParameterKind::SSBO;
553 else if (Qt3DCore::contains(destination: m_structNamesIds, element: nameId))
554 return ParameterKind::Struct;
555 return ParameterKind::Uniform;
556}
557
558bool RHIShader::hasUniform(int nameId) const noexcept
559{
560 return Qt3DCore::contains(destination: m_uniformsNamesIds, element: nameId);
561}
562
563bool RHIShader::hasActiveVariables() const noexcept
564{
565 return !m_attributeNamesIds.empty() || !m_uniformsNamesIds.empty()
566 || !m_uniformBlockNamesIds.empty() || !m_shaderStorageBlockNamesIds.empty();
567}
568
569void RHIShader::setShaderCode(const std::vector<QByteArray> &shaderCode)
570{
571 m_shaderCode.clear();
572 Qt3DCore::append(destination&: m_shaderCode, source: shaderCode);
573}
574
575void RHIShader::setFragOutputs(const QHash<QString, int> &fragOutputs)
576{
577 {
578 QMutexLocker lock(&m_mutex);
579 m_fragOutputs = fragOutputs;
580 }
581 // updateDNA();
582}
583
584const QHash<QString, int> RHIShader::fragOutputs() const
585{
586 QMutexLocker lock(&m_mutex);
587 return m_fragOutputs;
588}
589
590void RHIShader::initializeAttributes(const std::vector<ShaderAttribute> &attributesDescription)
591{
592 m_attributes = attributesDescription;
593 m_attributesNames.resize(new_size: attributesDescription.size());
594 m_attributeNamesIds.resize(new_size: attributesDescription.size());
595 for (size_t i = 0, m = attributesDescription.size(); i < m; i++) {
596 m_attributesNames[i] = attributesDescription[i].m_name;
597 m_attributes[i].m_nameId = StringToInt::lookupId(str: m_attributesNames[i]);
598 m_attributeNamesIds[i] = m_attributes[i].m_nameId;
599 qCDebug(Shaders) << "Active Attribute " << attributesDescription[i].m_name;
600 }
601}
602
603void RHIShader::initializeSamplers(const std::vector<ShaderAttribute> &samplersDescription)
604{
605 m_samplers = samplersDescription;
606 m_samplerNames.resize(new_size: samplersDescription.size());
607 m_samplerIds.resize(new_size: samplersDescription.size());
608 for (size_t i = 0, m = samplersDescription.size(); i < m; i++) {
609 m_samplerNames[i] = samplersDescription[i].m_name;
610 m_samplers[i].m_nameId = StringToInt::lookupId(str: m_samplerNames[i]);
611 m_samplerIds[i] = m_samplers[i].m_nameId;
612 qCDebug(Shaders) << "Active sampler " << samplersDescription[i].m_name;
613 }
614}
615
616void RHIShader::initializeImages(const std::vector<ShaderAttribute> &imagesDescription)
617{
618 m_images = imagesDescription;
619 m_imageNames.resize(new_size: imagesDescription.size());
620 m_imageIds.resize(new_size: imagesDescription.size());
621 for (size_t i = 0, m = imagesDescription.size(); i < m; i++) {
622 m_imageNames[i] = imagesDescription[i].m_name;
623 m_images[i].m_nameId = StringToInt::lookupId(str: m_imageNames[i]);
624 m_imageIds[i] = m_images[i].m_nameId;
625 qCDebug(Shaders) << "Active image " << imagesDescription[i].m_name;
626 }
627}
628
629void RHIShader::initializeUniformBlocks(const std::vector<ShaderUniformBlock> &uniformBlockDescription)
630{
631 m_uniformBlocks = uniformBlockDescription;
632 m_uniformBlockNames.resize(new_size: uniformBlockDescription.size());
633 m_uniformBlockNamesIds.resize(new_size: uniformBlockDescription.size());
634 for (size_t i = 0, m = uniformBlockDescription.size(); i < m; ++i) {
635 m_uniformBlockNames[i] = m_uniformBlocks[i].m_name;
636 m_uniformBlockNamesIds[i] = StringToInt::lookupId(str: m_uniformBlockNames[i]);
637 m_uniformBlocks[i].m_nameId = m_uniformBlockNamesIds[i];
638 qCDebug(Shaders) << "Initializing Uniform Block {" << m_uniformBlockNames[i] << "}";
639
640 // Find all active uniforms for the shader block
641 std::vector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.cbegin();
642 const std::vector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.cend();
643
644 std::vector<QString>::const_iterator uniformNamesIt = m_uniformsNames.cbegin();
645 const std::vector<QString>::const_iterator uniformNamesEnd = m_uniformsNames.cend();
646
647 QHash<QString, ShaderUniform> activeUniformsInBlock;
648
649 while (uniformsIt != uniformsEnd && uniformNamesIt != uniformNamesEnd) {
650 if (uniformsIt->m_blockIndex == uniformBlockDescription[i].m_index) {
651 QString uniformName = *uniformNamesIt;
652 if (!m_uniformBlockNames[i].isEmpty()
653 && !uniformName.startsWith(s: m_uniformBlockNames[i]))
654 uniformName = m_uniformBlockNames[i] + QLatin1Char('.') + *uniformNamesIt;
655 activeUniformsInBlock.insert(key: uniformName, value: *uniformsIt);
656 qCDebug(Shaders) << "Active Uniform Block " << uniformName << " in block "
657 << m_uniformBlockNames[i] << " at index "
658 << uniformsIt->m_blockIndex;
659 }
660 ++uniformsIt;
661 ++uniformNamesIt;
662 }
663 m_uniformBlockIndexToShaderUniforms.insert(key: uniformBlockDescription[i].m_index,
664 value: activeUniformsInBlock);
665 }
666}
667
668void RHIShader::initializeShaderStorageBlocks(
669 const std::vector<ShaderStorageBlock> &shaderStorageBlockDescription)
670{
671 m_shaderStorageBlocks = shaderStorageBlockDescription;
672 m_shaderStorageBlockNames.resize(new_size: shaderStorageBlockDescription.size());
673 m_shaderStorageBlockNamesIds.resize(new_size: shaderStorageBlockDescription.size());
674
675 for (size_t i = 0, m = shaderStorageBlockDescription.size(); i < m; ++i) {
676 m_shaderStorageBlockNames[i] = m_shaderStorageBlocks[i].m_name;
677 m_shaderStorageBlockNamesIds[i] = StringToInt::lookupId(str: m_shaderStorageBlockNames[i]);
678 m_shaderStorageBlocks[i].m_nameId = m_shaderStorageBlockNamesIds[i];
679 qCDebug(Shaders) << "Initializing Shader Storage Block {" << m_shaderStorageBlockNames[i]
680 << "}";
681 }
682}
683
684} // Rhi
685
686} // Render
687
688} // Qt3DRender
689
690QT_END_NAMESPACE
691

source code of qt3d/src/plugins/renderers/rhi/renderer/rhishader.cpp