ShaderNode: Add automatic variables

This commit is contained in:
Lynix 2020-05-26 20:30:24 +02:00
parent 09e08255fb
commit d96bc9db6e
12 changed files with 143 additions and 19 deletions

View File

@ -40,6 +40,12 @@ namespace Nz
VertexPosition, // gl_Position
};
enum class ExpressionCategory
{
LValue,
RValue
};
enum class ExpressionType
{
Boolean, // bool
@ -104,6 +110,7 @@ namespace Nz
class NAZARA_RENDERER_API Expression : public Node
{
public:
virtual ExpressionCategory GetExpressionCategory() const;
virtual ExpressionType GetExpressionType() const = 0;
};
@ -152,6 +159,7 @@ namespace Nz
public:
inline Variable(VariableType varKind, ExpressionType varType);
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
ExpressionType type;
@ -191,14 +199,14 @@ namespace Nz
class NAZARA_RENDERER_API AssignOp : public Expression
{
public:
inline AssignOp(AssignType Op, VariablePtr Var, ExpressionPtr Right);
inline AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right);
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override;
AssignType op;
VariablePtr variable;
ExpressionPtr left;
ExpressionPtr right;
};
@ -277,6 +285,7 @@ namespace Nz
public:
inline SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override;

View File

@ -82,11 +82,14 @@ namespace Nz
{
}
inline AssignOp::AssignOp(AssignType Op, VariablePtr Var, ExpressionPtr Right) :
inline AssignOp::AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right) :
op(Op),
variable(std::move(Var)),
left(std::move(Left)),
right(std::move(Right))
{
if (left->GetExpressionCategory() != ExpressionCategory::LValue)
//TODO: AstParseError
throw std::runtime_error("Assignation is only possible with lvalues");
}
inline BinaryOp::BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right) :

View File

@ -18,7 +18,7 @@ namespace Nz { namespace ShaderBuilder
{
constexpr AssignOpBuilder() {}
std::shared_ptr<ShaderAst::AssignOp> operator()(const ShaderAst::VariablePtr& left, const ShaderAst::ExpressionPtr& right) const;
std::shared_ptr<ShaderAst::AssignOp> operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const;
};
template<ShaderAst::BinaryType op>

View File

@ -15,7 +15,7 @@ namespace Nz { namespace ShaderBuilder
}
template<ShaderAst::AssignType op>
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::VariablePtr& left, const ShaderAst::ExpressionPtr& right) const
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
{
return std::make_shared<ShaderAst::AssignOp>(op, left, right);
}

View File

@ -139,7 +139,7 @@ namespace Nz
void GlslWriter::Write(const ShaderAst::AssignOp& node)
{
Write(node.variable);
Write(node.left);
switch (node.op)
{

View File

@ -8,6 +8,11 @@
namespace Nz::ShaderAst
{
ExpressionCategory Expression::GetExpressionCategory() const
{
return ExpressionCategory::RValue;
}
void ExpressionStatement::Register(ShaderWriter& visitor)
{
expression->Register(visitor);
@ -43,6 +48,10 @@ namespace Nz::ShaderAst
visitor.Write(*this);
}
ExpressionCategory Variable::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType Variable::GetExpressionType() const
{
@ -60,7 +69,7 @@ namespace Nz::ShaderAst
}
void BuiltinVariable::Register(ShaderWriter& visitor)
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
{
}
@ -72,12 +81,12 @@ namespace Nz::ShaderAst
ExpressionType AssignOp::GetExpressionType() const
{
return variable->GetExpressionType();
return left->GetExpressionType();
}
void AssignOp::Register(ShaderWriter& visitor)
{
variable->Register(visitor);
left->Register(visitor);
right->Register(visitor);
}
@ -102,6 +111,7 @@ namespace Nz::ShaderAst
case ShaderAst::BinaryType::Equality:
exprType = ExpressionType::Boolean;
break;
}
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
@ -178,7 +188,12 @@ namespace Nz::ShaderAst
}
ExpressionType ShaderAst::SwizzleOp::GetExpressionType() const
ExpressionCategory SwizzleOp::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType SwizzleOp::GetExpressionType() const
{
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
}

View File

@ -13,6 +13,13 @@ ShaderNode(graph)
UpdatePreview();
});
if (graph.GetInputCount() > 0)
{
auto& firstInput = graph.GetInput(0);
m_currentInputIndex = 0;
m_currentInputText = firstInput.name;
}
UpdatePreview();
}

View File

@ -14,6 +14,15 @@ ShaderNode(graph)
if (m_currentTextureIndex == textureIndex)
UpdatePreview();
});
if (graph.GetTextureCount() > 0)
{
auto& firstInput = graph.GetTexture(0);
m_currentTextureIndex = 0;
m_currentTextureText = firstInput.name;
}
UpdateOutput();
}
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const

View File

