summaryrefslogtreecommitdiffstats
path: root/src/plugins/renderers/rhi/renderer/rhishader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/renderers/rhi/renderer/rhishader.cpp')
-rw-r--r--src/plugins/renderers/rhi/renderer/rhishader.cpp681
1 files changed, 681 insertions, 0 deletions
diff --git a/src/plugins/renderers/rhi/renderer/rhishader.cpp b/src/plugins/renderers/rhi/renderer/rhishader.cpp
new file mode 100644
index 000000000..20da46347
--- /dev/null
+++ b/src/plugins/renderers/rhi/renderer/rhishader.cpp
@@ -0,0 +1,681 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rhishader_p.h"
+#include <QMutexLocker>
+#include <Qt3DRender/private/stringtoint_p.h>
+#include <submissioncontext_p.h>
+#include <logging_p.h>
+#include <QRegularExpression>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace Rhi {
+
+RHIShader::RHIShader() : m_isLoaded(false)
+{
+ m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
+}
+
+QVector<QString> RHIShader::uniformsNames() const
+{
+ return m_uniformsNames;
+}
+
+QVector<QString> RHIShader::attributesNames() const
+{
+ return m_attributesNames;
+}
+
+QVector<QString> RHIShader::uniformBlockNames() const
+{
+ return m_uniformBlockNames;
+}
+
+QVector<QString> RHIShader::storageBlockNames() const
+{
+ return m_shaderStorageBlockNames;
+}
+
+QVector<QString> RHIShader::samplerNames() const
+{
+ return m_samplerNames;
+}
+
+QVector<QString> RHIShader::imagesNames() const
+{
+ return m_imageNames;
+}
+
+QVector<QByteArray> RHIShader::shaderCode() const
+{
+ return m_shaderCode;
+}
+
+namespace {
+static constexpr QRhiVertexInputAttribute::Format
+rhiInputType(QShaderDescription::VariableType type)
+{
+ switch (type) {
+ case QShaderDescription::Vec4:
+ return QRhiVertexInputAttribute::Float4;
+ case QShaderDescription::Vec3:
+ return QRhiVertexInputAttribute::Float3;
+ case QShaderDescription::Vec2:
+ return QRhiVertexInputAttribute::Float2;
+ case QShaderDescription::Float:
+ return QRhiVertexInputAttribute::Float;
+ default:
+ // TODO UNormByte4, UNormByte2, UNormByte
+ RHI_UNIMPLEMENTED;
+ return QRhiVertexInputAttribute::UNormByte;
+ break;
+ }
+}
+
+static constexpr int rhiTypeSize(QShaderDescription::VariableType type)
+{
+ switch (type) {
+ case QShaderDescription::Unknown:
+ return 0;
+
+ case QShaderDescription::Float:
+ return 1;
+ case QShaderDescription::Vec2:
+ return 2;
+ case QShaderDescription::Vec3:
+ return 3;
+ case QShaderDescription::Vec4:
+ return 4;
+ case QShaderDescription::Mat2:
+ return 2 * 2;
+ case QShaderDescription::Mat2x3:
+ return 2 * 3;
+ case QShaderDescription::Mat2x4:
+ return 2 * 4;
+ case QShaderDescription::Mat3:
+ return 3 * 3;
+ case QShaderDescription::Mat3x2:
+ return 3 * 2;
+ case QShaderDescription::Mat3x4:
+ return 3 * 4;
+ case QShaderDescription::Mat4:
+ return 4 * 4;
+ case QShaderDescription::Mat4x2:
+ return 4 * 2;
+ case QShaderDescription::Mat4x3:
+ return 4 * 3;
+
+ case QShaderDescription::Int:
+ return 1;
+ case QShaderDescription::Int2:
+ return 2;
+ case QShaderDescription::Int3:
+ return 3;
+ case QShaderDescription::Int4:
+ return 4;
+
+ case QShaderDescription::Uint:
+ return 1;
+ case QShaderDescription::Uint2:
+ return 2;
+ case QShaderDescription::Uint3:
+ return 3;
+ case QShaderDescription::Uint4:
+ return 4;
+
+ case QShaderDescription::Bool:
+ return 1;
+ case QShaderDescription::Bool2:
+ return 2;
+ case QShaderDescription::Bool3:
+ return 3;
+ case QShaderDescription::Bool4:
+ return 4;
+
+ case QShaderDescription::Double:
+ return 1;
+ case QShaderDescription::Double2:
+ return 2;
+ case QShaderDescription::Double3:
+ return 3;
+ case QShaderDescription::Double4:
+ return 4;
+ case QShaderDescription::DMat2:
+ return 2 * 2;
+ case QShaderDescription::DMat2x3:
+ return 2 * 3;
+ case QShaderDescription::DMat2x4:
+ return 2 * 4;
+ case QShaderDescription::DMat3:
+ return 3 * 3;
+ case QShaderDescription::DMat3x2:
+ return 3 * 2;
+ case QShaderDescription::DMat3x4:
+ return 3 * 4;
+ case QShaderDescription::DMat4:
+ return 4 * 4;
+ case QShaderDescription::DMat4x2:
+ return 4 * 2;
+ case QShaderDescription::DMat4x3:
+ return 4 * 3;
+
+ case QShaderDescription::Sampler1D:
+ return 0;
+ case QShaderDescription::Sampler2D:
+ return 0;
+ case QShaderDescription::Sampler2DMS:
+ return 0;
+ case QShaderDescription::Sampler3D:
+ return 0;
+ case QShaderDescription::SamplerCube:
+ return 0;
+ case QShaderDescription::Sampler1DArray:
+ return 0;
+ case QShaderDescription::Sampler2DArray:
+ return 0;
+ case QShaderDescription::Sampler2DMSArray:
+ return 0;
+ case QShaderDescription::Sampler3DArray:
+ return 0;
+ case QShaderDescription::SamplerCubeArray:
+ return 0;
+ case QShaderDescription::SamplerRect:
+ return 0;
+ case QShaderDescription::SamplerBuffer:
+ return 0;
+
+ case QShaderDescription::Image1D:
+ return 0;
+ case QShaderDescription::Image2D:
+ return 0;
+ case QShaderDescription::Image2DMS:
+ return 0;
+ case QShaderDescription::Image3D:
+ return 0;
+ case QShaderDescription::ImageCube:
+ return 0;
+ case QShaderDescription::Image1DArray:
+ return 0;
+ case QShaderDescription::Image2DArray:
+ return 0;
+ case QShaderDescription::Image2DMSArray:
+ return 0;
+ case QShaderDescription::Image3DArray:
+ return 0;
+ case QShaderDescription::ImageCubeArray:
+ return 0;
+ case QShaderDescription::ImageRect:
+ return 0;
+ case QShaderDescription::ImageBuffer:
+ return 0;
+
+ case QShaderDescription::Struct:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+template<typename T, typename Pred>
+QVector<T> stableRemoveDuplicates(QVector<T> in, Pred predicate)
+{
+ QVector<T> out;
+ for (const auto &element : in) {
+ if (std::none_of(out.begin(), out.end(),
+ [&](T &other) { return predicate(element, other); }))
+ out.push_back(element);
+ }
+ return out;
+}
+
+// Utility function to enumerate an array of dimensions
+// Given dims == [0, 3, 2] and maxs == [4, 4, 4]
+// changes dims into [0, 3, 3]
+// Given dims == [0, 3, 3] and maxs == [4, 4, 4]
+// changes dims into [1, 0, 0]
+bool incrementArray(QVarLengthArray<int> &dims, const QVector<int> &maxs)
+{
+ const int n = dims.size();
+ int i = n;
+ for (; i-- > 0;) {
+ if (dims[i] == maxs[i] - 1) {
+ if (i == 0) {
+ // we're done
+ return false;
+ }
+ continue;
+
+ } else {
+ dims[i]++;
+ for (int j = i + 1; j < n; j++) {
+ dims[j] = 0;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+// Call a function with a string such as [0][3][2]
+// for all valable array values, given an array of dimension sizes.
+// Dimensions must all be >= 1
+template<typename F>
+void forEachArrayAccessor(const QVector<int> &maxs, F f)
+{
+ if (std::any_of(maxs.begin(), maxs.end(), [](int v) { return v <= 0; }))
+ return;
+
+ QVarLengthArray<int> dims;
+ dims.resize(maxs.size());
+
+ // QVarLengthArray does not initialize ints
+ std::fill(dims.begin(), dims.end(), 0);
+
+ QString str;
+
+ do {
+ str.resize(0);
+ for (int k : dims) {
+ str += QStringLiteral("[%1]").arg(k);
+ }
+ f(str);
+ } while (incrementArray(dims, maxs));
+}
+}
+
+void RHIShader::recordAllUniforms(const QShaderDescription::BlockVariable &member,
+ QString parentName)
+{
+ const bool isStruct = !member.structMembers.empty();
+ const bool isArray = !member.arrayDims.empty();
+
+ // "foo.bar"
+ const QString fullMemberName = parentName + member.name;
+ m_unqualifiedUniformNames << fullMemberName;
+
+ if (isStruct && !isArray) {
+ m_structNames << fullMemberName;
+ m_structNamesIds << StringToInt::lookupId(fullMemberName);
+
+ for (const QShaderDescription::BlockVariable& bv : member.structMembers) {
+ // recordAllUniforms("baz", "foo.bar.")
+ recordAllUniforms(bv, fullMemberName + QLatin1Char('.'));
+ }
+ } else if (!isStruct && isArray) {
+ // We iterate through all the [l][n][m] by building [0][0][0] and incrementing
+ forEachArrayAccessor(member.arrayDims, [&](const QString &str) {
+ // "foo.bar[1][2]"
+ m_unqualifiedUniformNames << (fullMemberName + str);
+ // Question : does it make sense to also record foo[0], foo[0][0], etc...
+ // if there are e.g. 3 dimensions ?
+ });
+ }
+ else if (isStruct && isArray) {
+ // Record the struct names
+ forEachArrayAccessor(member.arrayDims, [&] (const QString& str) {
+ m_structNames << (fullMemberName + str);
+ m_structNamesIds << StringToInt::lookupId(m_structNames.back());
+ });
+
+ // Record the struct members
+ for (const QShaderDescription::BlockVariable& bv : member.structMembers) {
+ forEachArrayAccessor(member.arrayDims, [&] (const QString& str) {
+ //recordAllUniforms("baz", "foo.bar[1][2].")
+ recordAllUniforms(bv, fullMemberName + str + QLatin1Char('.'));
+ });
+ }
+ }
+}
+
+void RHIShader::introspect()
+{
+ const thread_local QRegularExpression generatedUBOName { "_[0-9]+" };
+ QVector<QShaderDescription::UniformBlock> rhiUBO;
+ QVector<QShaderDescription::StorageBlock> rhiSSBO;
+
+ QVector<ShaderUniformBlock> uniformBlocks;
+ QVector<ShaderStorageBlock> storageBlocks;
+ QVector<ShaderAttribute> attributes;
+ QVector<ShaderAttribute> samplers;
+ QVector<ShaderAttribute> images;
+
+ // Introspect shader vertex input
+ if (m_stages[QShader::VertexStage].isValid()) {
+ const QShaderDescription &vtx = m_stages[QShader::VertexStage].description();
+
+ for (const QShaderDescription::InOutVariable &input : vtx.inputVariables()) {
+ attributes.push_back(ShaderAttribute { input.name, StringToInt::lookupId(input.name),
+ input.type, rhiTypeSize(input.type),
+ input.location });
+ }
+
+ rhiUBO += vtx.uniformBlocks();
+ rhiSSBO += vtx.storageBlocks();
+ }
+
+ // Introspect shader uniforms
+
+ if (m_stages[QShader::FragmentStage].isValid()) {
+ const QShaderDescription &frag = m_stages[QShader::FragmentStage].description();
+ for (const QShaderDescription::InOutVariable &sampler : frag.combinedImageSamplers()) {
+ samplers.push_back(ShaderAttribute { sampler.name, StringToInt::lookupId(sampler.name),
+ sampler.type, rhiTypeSize(sampler.type),
+ sampler.binding });
+ }
+ for (const QShaderDescription::InOutVariable &image : frag.storageImages()) {
+ images.push_back(ShaderAttribute { image.name, StringToInt::lookupId(image.name),
+ image.type, rhiTypeSize(image.type),
+ image.binding });
+ }
+
+ rhiUBO += frag.uniformBlocks();
+ rhiSSBO += frag.storageBlocks();
+ }
+
+ rhiUBO = stableRemoveDuplicates(rhiUBO,
+ [](const QShaderDescription::UniformBlock &lhs,
+ const QShaderDescription::UniformBlock &rhs) {
+ return lhs.blockName == rhs.blockName;
+ });
+ rhiSSBO = stableRemoveDuplicates(rhiSSBO,
+ [](const QShaderDescription::StorageBlock &lhs,
+ const QShaderDescription::StorageBlock &rhs) {
+ return lhs.blockName == rhs.blockName;
+ });
+
+ for (const QShaderDescription::UniformBlock &ubo : rhiUBO) {
+ uniformBlocks.push_back(ShaderUniformBlock { ubo.blockName,
+ StringToInt::lookupId(ubo.blockName), -1,
+ ubo.binding, ubo.members.size(), ubo.size });
+ const bool addUnqualifiedUniforms = ubo.structName.contains(generatedUBOName);
+
+ // Parse Uniform Block members so that we can later on map a Parameter name to an actual
+ // member
+ const QVector<QShaderDescription::BlockVariable> members = ubo.members;
+
+ QVector<int> namesIds;
+ namesIds.reserve(members.size());
+
+ for (const QShaderDescription::BlockVariable &member : members) {
+ namesIds << StringToInt::lookupId(member.name);
+ if (addUnqualifiedUniforms) {
+ recordAllUniforms(member, QStringLiteral(""));
+ }
+ }
+ m_uniformsNamesIds += namesIds;
+ m_uboMembers.push_back({ uniformBlocks.last(), members });
+ }
+
+ for (const QShaderDescription::StorageBlock &ssbo : rhiSSBO) {
+ storageBlocks.push_back(ShaderStorageBlock { ssbo.blockName, -1, -1, ssbo.binding, 0, 0 });
+ }
+
+ initializeAttributes(attributes);
+ initializeUniformBlocks(uniformBlocks);
+ initializeShaderStorageBlocks(storageBlocks);
+ initializeSamplers(samplers);
+ initializeImages(images);
+}
+
+QHash<QString, ShaderUniform> RHIShader::activeUniformsForUniformBlock(int blockIndex) const
+{
+ return m_uniformBlockIndexToShaderUniforms.value(blockIndex);
+}
+
+ShaderUniformBlock RHIShader::uniformBlockForBlockIndex(int blockIndex) const noexcept
+{
+ for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
+ if (m_uniformBlocks[i].m_index == blockIndex) {
+ return m_uniformBlocks[i];
+ }
+ }
+ return ShaderUniformBlock();
+}
+
+ShaderUniformBlock RHIShader::uniformBlockForBlockNameId(int blockNameId) const noexcept
+{
+ for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
+ if (m_uniformBlocks[i].m_nameId == blockNameId) {
+ return m_uniformBlocks[i];
+ }
+ }
+ return ShaderUniformBlock();
+}
+
+ShaderUniformBlock RHIShader::uniformBlockForBlockName(const QString &blockName) const noexcept
+{
+ for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
+ if (m_uniformBlocks[i].m_name == blockName) {
+ return m_uniformBlocks[i];
+ }
+ }
+ return ShaderUniformBlock();
+}
+
+ShaderStorageBlock RHIShader::storageBlockForBlockIndex(int blockIndex) const noexcept
+{
+ for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
+ if (m_shaderStorageBlocks[i].m_index == blockIndex)
+ return m_shaderStorageBlocks[i];
+ }
+ return ShaderStorageBlock();
+}
+
+ShaderStorageBlock RHIShader::storageBlockForBlockNameId(int blockNameId) const noexcept
+{
+ for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
+ if (m_shaderStorageBlocks[i].m_nameId == blockNameId)
+ return m_shaderStorageBlocks[i];
+ }
+ return ShaderStorageBlock();
+}
+
+ShaderStorageBlock RHIShader::storageBlockForBlockName(const QString &blockName) const noexcept
+{
+ for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
+ if (m_shaderStorageBlocks[i].m_name == blockName)
+ return m_shaderStorageBlocks[i];
+ }
+ return ShaderStorageBlock();
+}
+
+RHIShader::ParameterKind RHIShader::categorizeVariable(int nameId) const noexcept
+{
+ if (m_uniformsNamesIds.contains(nameId))
+ return ParameterKind::Uniform;
+ else if (m_uniformBlockNamesIds.contains(nameId))
+ return ParameterKind::UBO;
+ else if (m_shaderStorageBlockNamesIds.contains(nameId))
+ return ParameterKind::SSBO;
+ else if (m_structNamesIds.contains(nameId))
+ return ParameterKind::Struct;
+ return ParameterKind::Uniform;
+}
+
+bool RHIShader::hasUniform(int nameId) const noexcept
+{
+ return m_uniformsNamesIds.contains(nameId);
+}
+
+bool RHIShader::hasActiveVariables() const noexcept
+{
+ return !m_attributeNamesIds.empty() || !m_uniformsNamesIds.empty()
+ || !m_uniformBlockNamesIds.empty() || !m_shaderStorageBlockNamesIds.empty();
+}
+
+void RHIShader::prepareUniforms(ShaderParameterPack &pack)
+{
+ const PackUniformHash &values = pack.uniforms();
+
+ auto it = values.keys.cbegin();
+ const auto end = values.keys.cend();
+
+ while (it != end) {
+ // Find if there's a uniform with the same name id
+ for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
+ if (uniform.m_nameId == *it) {
+ pack.setSubmissionUniform(uniform);
+ break;
+ }
+ }
+ ++it;
+ }
+}
+
+void RHIShader::setFragOutputs(const QHash<QString, int> &fragOutputs)
+{
+ {
+ QMutexLocker lock(&m_mutex);
+ m_fragOutputs = fragOutputs;
+ }
+ // updateDNA();
+}
+
+const QHash<QString, int> RHIShader::fragOutputs() const
+{
+ QMutexLocker lock(&m_mutex);
+ return m_fragOutputs;
+}
+
+void RHIShader::initializeAttributes(const QVector<ShaderAttribute> &attributesDescription)
+{
+ m_attributes = attributesDescription;
+ m_attributesNames.resize(attributesDescription.size());
+ m_attributeNamesIds.resize(attributesDescription.size());
+ for (int i = 0, m = attributesDescription.size(); i < m; i++) {
+ m_attributesNames[i] = attributesDescription[i].m_name;
+ m_attributes[i].m_nameId = StringToInt::lookupId(m_attributesNames[i]);
+ m_attributeNamesIds[i] = m_attributes[i].m_nameId;
+ qCDebug(Shaders) << "Active Attribute " << attributesDescription[i].m_name;
+ }
+}
+
+void RHIShader::initializeSamplers(const QVector<ShaderAttribute> &samplersDescription)
+{
+ m_samplers = samplersDescription;
+ m_samplerNames.resize(samplersDescription.size());
+ m_samplerIds.resize(samplersDescription.size());
+ for (int i = 0, m = samplersDescription.size(); i < m; i++) {
+ m_samplerNames[i] = samplersDescription[i].m_name;
+ m_samplers[i].m_nameId = StringToInt::lookupId(m_samplerNames[i]);
+ m_samplerIds[i] = m_samplers[i].m_nameId;
+ qCDebug(Shaders) << "Active sampler " << samplersDescription[i].m_name;
+ }
+}
+
+void RHIShader::initializeImages(const QVector<ShaderAttribute> &imagesDescription)
+{
+ m_images = imagesDescription;
+ m_imageNames.resize(imagesDescription.size());
+ m_imageIds.resize(imagesDescription.size());
+ for (int i = 0, m = imagesDescription.size(); i < m; i++) {
+ m_imageNames[i] = imagesDescription[i].m_name;
+ m_images[i].m_nameId = StringToInt::lookupId(m_imageNames[i]);
+ m_imageIds[i] = m_images[i].m_nameId;
+ qCDebug(Shaders) << "Active image " << imagesDescription[i].m_name;
+ }
+}
+
+void RHIShader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformBlockDescription)
+{
+ m_uniformBlocks = uniformBlockDescription;
+ m_uniformBlockNames.resize(uniformBlockDescription.size());
+ m_uniformBlockNamesIds.resize(uniformBlockDescription.size());
+ for (int i = 0, m = uniformBlockDescription.size(); i < m; ++i) {
+ m_uniformBlockNames[i] = m_uniformBlocks[i].m_name;
+ m_uniformBlockNamesIds[i] = StringToInt::lookupId(m_uniformBlockNames[i]);
+ m_uniformBlocks[i].m_nameId = m_uniformBlockNamesIds[i];
+ qCDebug(Shaders) << "Initializing Uniform Block {" << m_uniformBlockNames[i] << "}";
+
+ // Find all active uniforms for the shader block
+ QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.cbegin();
+ const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.cend();
+
+ QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.cbegin();
+ const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.cend();
+
+ QHash<QString, ShaderUniform> activeUniformsInBlock;
+
+ while (uniformsIt != uniformsEnd && uniformNamesIt != uniformNamesEnd) {
+ if (uniformsIt->m_blockIndex == uniformBlockDescription[i].m_index) {
+ QString uniformName = *uniformNamesIt;
+ if (!m_uniformBlockNames[i].isEmpty()
+ && !uniformName.startsWith(m_uniformBlockNames[i]))
+ uniformName = m_uniformBlockNames[i] + QLatin1Char('.') + *uniformNamesIt;
+ activeUniformsInBlock.insert(uniformName, *uniformsIt);
+ qCDebug(Shaders) << "Active Uniform Block " << uniformName << " in block "
+ << m_uniformBlockNames[i] << " at index "
+ << uniformsIt->m_blockIndex;
+ }
+ ++uniformsIt;
+ ++uniformNamesIt;
+ }
+ m_uniformBlockIndexToShaderUniforms.insert(uniformBlockDescription[i].m_index,
+ activeUniformsInBlock);
+ }
+}
+
+void RHIShader::initializeShaderStorageBlocks(
+ const QVector<ShaderStorageBlock> &shaderStorageBlockDescription)
+{
+ m_shaderStorageBlocks = shaderStorageBlockDescription;
+ m_shaderStorageBlockNames.resize(shaderStorageBlockDescription.size());
+ m_shaderStorageBlockNamesIds.resize(shaderStorageBlockDescription.size());
+
+ for (int i = 0, m = shaderStorageBlockDescription.size(); i < m; ++i) {
+ m_shaderStorageBlockNames[i] = m_shaderStorageBlocks[i].m_name;
+ m_shaderStorageBlockNamesIds[i] = StringToInt::lookupId(m_shaderStorageBlockNames[i]);
+ m_shaderStorageBlocks[i].m_nameId = m_shaderStorageBlockNamesIds[i];
+ qCDebug(Shaders) << "Initializing Shader Storage Block {" << m_shaderStorageBlockNames[i]
+ << "}";
+ }
+}
+
+} // Rhi
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE