From ef702546c9262e0ea0343caccb5f7992691ebe9a Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 26 Feb 2015 11:34:53 +0100 Subject: RenderView: moved the ShaderData name/value map building out It is now contained in RenderViewJobUtils inside an helper struct called UniformBlockValueBuilder. This allow to simplify the code and will make unit testing easier. Change-Id: Ibbeeda8d913bfa1adc7c93c1fecb9cafda15deb3 Reviewed-by: Sean Harmer --- src/render/backend/jobs/renderviewjobutils.cpp | 68 +++++++++++++++ src/render/backend/jobs/renderviewjobutils_p.h | 22 +++++ src/render/backend/renderview.cpp | 114 +++++-------------------- src/render/backend/renderview_p.h | 14 +-- 4 files changed, 115 insertions(+), 103 deletions(-) diff --git a/src/render/backend/jobs/renderviewjobutils.cpp b/src/render/backend/jobs/renderviewjobutils.cpp index 62d9f2202..3d341ed2d 100644 --- a/src/render/backend/jobs/renderviewjobutils.cpp +++ b/src/render/backend/jobs/renderviewjobutils.cpp @@ -52,6 +52,9 @@ #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -339,6 +342,71 @@ RenderStateSet *buildRenderStateSet(RenderRenderPass *pass, QFrameAllocator *all return stateSet; } +namespace { + +const QString blockArray = QStringLiteral("[%1]"); +const int qNodeIdTypeId = qMetaTypeId(); + +} + +UniformBlockValueBuilder::UniformBlockValueBuilder() + : shaderDataManager(Q_NULLPTR) +{ +} + +UniformBlockValueBuilder::~UniformBlockValueBuilder() +{ +} + +void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(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 + if (value.userType() == QMetaType::QVariantList) { // Array + QVariantList list = value.value(); + if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember + for (int i = 0; i < list.size(); ++i) { + if (list.at(i).userType() == qNodeIdTypeId) { + RenderShaderData *subShaderData = shaderDataManager->lookupResource(list.at(i).value()); + if (subShaderData) + buildActiveUniformNameValueMapStructHelper(subShaderData, + blockName + QStringLiteral(".") + qmlPropertyName + blockArray.arg(i), + QStringLiteral("")); + } + } + } else { // Array of scalar/vec qmlPropertyName[0] + QString varName = blockName + QStringLiteral(".") + qmlPropertyName + QStringLiteral("[0]"); + if (uniforms.contains(varName)) + activeUniformNamesToValue.insert(varName, value); + } + } else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember + RenderShaderData *rSubShaderData = shaderDataManager->lookupResource(value.value()); + if (rSubShaderData) + buildActiveUniformNameValueMapStructHelper(rSubShaderData, + blockName, + qmlPropertyName); + } else { // Scalar / Vec + QString varName = blockName + QStringLiteral(".") + qmlPropertyName; + if (uniforms.contains(varName)) + activeUniformNamesToValue.insert(varName, value); + } +} + +void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(RenderShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) +{ + const QHash &properties = updatedPropertiesOnly ? rShaderData->updatedProperties() : rShaderData->properties(); + QHash::const_iterator it = properties.begin(); + const QHash::const_iterator end = properties.end(); + + while (it != end) { + QString prefix = qmlPropertyName.isEmpty() ? QStringLiteral("") : QStringLiteral("."); + buildActiveUniformNameValueMapHelper(blockName + prefix + qmlPropertyName, + it.key(), + it.value()); + ++it; + } +} + } // namespace Render } // namespace Qt3D diff --git a/src/render/backend/jobs/renderviewjobutils_p.h b/src/render/backend/jobs/renderviewjobutils_p.h index 3c6714247..19bf9f6ce 100644 --- a/src/render/backend/jobs/renderviewjobutils_p.h +++ b/src/render/backend/jobs/renderviewjobutils_p.h @@ -60,6 +60,9 @@ class RenderStateSet; class RenderTechnique; class RenderView; class Renderer; +class ShaderDataManager; +class ShaderUniform; +class RenderShaderData; Q_AUTOTEST_EXPORT void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphNode *fgLeaf); @@ -103,6 +106,25 @@ Q_AUTOTEST_EXPORT ParameterInfoList::iterator findParamInfo(ParameterInfoList *i Q_AUTOTEST_EXPORT RenderStateSet *buildRenderStateSet(RenderRenderPass *pass, QFrameAllocator *allocator); + +struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder +{ + UniformBlockValueBuilder(); + ~UniformBlockValueBuilder(); + + void buildActiveUniformNameValueMapHelper(const QString &blockName, + const QString &qmlPropertyName, + const QVariant &value); + void buildActiveUniformNameValueMapStructHelper(RenderShaderData *rShaderData, + const QString &blockName, + const QString &qmlPropertyName = QString()); + + bool updatedPropertiesOnly; + QHash uniforms; + QHash activeUniformNamesToValue; + ShaderDataManager *shaderDataManager; +}; + } // namespace Render } // namespace Qt3D diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 606bfea88..36664515c 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -95,9 +95,6 @@ bool isEntityInLayers(const RenderEntity *entity, const QStringList &layers) return false; } -const QString blockArray = QStringLiteral("[%1]"); -const int qNodeIdTypeId = qMetaTypeId(); - } // anonymouse namespace RenderView::StandardUniformsPFuncsHash RenderView::ms_standardUniformSetters = RenderView::initializeStandardUniformSetters(); @@ -348,6 +345,12 @@ void RenderView::sort() } } +void RenderView::setRenderer(Renderer *renderer) +{ + m_renderer = renderer; + m_data->m_uniformBlockBuilder.shaderDataManager = m_renderer->shaderDataManager(); +} + // Tries to order renderCommand by shader so as to minimize shader changes void RenderView::buildRenderCommands(RenderEntity *node) { @@ -425,70 +428,6 @@ void RenderView::setUniformValue(QUniformPack &uniformPack, const QString &name, } } -// Builds a QHash -> QmlPropertyName / ActiveUniformName -void RenderView::buildActiveUniformNameValueMap(const QHash &uniforms, - const QString &blockName, - const QString &qmlPropertyName, - const QVariant &value, - bool updatedPropertiesOnly) -{ - // In the end, values are either scalar or a scalar array - // Composed elements (structs, structs array) are simplified into simple scalars - if (value.userType() == QMetaType::QVariantList) { // Array - QVariantList list = value.value(); - if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember - for (int i = 0; i < list.size(); ++i) { - if (list.at(i).userType() == qNodeIdTypeId) { - RenderShaderData *subShaderData = m_renderer->shaderDataManager()->lookupResource(list.at(i).value()); - if (subShaderData) - buildActiveUniformNameValueMapStructHelper(uniforms, - subShaderData, - blockName + QStringLiteral(".") + qmlPropertyName + blockArray.arg(i), - QStringLiteral(""), - updatedPropertiesOnly); - } - } - } else { // Array of scalar/vec qmlPropertyName[0] - QString varName = blockName + QStringLiteral(".") + qmlPropertyName + QStringLiteral("[0]"); - if (uniforms.contains(varName)) - m_activeUniformNamesToValue.insert(varName, value); - } - } else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember - RenderShaderData *rSubShaderData = m_renderer->shaderDataManager()->lookupResource(value.value()); - if (rSubShaderData) - buildActiveUniformNameValueMapStructHelper(uniforms, - rSubShaderData, - blockName, - qmlPropertyName, - updatedPropertiesOnly); - } else { // Scalar / Vec - QString varName = blockName + QStringLiteral(".") + qmlPropertyName; - if (uniforms.contains(varName)) - m_activeUniformNamesToValue.insert(varName, value); - } -} - -void RenderView::buildActiveUniformNameValueMapStructHelper(const QHash &uniforms, - RenderShaderData *rShaderData, - const QString &blockName, - const QString &qmlPropertyName, - bool updatedPropertiesOnly) -{ - const QHash &properties = updatedPropertiesOnly ? rShaderData->updatedProperties() : rShaderData->properties(); - QHash::const_iterator it = properties.begin(); - const QHash::const_iterator end = properties.end(); - - while (it != end) { - QString prefix = qmlPropertyName.isEmpty() ? QStringLiteral("") : QStringLiteral("."); - buildActiveUniformNameValueMap(uniforms, - blockName + prefix + qmlPropertyName, - it.key(), - it.value(), - updatedPropertiesOnly); - ++it; - } -} - void RenderView::setUniformBlockValue(QUniformPack &uniformPack, RenderShader *shader, const ShaderUniformBlock &block, const QVariant &value) { RenderShaderData *shaderData = Q_NULLPTR; @@ -521,21 +460,17 @@ void RenderView::setUniformBlockValue(QUniformPack &uniformPack, RenderShader *s // for all the updated properties (all the properties if the UBO was just created) if (shaderData->needsUpdate(*m_data->m_viewMatrix) || uboNeedsUpdate) { // Clear previous values remaining in the hash - m_activeUniformNamesToValue.clear(); + m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear(); + // Update only update properties if uboNeedsUpdate is true, otherwise update the whole block + m_data->m_uniformBlockBuilder.updatedPropertiesOnly = uboNeedsUpdate; // Retrieve names and description of each active uniforms in the uniform block - const QHash &activeProperties = shader->activeUniformsForBlock(block.m_index); - - // We want a copy here in case another RenderViewJobs modifies the updatedProperties of the RenderShaderData - const QHash properties = uboNeedsUpdate ? shaderData->properties() : shaderData->updatedProperties(); - QHash::const_iterator it = properties.begin(); - const QHash::const_iterator end = properties.end(); - - for (; it != end; ++it) - buildActiveUniformNameValueMap(activeProperties, block.m_name, it.key(), it.value(), !uboNeedsUpdate); - + m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForBlock(block.m_index); + // Builds the name-value map for the block + m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, block.m_name); if (!uboNeedsUpdate) shaderData->addToClearUpdateList(); - uniformBlockUBO.m_updatedProperties = m_activeUniformNamesToValue; + // copy the name-value map into the BlockToUBO + uniformBlockUBO.m_updatedProperties = m_data->m_uniformBlockBuilder.activeUniformNamesToValue; uboNeedsUpdate = true; } @@ -546,22 +481,19 @@ void RenderView::setUniformBlockValue(QUniformPack &uniformPack, RenderShader *s void RenderView::setDefaultUniformBlockShaderDataValue(QUniformPack &uniformPack, RenderShader *shader, RenderShaderData *shaderData, const QString &structName) { - m_activeUniformNamesToValue.clear(); + m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear(); // updates transformed properties; shaderData->needsUpdate(*m_data->m_viewMatrix); + // Force to update the whole block + m_data->m_uniformBlockBuilder.updatedPropertiesOnly = false; // Retrieve names and description of each active uniforms in the uniform block - const QHash &activeUniformsInDefaultBlock = shader->activeUniformsForBlock(-1); - - const QHash &properties = shaderData->properties(); - QHash::const_iterator pIt = properties.begin(); - const QHash::const_iterator pEnd = properties.end(); - - for (; pIt != pEnd; ++pIt) - buildActiveUniformNameValueMap(activeUniformsInDefaultBlock, structName, pIt.key(), pIt.value(), false); - - QHash::const_iterator activeValuesIt = m_activeUniformNamesToValue.begin(); - const QHash::const_iterator activeValuesEnd = m_activeUniformNamesToValue.end(); + m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForBlock(-1); + // Build name-value map for the block + m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, structName); + // Set uniform values for each entrie of the block name-value map + QHash::const_iterator activeValuesIt = m_data->m_uniformBlockBuilder.activeUniformNamesToValue.begin(); + const QHash::const_iterator activeValuesEnd = m_data->m_uniformBlockBuilder.activeUniformNamesToValue.end(); while (activeValuesIt != activeValuesEnd) { setUniformValue(uniformPack, activeValuesIt.key(), activeValuesIt.value()); diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index bb24cc67e..83215dbf8 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -90,7 +90,7 @@ public: // TODO: Add a way to specify a sort predicate for the RenderCommands void sort(); - inline void setRenderer(Renderer *renderer) { m_renderer = renderer; } + void setRenderer(Renderer *renderer); inline void setSurfaceSize(const QSize &size) { m_surfaceSize = size; } inline Renderer *renderer() const { return m_renderer; } @@ -211,6 +211,7 @@ private: QStringList m_layers; QList m_sortingCriteria; QVector3D m_eyePos; + UniformBlockValueBuilder m_uniformBlockBuilder; } *m_data; mutable QColor *m_clearColor; @@ -219,7 +220,6 @@ private: AttachmentPack m_attachmentPack; QClearBuffer::BufferType m_clearBuffer; int m_frameIndex; - QHash m_activeUniformNamesToValue; // We do not use pointers to RenderNodes or Drawable's here so that the // render aspect is free to change the drawables on the next frame whilst @@ -253,16 +253,6 @@ private: RenderShader *shader, const ShaderUniformBlock &block, const QVariant &value); - void buildActiveUniformNameValueMap(const QHash &uniforms, - const QString &blockName, - const QString &qmlPropertyName, - const QVariant &value, - bool updatedPropertiesOnly); - void buildActiveUniformNameValueMapStructHelper(const QHash &uniforms, - RenderShaderData *rShaderData, - const QString &blockName, - const QString &qmlPropertyName, - bool updatedPropertiesOnlyue); void setDefaultUniformBlockShaderDataValue(QUniformPack &uniformPack, RenderShader *shader, RenderShaderData *shaderData, -- cgit v1.2.3