From 0f0392b8d5202ccac56352e3930b4050a0d7e10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Tue, 14 Apr 2020 15:23:21 +0200 Subject: rhi: Rework uniform processing Change-Id: I1dc305b727b148773f1d7dafa3ba8e2b74366aec Reviewed-by: Paul Lemire --- .../renderers/rhi/jobs/renderviewjobutils.cpp | 11 +- .../renderers/rhi/jobs/renderviewjobutils_p.h | 6 +- src/plugins/renderers/rhi/renderer/renderview.cpp | 142 +++++--------- src/plugins/renderers/rhi/renderer/renderview_p.h | 44 +---- src/plugins/renderers/rhi/renderer/rhishader.cpp | 213 +++++++++++++++------ src/plugins/renderers/rhi/renderer/rhishader_p.h | 33 +++- src/render/materialsystem/shaderdata.cpp | 2 +- src/render/materialsystem/shaderdata_p.h | 2 +- 8 files changed, 246 insertions(+), 207 deletions(-) (limited to 'src') diff --git a/src/plugins/renderers/rhi/jobs/renderviewjobutils.cpp b/src/plugins/renderers/rhi/jobs/renderviewjobutils.cpp index 730a0060a..8918225cd 100644 --- a/src/plugins/renderers/rhi/jobs/renderviewjobutils.cpp +++ b/src/plugins/renderers/rhi/jobs/renderviewjobutils.cpp @@ -466,7 +466,11 @@ UniformBlockValueBuilder::~UniformBlockValueBuilder() { } -void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *currentShaderData, const QString &blockName, const QString &qmlPropertyName, const QVariant &value) +void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper( + const ShaderData *currentShaderData, + const QString &blockName, + const QString &qmlPropertyName, + const QVariant &value) { // In the end, values are either scalar or a scalar array // Composed elements (structs, structs array) are simplified into simple scalars @@ -527,7 +531,10 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * } } -void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) +void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper( + const ShaderData *rShaderData, + const QString &blockName, + const QString &qmlPropertyName) { const QHash &properties = rShaderData->properties(); auto it = properties.begin(); diff --git a/src/plugins/renderers/rhi/jobs/renderviewjobutils_p.h b/src/plugins/renderers/rhi/jobs/renderviewjobutils_p.h index 2fb441ef9..da4cf5ffa 100644 --- a/src/plugins/renderers/rhi/jobs/renderviewjobutils_p.h +++ b/src/plugins/renderers/rhi/jobs/renderviewjobutils_p.h @@ -166,16 +166,16 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder QT3D_ALIGNED_MALLOC_AND_FREE() - void buildActiveUniformNameValueMapHelper(ShaderData *currentShaderData, + void buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData, const QString &blockName, const QString &qmlPropertyName, const QVariant &value); - void buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, + void buildActiveUniformNameValueMapStructHelper(const ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName = QString()); bool updatedPropertiesOnly; - QHash uniforms; + QSet uniforms; UniformBlockValueBuilderHash activeUniformNamesToValue; ShaderDataManager *shaderDataManager; TextureManager *textureManager; diff --git a/src/plugins/renderers/rhi/renderer/renderview.cpp b/src/plugins/renderers/rhi/renderer/renderview.cpp index 70020093a..c08be80eb 100644 --- a/src/plugins/renderers/rhi/renderer/renderview.cpp +++ b/src/plugins/renderers/rhi/renderer/renderview.cpp @@ -111,41 +111,6 @@ std::atomic_bool wasInitialized{}; } // anonymous namespace -RenderView::StandardUniformsNameToTypeHash RenderView::ms_standardUniformSetters; - - -RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniformSetters() -{ - RenderView::StandardUniformsNameToTypeHash setters; - - setters.insert(Shader::modelMatrixNameId, ModelMatrix); - setters.insert(Shader::viewMatrixNameId, ViewMatrix); - setters.insert(Shader::projectionMatrixNameId, ProjectionMatrix); - setters.insert(Shader::modelViewMatrixNameId, ModelViewMatrix); - setters.insert(Shader::viewProjectionMatrixNameId, ViewProjectionMatrix); - setters.insert(Shader::modelViewProjectionNameId, ModelViewProjectionMatrix); - setters.insert(Shader::mvpNameId, ModelViewProjectionMatrix); - setters.insert(Shader::inverseModelMatrixNameId, InverseModelMatrix); - setters.insert(Shader::inverseViewMatrixNameId, InverseViewMatrix); - setters.insert(Shader::inverseProjectionMatrixNameId, InverseProjectionMatrix); - setters.insert(Shader::inverseModelViewNameId, InverseModelViewMatrix); - setters.insert(Shader::inverseViewProjectionMatrixNameId, InverseViewProjectionMatrix); - setters.insert(Shader::inverseModelViewProjectionNameId, InverseModelViewProjectionMatrix); - setters.insert(Shader::modelNormalMatrixNameId, ModelNormalMatrix); - setters.insert(Shader::modelViewNormalNameId, ModelViewNormalMatrix); - setters.insert(Shader::viewportMatrixNameId, ViewportMatrix); - setters.insert(Shader::inverseViewportMatrixNameId, InverseViewportMatrix); - setters.insert(Shader::textureTransformMatrixNameId, TextureTransformMatrix); - setters.insert(Shader::aspectRatioNameId, AspectRatio); - setters.insert(Shader::exposureNameId, Exposure); - setters.insert(Shader::gammaNameId, Gamma); - setters.insert(Shader::timeNameId, Time); - setters.insert(Shader::eyePositionNameId, EyePosition); - setters.insert(Shader::skinningPaletteNameId, SkinningPalette); - - return setters; -} - // TODO: Move this somewhere global where GraphicsContext::setViewport() can use it too static QRectF resolveViewport(const QRectF &fractionalViewport, const QSize &surfaceSize) { @@ -157,8 +122,6 @@ static QRectF resolveViewport(const QRectF &fractionalViewport, const QSize &sur static Matrix4x4 getProjectionMatrix(const CameraLens *lens, bool yIsUp) { - if (!lens) - qWarning() << "[Qt3D Renderer] No Camera Lens found. Add a CameraSelector to your Frame Graph or make sure that no entities will be rendered."; if (lens) { if (yIsUp) @@ -177,6 +140,7 @@ static Matrix4x4 getProjectionMatrix(const CameraLens *lens, bool yIsUp) } else { + qWarning() << "[Qt3D Renderer] No Camera Lens found. Add a CameraSelector to your Frame Graph or make sure that no entities will be rendered."; return Matrix4x4(); } } @@ -958,7 +922,7 @@ void RenderView::setUniformValue(ShaderParameterPack &uniformPack, int nameId, c } void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, - RHIShader *shader, + const RHIShader *shader, const ShaderUniformBlock &block, const UniformValue &value) const { @@ -979,7 +943,7 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, } void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, - RHIShader *shader, + const RHIShader *shader, const ShaderStorageBlock &block, const UniformValue &value) const { @@ -997,7 +961,11 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, } } -void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, RHIShader *shader, ShaderData *shaderData, const QString &structName) const +void RenderView::setDefaultUniformBlockShaderDataValue( + ShaderParameterPack &uniformPack, + const RHIShader *shader, + const ShaderData *shaderData, + const QString &structName) const { UniformBlockValueBuilder *builder = m_localData.localData(); builder->activeUniformNamesToValue.clear(); @@ -1007,7 +975,7 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif // Force to update the whole block builder->updatedPropertiesOnly = false; // Retrieve names and description of each active uniforms in the uniform block - builder->uniforms = shader->activeUniformsForUniformBlock(-1); + builder->uniforms = shader->unqualifiedUniformNames(); // Build name-value map for the block builder->buildActiveUniformNameValueMapStructHelper(shaderData, structName); // Set uniform values for each entrie of the block name-value map @@ -1021,6 +989,39 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif } } +void RenderView::applyParameter( + const Parameter *param, + RenderCommand *command, + const RHIShader *shader) const noexcept +{ + const int nameId = param->nameId(); + const UniformValue &uniformValue = param->uniformValue(); + switch (shader->categorizeVariable(nameId)) + { + case RHIShader::Uniform: { + setUniformValue(command->m_parameterPack, nameId, uniformValue); + break; + } + case RHIShader::UBO: { + setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(nameId), uniformValue); + break; + } + case RHIShader::SSBO: { + setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(nameId), uniformValue); + break; + } + case RHIShader::Struct: { + ShaderData *shaderData = nullptr; + if (uniformValue.valueType() == UniformValue::NodeId && + (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData())) != nullptr) { + // Try to check if we have a struct or array matching a QShaderData parameter + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(nameId)); + } + break; + } + } +} + void RenderView::setShaderAndUniforms(RenderCommand *command, ParameterInfoList ¶meters, Entity *entity, @@ -1043,10 +1044,6 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name // equals to the parameter name - const QVector uniformNamesIds = shader->uniformsNamesIds(); - const QVector uniformBlockNamesIds = shader->uniformBlockNamesIds(); - const QVector shaderStorageBlockNamesIds = shader->storageBlockNamesIds(); - const QVector attributeNamesIds = shader->attributeNamesIds(); // Set fragData Name and index // Later on we might want to relink the shader if attachments have changed @@ -1063,12 +1060,13 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, shader->setFragOutputs(fragOutputs); } - if (!uniformNamesIds.isEmpty() || - !attributeNamesIds.isEmpty() || - !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) { + if (shader->hasActiveVariables()) { + + // Unlike the GL engine, the standard uniforms are set a bit before this function, + // in RenderView::updateRenderCommand // Set default attributes - command->m_activeAttributes = attributeNamesIds; + command->m_activeAttributes = shader->attributeNamesIds(); // At this point we know whether the command is a valid draw command or not // We still need to process the uniforms as the command could be a compute command @@ -1084,27 +1082,12 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, const ParameterInfoList::const_iterator parametersEnd = parameters.cend(); while (it != parametersEnd) { - Parameter *param = m_manager->data(it->handle); - const UniformValue &uniformValue = param->uniformValue(); - if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block - setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue); - } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO - setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue); - } else { // Parameter is a struct - setUniformValue(command->m_parameterPack, it->nameId, uniformValue); -// ShaderData *shaderData = nullptr; -// if (uniformValue.valueType() == UniformValue::NodeId && -// (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData())) != nullptr) { -// // Try to check if we have a struct or array matching a QShaderData parameter -// setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId)); -// } - // Otherwise: param unused by current shader - } + const Parameter *param = m_manager->data(it->handle); + applyParameter(param, command, shader); ++it; } // Lights - int lightIdx = 0; for (const LightSource &lightSource : activeLightSources) { if (lightIdx == MAX_LIGHTS) @@ -1142,7 +1125,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, } } - if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID)) + if (shader->hasUniform(LIGHT_COUNT_NAME_ID)) setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx))); // If no active light sources and no environment light, add a default light @@ -1161,7 +1144,6 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, static const int specularId = StringToInt::lookupId(QLatin1String("envLight_specular")); ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData()); if (shaderData) { - //setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight")); envLightCount = 1; // ("specularSize", "irradiance", "irradianceSize", "specular") @@ -1172,30 +1154,6 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, setUniformValue(command->m_parameterPack, specularId, spec); } } - //if (environmentLight && environmentLight->isEnabled()) { - // ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData()); - // if (shaderData) { - // setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight")); - // envLightCount = 1; - // } - //} else { - // // with some drivers, samplers (like the envbox sampler) need to be bound even though - // // they may not be actually used, otherwise draw calls can fail - // static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight_irradiance")); - // static const int specularId = StringToInt::lookupId(QLatin1String("envLight_specular")); - // - // // for (const auto& sampler : shader->samplers()) - // // { - // // if (sampler.m_nameId == irradianceId) - // // { - // // setUniformValue(command->m_parameterPack, irradianceId, sampler.m_location); - // // } - // // else if (sampler.m_nameId == specularId) - // // { - // // setUniformValue(command->m_parameterPack, specularId, sampler.m_location); - // // } - // // } - //} setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount); } } diff --git a/src/plugins/renderers/rhi/renderer/renderview_p.h b/src/plugins/renderers/rhi/renderer/renderview_p.h index cceefe5e4..b42596498 100644 --- a/src/plugins/renderers/rhi/renderer/renderview_p.h +++ b/src/plugins/renderers/rhi/renderer/renderview_p.h @@ -346,54 +346,20 @@ private: MaterialParameterGathererData m_parameters; - enum StandardUniform - { - ModelMatrix, - ViewMatrix, - ProjectionMatrix, - ModelViewMatrix, - ViewProjectionMatrix, - ModelViewProjectionMatrix, - InverseModelMatrix, - InverseViewMatrix, - InverseProjectionMatrix, - InverseModelViewMatrix, - InverseViewProjectionMatrix, - InverseModelViewProjectionMatrix, - ModelNormalMatrix, - ModelViewNormalMatrix, - ViewportMatrix, - InverseViewportMatrix, - TextureTransformMatrix, - AspectRatio, - Time, - Exposure, - Gamma, - EyePosition, - SkinningPalette - }; - - typedef QHash StandardUniformsNameToTypeHash; - static StandardUniformsNameToTypeHash ms_standardUniformSetters; - static StandardUniformsNameToTypeHash initializeStandardUniformSetters(); - - UniformValue standardUniformValue(StandardUniform standardUniformType, - Entity *entity, - const Matrix4x4 &model) const; - void setUniformValue(ShaderParameterPack &uniformPack, int nameId, const UniformValue &value) const; void setUniformBlockValue(ShaderParameterPack &uniformPack, - RHIShader *shader, + const RHIShader *shader, const ShaderUniformBlock &block, const UniformValue &value) const; void setShaderStorageValue(ShaderParameterPack &uniformPack, - RHIShader *shader, + const RHIShader *shader, const ShaderStorageBlock &block, const UniformValue &value) const; void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, - RHIShader *shader, - ShaderData *shaderData, + const RHIShader *shader, + const ShaderData *shaderData, const QString &structName) const; + void applyParameter(const Parameter* param, RenderCommand* command, const RHIShader* shader) const noexcept; }; } // namespace Rhi diff --git a/src/plugins/renderers/rhi/renderer/rhishader.cpp b/src/plugins/renderers/rhi/renderer/rhishader.cpp index fe8fb6961..ffb74145a 100644 --- a/src/plugins/renderers/rhi/renderer/rhishader.cpp +++ b/src/plugins/renderers/rhi/renderer/rhishader.cpp @@ -42,6 +42,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -92,6 +93,8 @@ QVector RHIShader::shaderCode() const return m_shaderCode; } +namespace +{ static constexpr QRhiVertexInputAttribute::Format rhiInputType(QShaderDescription::VariableType type) { switch (type) @@ -199,8 +202,120 @@ QVector stableRemoveDuplicates(QVector in, Pred predicate) } 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& dims, const QVector& 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 +void forEachArrayAccessor(const QVector& maxs, F f) +{ + if (std::any_of(maxs.begin(), maxs.end(), [] (int v) { return v <= 0; })) + return; + + QVarLengthArray 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 rhiUBO; QVector rhiSSBO; @@ -246,6 +361,7 @@ void RHIShader::introspect() 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 members = ubo.members; @@ -254,8 +370,11 @@ void RHIShader::introspect() namesIds.reserve(members.size()); for (const QShaderDescription::BlockVariable& member : members) { - qDebug() << member.name << member.offset << member.size << member.structMembers.size() << member.type; namesIds << StringToInt::lookupId(member.name); + if (addUnqualifiedUniforms) + { + recordAllUniforms(member, QStringLiteral("")); + } } m_uniformsNamesIds += namesIds; m_uboMembers.push_back({uniformBlocks.last(), members}); @@ -277,7 +396,7 @@ QHash RHIShader::activeUniformsForUniformBlock(int block return m_uniformBlockIndexToShaderUniforms.value(blockIndex); } -ShaderUniformBlock RHIShader::uniformBlockForBlockIndex(int 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) { @@ -287,7 +406,7 @@ ShaderUniformBlock RHIShader::uniformBlockForBlockIndex(int blockIndex) return ShaderUniformBlock(); } -ShaderUniformBlock RHIShader::uniformBlockForBlockNameId(int blockNameId) +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) { @@ -297,7 +416,7 @@ ShaderUniformBlock RHIShader::uniformBlockForBlockNameId(int blockNameId) return ShaderUniformBlock(); } -ShaderUniformBlock RHIShader::uniformBlockForBlockName(const QString &blockName) +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) { @@ -307,7 +426,7 @@ ShaderUniformBlock RHIShader::uniformBlockForBlockName(const QString &blockName) return ShaderUniformBlock(); } -ShaderStorageBlock RHIShader::storageBlockForBlockIndex(int blockIndex) +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) @@ -316,7 +435,7 @@ ShaderStorageBlock RHIShader::storageBlockForBlockIndex(int blockIndex) return ShaderStorageBlock(); } -ShaderStorageBlock RHIShader::storageBlockForBlockNameId(int blockNameId) +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) @@ -325,7 +444,7 @@ ShaderStorageBlock RHIShader::storageBlockForBlockNameId(int blockNameId) return ShaderStorageBlock(); } -ShaderStorageBlock RHIShader::storageBlockForBlockName(const QString &blockName) +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) @@ -334,6 +453,32 @@ ShaderStorageBlock RHIShader::storageBlockForBlockName(const QString &blockName) 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(); @@ -368,60 +513,6 @@ const QHash RHIShader::fragOutputs() const return m_fragOutputs; } -void RHIShader::initializeUniforms(const QVector &uniformsDescription) -{ - m_uniforms = uniformsDescription; - m_uniformsNames.resize(uniformsDescription.size()); - m_uniformsNamesIds.reserve(uniformsDescription.size()); - m_standardUniformNamesIds.reserve(5); - QHash activeUniformsInDefaultBlock; - - static const QVector standardUniformNameIds = { - Shader::modelMatrixNameId, - Shader::viewMatrixNameId, - Shader::projectionMatrixNameId, - Shader::modelViewMatrixNameId, - Shader::viewProjectionMatrixNameId, - Shader::modelViewProjectionNameId, - Shader::mvpNameId, - Shader::inverseModelMatrixNameId, - Shader::inverseViewMatrixNameId, - Shader::inverseProjectionMatrixNameId, - Shader::inverseModelViewNameId, - Shader::inverseViewProjectionMatrixNameId, - Shader::inverseModelViewProjectionNameId, - Shader::modelNormalMatrixNameId, - Shader::modelViewNormalNameId, - Shader::viewportMatrixNameId, - Shader::inverseViewportMatrixNameId, - Shader::textureTransformMatrixNameId, - Shader::aspectRatioNameId, - Shader::exposureNameId, - Shader::gammaNameId, - Shader::timeNameId, - Shader::eyePositionNameId, - Shader::skinningPaletteNameId, - }; - - for (int i = 0, m = uniformsDescription.size(); i < m; i++) { - m_uniformsNames[i] = m_uniforms[i].m_name; - const int nameId = StringToInt::lookupId(m_uniformsNames[i]); - m_uniforms[i].m_nameId = nameId; - - // Is the uniform a Qt3D "Standard" uniform or a user defined one? - if (standardUniformNameIds.contains(nameId)) - m_standardUniformNamesIds.push_back(nameId); - else - m_uniformsNamesIds.push_back(nameId); - - if (uniformsDescription[i].m_blockIndex == -1) { // Uniform is in default block - qCDebug(Shaders) << "Active Uniform in Default Block " << uniformsDescription[i].m_name << uniformsDescription[i].m_blockIndex; - activeUniformsInDefaultBlock.insert(uniformsDescription[i].m_name, uniformsDescription[i]); - } - } - m_uniformBlockIndexToShaderUniforms.insert(-1, activeUniformsInDefaultBlock); -} - void RHIShader::initializeAttributes(const QVector &attributesDescription) { m_attributes = attributesDescription; diff --git a/src/plugins/renderers/rhi/renderer/rhishader_p.h b/src/plugins/renderers/rhi/renderer/rhishader_p.h index 8d23a6f28..baed31fc2 100644 --- a/src/plugins/renderers/rhi/renderer/rhishader_p.h +++ b/src/plugins/renderers/rhi/renderer/rhishader_p.h @@ -109,13 +109,24 @@ public: QHash activeUniformsForUniformBlock(int blockIndex) const; - ShaderUniformBlock uniformBlockForBlockIndex(int blockNameId); - ShaderUniformBlock uniformBlockForBlockNameId(int blockIndex); - ShaderUniformBlock uniformBlockForBlockName(const QString &blockName); + ShaderUniformBlock uniformBlockForBlockIndex(int blockNameId) const noexcept; + ShaderUniformBlock uniformBlockForBlockNameId(int blockIndex) const noexcept; + ShaderUniformBlock uniformBlockForBlockName(const QString &blockName) const noexcept; + + ShaderStorageBlock storageBlockForBlockIndex(int blockIndex) const noexcept; + ShaderStorageBlock storageBlockForBlockNameId(int blockNameId) const noexcept; + ShaderStorageBlock storageBlockForBlockName(const QString &blockName) const noexcept; + + enum ParameterKind { + Uniform, + UBO, + SSBO, + Struct + }; + ParameterKind categorizeVariable(int nameId) const noexcept; - ShaderStorageBlock storageBlockForBlockIndex(int blockIndex); - ShaderStorageBlock storageBlockForBlockNameId(int blockNameId); - ShaderStorageBlock storageBlockForBlockName(const QString &blockName); + bool hasUniform(int nameId) const noexcept; + bool hasActiveVariables() const noexcept; void setShaderCode(const QVector shaderCode) { m_shaderCode = shaderCode; } QVector shaderCode() const; @@ -123,6 +134,8 @@ public: const QShader& shaderStage(QShader::Stage stage) const noexcept { return m_stages[stage]; } QVector uboMembers() const { return m_uboMembers; } + const QSet& unqualifiedUniformNames() const noexcept { return m_unqualifiedUniformNames; } + void introspect(); private: bool m_isLoaded; @@ -141,6 +154,7 @@ private: QVector m_uniformBlockNamesIds; QVector m_uniformBlocks; QHash > m_uniformBlockIndexToShaderUniforms; + QSet m_unqualifiedUniformNames; QVector m_shaderStorageBlockNames; QVector m_shaderStorageBlockNamesIds; @@ -154,20 +168,23 @@ private: QVector m_imageIds; QVector m_images; + QVector m_structNames; + QVector m_structNamesIds; + QHash m_fragOutputs; QVector m_shaderCode; // Private so that only SubmissionContext can call it friend class SubmissionContext; - void initializeUniforms(const QVector &uniformsDescription); void initializeAttributes(const QVector &attributesDescription); void initializeUniformBlocks(const QVector &uniformBlockDescription); + void initializeShaderStorageBlocks(const QVector &shaderStorageBlockDescription); void initializeSamplers(const QVector &samplerDescription); void initializeImages(const QVector &imageDescription); + void recordAllUniforms(const QShaderDescription::BlockVariable &ubo, QString parentName); QVector m_uboMembers; - void initializeShaderStorageBlocks(const QVector &shaderStorageBlockDescription); mutable QMutex m_mutex; QMetaObject::Connection m_contextConnection; diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp index 97db303c2..d7a7265a7 100644 --- a/src/render/materialsystem/shaderdata.cpp +++ b/src/render/materialsystem/shaderdata.cpp @@ -162,7 +162,7 @@ ShaderData *ShaderData::lookupResource(QNodeId id) } // RenderCommand updater jobs -QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const +QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const noexcept { // Note protecting m_worldMatrix at this point as we assume all world updates // have been performed when reaching this point diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h index 080d2c85e..6b185d2ea 100644 --- a/src/render/materialsystem/shaderdata_p.h +++ b/src/render/materialsystem/shaderdata_p.h @@ -89,7 +89,7 @@ public: // Called by FramePreparationJob void updateWorldTransform(const Matrix4x4 &worldMatrix); - QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const; + QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) const noexcept; // Unit tests purposes only TransformType propertyTransformType(const QString &name) const; -- cgit v1.2.3