diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-02-26 01:00:25 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2020-02-26 18:39:21 +0100 |
commit | 75c0ffaf6d2b92cdf26092e01acdd5af4afeac97 (patch) | |
tree | bb9e85c21248790ec99b3665928872e39b14db64 /src/gui/util | |
parent | 4753d69d8934258de7fb64550e50a5cbb9b5603f (diff) | |
parent | 462c2745a5168a5b57381d05779b5d16aebe018e (diff) | |
download | qtbase-75c0ffaf6d2b92cdf26092e01acdd5af4afeac97.tar.gz |
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
examples/network/bearermonitor/CMakeLists.txt
examples/network/CMakeLists.txt
src/corelib/tools/qlinkedlist.h
src/sql/kernel/qsqldriver_p.h
src/sql/kernel/qsqlresult_p.h
src/widgets/kernel/qwidget.cpp
src/widgets/kernel/qwidget_p.h
tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
tests/auto/tools/moc/allmocs_baseline_in.json
Change-Id: I21a3c34570ae79ea9d30107fae71759d7eac17d9
Diffstat (limited to 'src/gui/util')
-rw-r--r-- | src/gui/util/qshadergenerator.cpp | 106 | ||||
-rw-r--r-- | src/gui/util/qshadergraph.cpp | 64 |
2 files changed, 134 insertions, 36 deletions
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp index 4beed8ed25..1ec25ccd7b 100644 --- a/src/gui/util/qshadergenerator.cpp +++ b/src/gui/util/qshadergenerator.cpp @@ -42,6 +42,8 @@ #include "qshaderlanguage_p.h" #include <QRegularExpression> +#include <cctype> + QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg) @@ -344,10 +346,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) code << QByteArrayLiteral("void main()"); code << QByteArrayLiteral("{"); - const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+)).*;$")); - const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("^(.*\\s+(v\\d+))\\s*=\\s*(.*);$")); + const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);")); const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); - const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("^\\s*(\\w+)\\s*=\\s*(.*);$")); + const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); struct Variable; @@ -457,6 +458,13 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) QByteArray line = node.rule(format).substitution; const QVector<QShaderNodePort> ports = node.ports(); + struct VariableReplacement { + QByteArray placeholder; + QByteArray variable; + }; + + QVector<VariableReplacement> variableReplacements; + // Generate temporary variable names vN for (const QShaderNodePort &port : ports) { const QString portName = port.name; @@ -472,23 +480,65 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) if (variableIndex < 0) continue; - const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8()); - const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex)); + VariableReplacement replacement; + replacement.placeholder = QByteArrayLiteral("$") + portName.toUtf8(); + replacement.variable = QByteArrayLiteral("v") + QByteArray::number(variableIndex); + + variableReplacements.append(std::move(replacement)); + } + + int begin = 0; + while ((begin = line.indexOf('$', begin)) != -1) { + int end = begin + 1; + char endChar = line.at(end); + const int size = line.size(); + while (end < size && (std::isalnum(endChar) || endChar == '_')) { + ++end; + endChar = line.at(end); + } + + const int placeholderLength = end - begin; + + const QByteArray variableName = line.mid(begin, placeholderLength); + const auto replacementIt = std::find_if(variableReplacements.cbegin(), variableReplacements.cend(), + [&variableName](const VariableReplacement &replacement) { + return variableName == replacement.placeholder; + }); - line.replace(placeholder, variable); + if (replacementIt != variableReplacements.cend()) { + line.replace(begin, placeholderLength, replacementIt->variable); + begin += replacementIt->variable.length(); + } else { + begin = end; + } } // Substitute variable names by generated vN variable names const QByteArray substitutionedLine = replaceParameters(line, node, format); - Variable *v = nullptr; + QRegularExpressionMatchIterator matches; switch (node.type()) { - // Record name of temporary variable that possibly references a global input - // We will replace the temporary variables by the matching global variables later - case QShaderNode::Input: { - const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Input: + case QShaderNode::Output: + matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + break; + case QShaderNode::Function: + matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + break; + case QShaderNode::Invalid: + break; + } + + while (matches.hasNext()) { + QRegularExpressionMatch match = matches.next(); + + Variable *v = nullptr; + + switch (node.type()) { + // Record name of temporary variable that possibly references a global input + // We will replace the temporary variables by the matching global variables later + case QShaderNode::Input: { const QString localVariable = match.captured(1); const QString globalVariable = match.captured(2); @@ -499,13 +549,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) Assignment assignment; assignment.expression = globalVariable; v->assignment = assignment; + break; } - break; - } - case QShaderNode::Function: { - const QRegularExpressionMatch match = temporaryVariableToAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Function: { const QString localVariableDeclaration = match.captured(1); const QString localVariableName = match.captured(2); const QString assignmentContent = match.captured(3); @@ -518,13 +565,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) // Find variables that may be referenced in the assignment gatherTemporaryVariablesFromAssignment(v, assignmentContent); + break; } - break; - } - case QShaderNode::Output: { - const QRegularExpressionMatch match = outputToTemporaryAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Output: { const QString outputDeclaration = match.captured(1); const QString assignmentContent = match.captured(2); @@ -539,17 +583,17 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) // Find variables that may be referenced in the assignment gatherTemporaryVariablesFromAssignment(v, assignmentContent); + break; + } + case QShaderNode::Invalid: + break; } - break; - } - case QShaderNode::Invalid: - break; - } - LineContent lineContent; - lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); - lineContent.var = v; - lines << lineContent; + LineContent lineContent; + lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); + lineContent.var = v; + lines << lineContent; + } } // Go through all lines diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp index b05b710713..611bb4b938 100644 --- a/src/gui/util/qshadergraph.cpp +++ b/src/gui/util/qshadergraph.cpp @@ -44,13 +44,20 @@ QT_BEGIN_NAMESPACE namespace { - QVector<QShaderNode> copyOutputNodes(const QVector<QShaderNode> &nodes) + QVector<QShaderNode> copyOutputNodes(const QVector<QShaderNode> &nodes, const QVector<QShaderGraph::Edge> &edges) { auto res = QVector<QShaderNode>(); std::copy_if(nodes.cbegin(), nodes.cend(), std::back_inserter(res), - [] (const QShaderNode &node) { - return node.type() == QShaderNode::Output; + [&edges] (const QShaderNode &node) { + return node.type() == QShaderNode::Output || + (node.type() == QShaderNode::Function && + !std::any_of(edges.cbegin(), + edges.cend(), + [&node] (const QShaderGraph::Edge &edge) { + return edge.sourceNodeUuid == + node.uuid(); + })); }); return res; } @@ -116,6 +123,50 @@ namespace } return targetStatement; } + + void removeNodesWithUnboundInputs(QVector<QShaderGraph::Statement> &statements, + const QVector<QShaderGraph::Edge> &allEdges) + { + // A node is invalid if any of its input ports is disconected + // or connected to the output port of another invalid node. + + // Keeps track of the edges from the nodes we know to be valid + // to unvisited nodes + auto currentEdges = QVector<QShaderGraph::Edge>(); + + statements.erase(std::remove_if(statements.begin(), + statements.end(), + [¤tEdges, &allEdges] (const QShaderGraph::Statement &statement) { + const QShaderNode &node = statement.node; + const QVector<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, node.uuid()); + const QVector<QShaderNodePort> ports = node.ports(); + + bool allInputsConnected = true; + for (const QShaderNodePort &port : node.ports()) { + if (port.direction == QShaderNodePort::Output) + continue; + + const auto edgeIt = std::find_if(outgoing.cbegin(), + outgoing.cend(), + [&port] (const QShaderGraph::Edge &edge) { + return edge.targetPortName == port.name; + }); + + if (edgeIt != outgoing.cend()) + currentEdges.removeAll(*edgeIt); + else + allInputsConnected = false; + } + + if (allInputsConnected) { + const QVector<QShaderGraph::Edge> incoming = incomingEdges(allEdges, node.uuid()); + currentEdges.append(incoming); + } + + return !allInputsConnected; + }), + statements.end()); + } } QUuid QShaderGraph::Statement::uuid() const noexcept @@ -210,8 +261,8 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis auto result = QVector<Statement>(); QVector<Edge> currentEdges = enabledEdges; - QVector<QUuid> currentUuids = [enabledNodes] { - const QVector<QShaderNode> inputs = copyOutputNodes(enabledNodes); + QVector<QUuid> currentUuids = [enabledNodes, enabledEdges] { + const QVector<QShaderNode> inputs = copyOutputNodes(enabledNodes, enabledEdges); auto res = QVector<QUuid>(); std::transform(inputs.cbegin(), inputs.cend(), std::back_inserter(res), @@ -241,6 +292,9 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis } std::reverse(result.begin(), result.end()); + + removeNodesWithUnboundInputs(result, enabledEdges); + return result; } |