@ -40,13 +40,28 @@ m_flowScene(BuildRegistry())
OnSelectedNodeUpdate(this, nullptr);
});
auto& node1 = m_flowScene.createNode(std::make_unique<Vec4Value>(*this));
node1.nodeGraphicsObject().setPos(200, 200);
// Test
AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
AddTexture("Potato", TextureType::Sampler2D);
auto& node2 = m_flowScene.createNode(std::make_unique<FragmentOutput>(*this));
node2.nodeGraphicsObject().setPos(500, 300);
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
auto& node1 = m_flowScene.createNode(std::make_unique<InputValue>(*this));
node1.nodeGraphicsObject().setPos(0, 200);
auto& node2 = m_flowScene.createNode(std::make_unique<SampleTexture>(*this));
node2.nodeGraphicsObject().setPos(200, 200);
auto& node3 = m_flowScene.createNode(std::make_unique<Vec4Mul>(*this));
node3.nodeGraphicsObject().setPos(400, 200);
auto& node4 = m_flowScene.createNode(std::make_unique<FragmentOutput>(*this));
node4.nodeGraphicsObject().setPos(600, 300);
m_flowScene.createConnection(node2, 0, node1, 0);
m_flowScene.createConnection(node3, 0, node2, 0);
m_flowScene.createConnection(node3, 1, node2, 0);
m_flowScene.createConnection(node4, 0, node3, 0);
}
ShaderGraph::~ShaderGraph()
@ -83,13 +98,51 @@ std::size_t ShaderGraph::AddTexture(std::string name, TextureType type)
Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
{
std::vector<Nz::ShaderAst::StatementPtr> statements;
QHash<QUuid, unsigned int> usageCount;
unsigned int varCount = 0;
std::function<void(QtNodes::Node*)> DetectVariables;
DetectVariables = [&](QtNodes::Node* node)
{
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
qDebug() << shaderNode->name() << node->id();
auto it = usageCount.find(node->id());
if (it == usageCount.end())
it = usageCount.insert(node->id(), 0);
(*it)++;
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
{
for (const auto& [uuid, conn] : connectionSet)
{
DetectVariables(conn->getNode(QtNodes::PortType::Out));
}
}
};
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)
{
if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0)
DetectVariables(node);
});
QHash<QUuid, Nz::ShaderAst::ExpressionPtr> variableExpressions;
std::function<Nz::ShaderAst::ExpressionPtr(QtNodes::Node*)> HandleNode;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
{
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
qDebug() << shaderNode->name();
qDebug() << shaderNode->name() << node->id();
if (auto it = variableExpressions.find(node->id()); it != variableExpressions.end())
return *it;
auto it = usageCount.find(node->id());
assert(it != usageCount.end());
std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In);
Nz::StackArray<Nz::ShaderAst::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount);
std::size_t i = 0;
@ -104,7 +157,25 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
}
}
return shaderNode->GetExpression(expressions.data(), expressions.size());
auto expression = shaderNode->GetExpression(expressions.data(), expressions.size());
if (*it > 1)
{
Nz::ShaderAst::ExpressionPtr varExpression;
if (expression->GetExpressionCategory() == Nz::ShaderAst::ExpressionCategory::RValue)
{
varExpression = Nz::ShaderBuilder::Variable("var" + std::to_string(varCount++), expression->GetExpressionType());
statements.emplace_back(Nz::ShaderBuilder::ExprStatement(Nz::ShaderBuilder::Assign(varExpression, expression)));
}
else
varExpression = expression;
variableExpressions.insert(node->id(), varExpression);
return varExpression;
}
else
return expression;
};
m_flowScene.iterateOverNodes([&](QtNodes::Node* node)

View File

@ -26,10 +26,12 @@ class ShaderGraph
std::size_t AddTexture(std::string name, TextureType type);
inline const InputEntry& GetInput(std::size_t inputIndex) const;
inline std::size_t GetInputCount() const;
inline const std::vector<InputEntry>& GetInputs() const;
inline const PreviewModel& GetPreviewModel() const;
inline QtNodes::FlowScene& GetScene();
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
inline std::size_t GetTextureCount() const;
inline const std::vector<TextureEntry>& GetTextures() const;
Nz::ShaderAst::StatementPtr ToAst();

View File

@ -6,6 +6,11 @@ inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEn
return m_inputs[inputIndex];
}
inline std::size_t ShaderGraph::GetInputCount() const
{
return m_inputs.size();
}
inline auto ShaderGraph::GetInputs() const -> const std::vector<InputEntry>&
{
return m_inputs;
@ -27,6 +32,11 @@ inline auto ShaderGraph::GetTexture(std::size_t textureIndex) const -> const Tex
return m_textures[textureIndex];
}
inline std::size_t ShaderGraph::GetTextureCount() const
{
return m_textures.size();
}
inline auto ShaderGraph::GetTextures() const -> const std::vector<TextureEntry>&
{
return m_textures;

View File

@ -8,8 +8,6 @@ int main(int argc, char* argv[])
QApplication app(argc, argv);
ShaderGraph shaderGraph;
shaderGraph.AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
shaderGraph.AddTexture("Potato", TextureType::Sampler2D);
MainWindow mainWindow(shaderGraph);
mainWindow.resize(1280, 720);