Implement graph layers support in QShaderGraph
When creating the statements, it is now possible to pass a list of enabled layer names. Every node or edge which is not in the list of enabled layers will be pruned from the graph prior to traversal. Note that an empty layer list for a node or an edge means it is on all layers. Change-Id: I61a4df7d395b4beb42ee55ce08fef8ebe04263c9 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
This commit is contained in:
parent
32281653bf
commit
f3c70ab9f3
@ -172,20 +172,46 @@ QVector<QShaderGraph::Edge> QShaderGraph::edges() const Q_DECL_NOTHROW
|
||||
return m_edges;
|
||||
}
|
||||
|
||||
QVector<QShaderGraph::Statement> QShaderGraph::createStatements() const
|
||||
QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringList &enabledLayers) const
|
||||
{
|
||||
const auto idHash = [this] {
|
||||
const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
|
||||
return layers.isEmpty()
|
||||
|| std::any_of(layers.cbegin(), layers.cend(),
|
||||
[enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
|
||||
};
|
||||
|
||||
const auto enabledNodes = [this, intersectsEnabledLayers] {
|
||||
auto res = QVector<QShaderNode>();
|
||||
std::copy_if(m_nodes.cbegin(), m_nodes.cend(),
|
||||
std::back_inserter(res),
|
||||
[intersectsEnabledLayers] (const QShaderNode &node) {
|
||||
return intersectsEnabledLayers(node.layers());
|
||||
});
|
||||
return res;
|
||||
}();
|
||||
|
||||
const auto enabledEdges = [this, intersectsEnabledLayers] {
|
||||
auto res = QVector<Edge>();
|
||||
std::copy_if(m_edges.cbegin(), m_edges.cend(),
|
||||
std::back_inserter(res),
|
||||
[intersectsEnabledLayers] (const Edge &edge) {
|
||||
return intersectsEnabledLayers(edge.layers);
|
||||
});
|
||||
return res;
|
||||
}();
|
||||
|
||||
const auto idHash = [enabledNodes] {
|
||||
auto nextVarId = 0;
|
||||
auto res = QHash<QUuid, Statement>();
|
||||
for (const auto &node : qAsConst(m_nodes))
|
||||
for (const auto &node : enabledNodes)
|
||||
res.insert(node.uuid(), nodeToStatement(node, nextVarId));
|
||||
return res;
|
||||
}();
|
||||
|
||||
auto result = QVector<Statement>();
|
||||
auto currentEdges = m_edges;
|
||||
auto currentUuids = [this] {
|
||||
const auto inputs = copyOutputNodes(m_nodes);
|
||||
auto currentEdges = enabledEdges;
|
||||
auto currentUuids = [enabledNodes] {
|
||||
const auto inputs = copyOutputNodes(enabledNodes);
|
||||
auto res = QVector<QUuid>();
|
||||
std::transform(inputs.cbegin(), inputs.cend(),
|
||||
std::back_inserter(res),
|
||||
@ -201,7 +227,7 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements() const
|
||||
// input nodes
|
||||
while (!currentUuids.isEmpty()) {
|
||||
const auto uuid = currentUuids.takeFirst();
|
||||
result.append(completeStatement(idHash, m_edges, uuid));
|
||||
result.append(completeStatement(idHash, enabledEdges, uuid));
|
||||
|
||||
const auto outgoing = outgoingEdges(currentEdges, uuid);
|
||||
for (const auto &outgoingEdge : outgoing) {
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
Q_GUI_EXPORT void removeEdge(const Edge &edge);
|
||||
Q_GUI_EXPORT QVector<Edge> edges() const Q_DECL_NOTHROW;
|
||||
|
||||
Q_GUI_EXPORT QVector<Statement> createStatements() const;
|
||||
Q_GUI_EXPORT QVector<Statement> createStatements(const QStringList &enabledLayers = QStringList()) const;
|
||||
|
||||
private:
|
||||
QVector<QShaderNode> m_nodes;
|
||||
|
@ -113,6 +113,7 @@ private slots:
|
||||
void shouldHandleUnboundPortsDuringGraphSerialization();
|
||||
void shouldSurviveCyclesDuringGraphSerialization();
|
||||
void shouldDealWithEdgesJumpingOverLayers();
|
||||
void shouldGenerateDifferentStatementsDependingOnActiveLayers();
|
||||
};
|
||||
|
||||
void tst_QShaderGraph::shouldHaveEdgeDefaultState()
|
||||
@ -657,6 +658,122 @@ void tst_QShaderGraph::shouldDealWithEdgesJumpingOverLayers()
|
||||
QCOMPARE(statements, expected);
|
||||
}
|
||||
|
||||
void tst_QShaderGraph::shouldGenerateDifferentStatementsDependingOnActiveLayers()
|
||||
{
|
||||
// GIVEN
|
||||
const auto texCoord = createNode({
|
||||
createPort(QShaderNodePort::Output, "texCoord")
|
||||
}, {
|
||||
"diffuseTexture",
|
||||
"normalTexture"
|
||||
});
|
||||
const auto diffuseUniform = createNode({
|
||||
createPort(QShaderNodePort::Output, "color")
|
||||
}, {"diffuseUniform"});
|
||||
const auto diffuseTexture = createNode({
|
||||
createPort(QShaderNodePort::Input, "coord"),
|
||||
createPort(QShaderNodePort::Output, "color")
|
||||
}, {"diffuseTexture"});
|
||||
const auto normalUniform = createNode({
|
||||
createPort(QShaderNodePort::Output, "normal")
|
||||
}, {"normalUniform"});
|
||||
const auto normalTexture = createNode({
|
||||
createPort(QShaderNodePort::Input, "coord"),
|
||||
createPort(QShaderNodePort::Output, "normal")
|
||||
}, {"normalTexture"});
|
||||
const auto lightFunction = createNode({
|
||||
createPort(QShaderNodePort::Input, "color"),
|
||||
createPort(QShaderNodePort::Input, "normal"),
|
||||
createPort(QShaderNodePort::Output, "output")
|
||||
});
|
||||
const auto fragColor = createNode({
|
||||
createPort(QShaderNodePort::Input, "fragColor")
|
||||
});
|
||||
|
||||
const auto graph = [=] {
|
||||
auto res = QShaderGraph();
|
||||
|
||||
res.addNode(texCoord);
|
||||
res.addNode(diffuseUniform);
|
||||
res.addNode(diffuseTexture);
|
||||
res.addNode(normalUniform);
|
||||
res.addNode(normalTexture);
|
||||
res.addNode(lightFunction);
|
||||
res.addNode(fragColor);
|
||||
|
||||
res.addEdge(createEdge(diffuseUniform.uuid(), "color", lightFunction.uuid(), "color", {"diffuseUniform"}));
|
||||
res.addEdge(createEdge(texCoord.uuid(), "texCoord", diffuseTexture.uuid(), "coord", {"diffuseTexture"}));
|
||||
res.addEdge(createEdge(diffuseTexture.uuid(), "color", lightFunction.uuid(), "color", {"diffuseTexture"}));
|
||||
|
||||
res.addEdge(createEdge(normalUniform.uuid(), "normal", lightFunction.uuid(), "normal", {"normalUniform"}));
|
||||
res.addEdge(createEdge(texCoord.uuid(), "texCoord", normalTexture.uuid(), "coord", {"normalTexture"}));
|
||||
res.addEdge(createEdge(normalTexture.uuid(), "normal", lightFunction.uuid(), "normal", {"normalTexture"}));
|
||||
|
||||
res.addEdge(createEdge(lightFunction.uuid(), "output", fragColor.uuid(), "fragColor"));
|
||||
|
||||
return res;
|
||||
}();
|
||||
|
||||
{
|
||||
// WHEN
|
||||
const auto statements = graph.createStatements({"diffuseUniform", "normalUniform"});
|
||||
|
||||
// THEN
|
||||
const auto expected = QVector<QShaderGraph::Statement>()
|
||||
<< createStatement(normalUniform, {}, {1})
|
||||
<< createStatement(diffuseUniform, {}, {0})
|
||||
<< createStatement(lightFunction, {0, 1}, {2})
|
||||
<< createStatement(fragColor, {2}, {});
|
||||
dumpStatementsIfNeeded(statements, expected);
|
||||
QCOMPARE(statements, expected);
|
||||
}
|
||||
|
||||
{
|
||||
// WHEN
|
||||
const auto statements = graph.createStatements({"diffuseUniform", "normalTexture"});
|
||||
|
||||
// THEN
|
||||
const auto expected = QVector<QShaderGraph::Statement>()
|
||||
<< createStatement(texCoord, {}, {0})
|
||||
<< createStatement(normalTexture, {0}, {2})
|
||||
<< createStatement(diffuseUniform, {}, {1})
|
||||
<< createStatement(lightFunction, {1, 2}, {3})
|
||||
<< createStatement(fragColor, {3}, {});
|
||||
dumpStatementsIfNeeded(statements, expected);
|
||||
QCOMPARE(statements, expected);
|
||||
}
|
||||
|
||||
{
|
||||
// WHEN
|
||||
const auto statements = graph.createStatements({"diffuseTexture", "normalUniform"});
|
||||
|
||||
// THEN
|
||||
const auto expected = QVector<QShaderGraph::Statement>()
|
||||
<< createStatement(texCoord, {}, {0})
|
||||
<< createStatement(normalUniform, {}, {2})
|
||||
<< createStatement(diffuseTexture, {0}, {1})
|
||||
<< createStatement(lightFunction, {1, 2}, {3})
|
||||
<< createStatement(fragColor, {3}, {});
|
||||
dumpStatementsIfNeeded(statements, expected);
|
||||
QCOMPARE(statements, expected);
|
||||
}
|
||||
|
||||
{
|
||||
// WHEN
|
||||
const auto statements = graph.createStatements({"diffuseTexture", "normalTexture"});
|
||||
|
||||
// THEN
|
||||
const auto expected = QVector<QShaderGraph::Statement>()
|
||||
<< createStatement(texCoord, {}, {0})
|
||||
<< createStatement(normalTexture, {0}, {2})
|
||||
<< createStatement(diffuseTexture, {0}, {1})
|
||||
<< createStatement(lightFunction, {1, 2}, {3})
|
||||
<< createStatement(fragColor, {3}, {});
|
||||
dumpStatementsIfNeeded(statements, expected);
|
||||
QCOMPARE(statements, expected);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QShaderGraph)
|
||||
|
||||
#include "tst_qshadergraph.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user