QShaderGraph: don't generate statements with undefined inputs
This fixes the shader generation for graphs like this one: Function0 ------> Output0 (with unbound input) Input ------> Function1 ------> Output1 With those graphs, createStatements will not return any statement for nodes Function0 and Output0. Change-Id: Iec32aa51623e176b03ae23e580f06d14df80a194 Reviewed-by: Paul Lemire <paul.lemire@kdab.com> (cherry picked from commit 7981dbfaf371a368fbd69e935768b310f42a0e5a)
This commit is contained in:
parent
b150901525
commit
34369b5e90
@ -123,6 +123,50 @@ namespace
|
|||||||
}
|
}
|
||||||
return targetStatement;
|
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 Q_DECL_NOTHROW
|
QUuid QShaderGraph::Statement::uuid() const Q_DECL_NOTHROW
|
||||||
@ -248,6 +292,9 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(result.begin(), result.end());
|
std::reverse(result.begin(), result.end());
|
||||||
|
|
||||||
|
removeNodesWithUnboundInputs(result, enabledEdges);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,12 +516,9 @@ void tst_QShaderGraph::shouldHandleUnboundPortsDuringGraphSerialization()
|
|||||||
const auto statements = graph.createStatements();
|
const auto statements = graph.createStatements();
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
// Note that no edge leads to the unbound input
|
// Note that no statement has any unbound input
|
||||||
const auto expected = QVector<QShaderGraph::Statement>()
|
const auto expected = QVector<QShaderGraph::Statement>()
|
||||||
<< createStatement(input, {}, {0})
|
<< createStatement(input, {}, {0});
|
||||||
<< createStatement(function, {-1, 0, -1}, {2, 3, 4})
|
|
||||||
<< createStatement(unboundOutput, {-1}, {})
|
|
||||||
<< createStatement(output, {3}, {});
|
|
||||||
dumpStatementsIfNeeded(statements, expected);
|
dumpStatementsIfNeeded(statements, expected);
|
||||||
QCOMPARE(statements, expected);
|
QCOMPARE(statements, expected);
|
||||||
}
|
}
|
||||||
@ -568,9 +565,8 @@ void tst_QShaderGraph::shouldSurviveCyclesDuringGraphSerialization()
|
|||||||
const auto statements = graph.createStatements();
|
const auto statements = graph.createStatements();
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
// Obviously will lead to a compile failure later on since it cuts everything beyond the cycle
|
// The cycle is ignored
|
||||||
const auto expected = QVector<QShaderGraph::Statement>()
|
const auto expected = QVector<QShaderGraph::Statement>();
|
||||||
<< createStatement(output, {2}, {});
|
|
||||||
dumpStatementsIfNeeded(statements, expected);
|
dumpStatementsIfNeeded(statements, expected);
|
||||||
QCOMPARE(statements, expected);
|
QCOMPARE(statements, expected);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user