diff options
4 files changed, 44 insertions, 22 deletions
diff --git a/src/plugins/renderers/opengl/renderer/renderview.cpp b/src/plugins/renderers/opengl/renderer/renderview.cpp index 78622366b..a97889d34 100644 --- a/src/plugins/renderers/opengl/renderer/renderview.cpp +++ b/src/plugins/renderers/opengl/renderer/renderview.cpp @@ -1210,11 +1210,11 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, } void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, - const GLShader *shader, + const std::vector<int> &uniformsNamesIds, ShaderData *shaderData, const QString &structName) const { - UniformBlockValueBuilder builder(shader->uniformsNamesIds(), + UniformBlockValueBuilder builder(uniformsNamesIds, m_manager->shaderDataManager(), m_manager->textureManager(), m_viewMatrix); @@ -1258,7 +1258,7 @@ void RenderView::applyParameter(const Parameter *param, if (uniformValue.valueType() == UniformValue::NodeId && (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) { // Try to check if we have a struct or array matching a QShaderData parameter - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(nameId)); + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader->uniformsNamesIds(), shaderData, StringToInt::lookupString(nameId)); } break; } @@ -1414,8 +1414,8 @@ void RenderView::updateLightUniforms(RenderCommand *command, const Entity *entit if (worldTransform) shaderData->updateWorldTransform(*worldTransform); - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, GLLights::LIGHT_STRUCT_NAMES[lightIdx]); - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, GLLights::LIGHT_STRUCT_UNROLL_NAMES[lightIdx]); + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader->lightUniformsNamesIds(), shaderData, GLLights::LIGHT_STRUCT_NAMES[lightIdx]); + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader->lightUniformsNamesIds(), shaderData, GLLights::LIGHT_STRUCT_UNROLL_NAMES[lightIdx]); ++lightIdx; } } @@ -1448,7 +1448,8 @@ void RenderView::updateLightUniforms(RenderCommand *command, const Entity *entit if (m_environmentLight && m_environmentLight->isEnabled()) { ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(m_environmentLight->shaderData()); if (shaderData) { - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight")); + // EnvLight isn't part of the light uniform name ids + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader->uniformsNamesIds(), shaderData, QStringLiteral("envLight")); auto irr = shaderData->properties()["irradiance"].value.value<Qt3DCore::QNodeId>(); auto spec = diff --git a/src/plugins/renderers/opengl/renderer/renderview_p.h b/src/plugins/renderers/opengl/renderer/renderview_p.h index d67a04b8c..b2fb7c69f 100644 --- a/src/plugins/renderers/opengl/renderer/renderview_p.h +++ b/src/plugins/renderers/opengl/renderer/renderview_p.h @@ -392,7 +392,7 @@ private: const ShaderStorageBlock &block, const UniformValue &value) const; void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, - const GLShader *shader, + const std::vector<int> &uniformsNamesIds, ShaderData *shaderData, const QString &structName) const; void applyParameter(const Parameter *param, diff --git a/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp b/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp index 750956b1b..54c02a8b1 100644 --- a/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp +++ b/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp @@ -620,29 +620,34 @@ void PipelineUBOSet::uploadUBOsForCommand(const RenderCommand &command, for (const RHIShader::UBO_Member &member : qAsConst(uboBlock.members)) { const QShaderDescription::BlockVariable &blockVariable = member.blockVariable; + + // Array if (!blockVariable.arrayDims.empty()) { - if (!blockVariable.structMembers.empty()) { - const int arr0 = blockVariable.arrayDims[0]; - for (int i = 0; i < arr0; i++) { - for (const RHIShader::UBO_Member &structMember : member.structMembers) { + if (!blockVariable.structMembers.empty()) { // Array of structs + // we treat structMembers as arrayMembers when we are dealing with an array of structs´ + const size_t arr0 = size_t(blockVariable.arrayDims[0]); + const size_t m = std::max(arr0, member.structMembers.size()); + for (size_t i = 0; i < m; ++i) { + const RHIShader::UBO_Member &arrayMember = member.structMembers[i]; + for (const RHIShader::UBO_Member &arrayStructMember : arrayMember.structMembers) { uploadUniform(uniforms, ubo, - structMember, + arrayStructMember, distanceToCommand, i * blockVariable.size / arr0); } } - } else { + } else { // Array of scalars uploadUniform(uniforms, ubo, member, distanceToCommand); } } else { - if (!blockVariable.structMembers.empty()) { + if (!blockVariable.structMembers.empty()) { // Struct for (const RHIShader::UBO_Member &structMember : member.structMembers) { uploadUniform(uniforms, ubo, structMember, distanceToCommand); } - } else { + } else { // Scalar uploadUniform(uniforms, ubo, member, distanceToCommand); } diff --git a/src/plugins/renderers/rhi/renderer/rhishader.cpp b/src/plugins/renderers/rhi/renderer/rhishader.cpp index e76fc2fd3..6509746ab 100644 --- a/src/plugins/renderers/rhi/renderer/rhishader.cpp +++ b/src/plugins/renderers/rhi/renderer/rhishader.cpp @@ -332,7 +332,14 @@ void RHIShader::recordAllUniforms(UBO_Member &uboMember, // 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); + const QString unqualifiedMemberName = (fullMemberName + str); + m_unqualifiedUniformNames << unqualifiedMemberName; + + // Record as an individual uniform + m_uniformsNames.push_back(unqualifiedMemberName); + const int nameId = StringToInt::lookupId(unqualifiedMemberName); + m_uniformsNamesIds.push_back(nameId); + // Question : does it make sense to also record foo[0], foo[0][0], etc... // if there are e.g. 3 dimensions ? }); @@ -344,20 +351,29 @@ void RHIShader::recordAllUniforms(UBO_Member &uboMember, m_structNamesIds.push_back(StringToInt::lookupId(m_structNames.back())); }); - // Record the struct members - for (const QShaderDescription::BlockVariable& bv : member.structMembers) { - forEachArrayAccessor(member.arrayDims, [&] (const QString& str) { + // Record the array times the struct members => entry[i].struct_member + forEachArrayAccessor(member.arrayDims, [&] (const QString& str) { + UBO_Member arrayMember {StringToInt::lookupId(fullMemberName + str), {}, {}}; + // Record all struct member into the array member[i] + for (const QShaderDescription::BlockVariable& bv : member.structMembers) { //recordAllUniforms("baz", "foo.bar[1][2].") const QString structMemberNamePrefix = fullMemberName + str + QLatin1Char('.'); UBO_Member innerMember {StringToInt::lookupId(structMemberNamePrefix), bv, {}}; recordAllUniforms(innerMember, structMemberNamePrefix); - uboMember.structMembers.push_back(innerMember); - }); - } + arrayMember.structMembers.push_back(innerMember); + } + // When dealing with an array of structs, we treat structMembers as arrayMembers + uboMember.structMembers.push_back(arrayMember); + }); } else { // Final member (not array or struct) // Replace nameId with final nameId name uboMember.nameId = StringToInt::lookupId(fullMemberName); + + // Record as an individual uniform + m_uniformsNames.push_back(fullMemberName); + const int nameId = StringToInt::lookupId(fullMemberName); + m_uniformsNamesIds.push_back(nameId); } } |