ShaderAst: Big refactor + add binding/location support

This commit is contained in:
Lynix
2020-06-17 16:00:03 +02:00
parent 463b540739
commit f38bfdde8a
63 changed files with 2380 additions and 1603 deletions

View File

@@ -11,16 +11,15 @@
namespace Nz
{
GlslWriter::GlslWriter() :
m_currentFunction(nullptr),
m_currentState(nullptr),
m_glslVersion(110)
{
}
String GlslWriter::Generate(const ShaderAst::StatementPtr& node)
std::string GlslWriter::Generate(const ShaderAst& shader)
{
std::string error;
if (!ShaderAst::Validate(node, &error))
if (!ValidateShader(shader, &error))
throw std::runtime_error("Invalid shader AST: " + error);
State state;
@@ -30,91 +29,54 @@ namespace Nz
m_currentState = nullptr;
});
// Register global variables (uniforms, varying, ..)
node->Register(*this);
// Header
Append("#version ");
AppendLine(String::Number(m_glslVersion));
AppendLine(std::to_string(m_glslVersion));
AppendLine();
// Global variables (uniforms, input and outputs)
DeclareVariables(state.uniforms, "uniform", "Uniforms");
DeclareVariables(state.inputs, "in", "Inputs");
DeclareVariables(state.outputs, "out", "Outputs");
// Extensions
Function entryPoint;
entryPoint.name = "main"; //< GLSL has only one entry point name possible
entryPoint.node = node;
entryPoint.retType = ShaderAst::ExpressionType::Void;
std::vector<std::string> requiredExtensions;
AppendFunction(entryPoint);
// GL_ARB_shading_language_420pack (required for layout(binding = X))
if (m_glslVersion < 420 && HasExplicitBinding(shader))
requiredExtensions.emplace_back("GL_ARB_shading_language_420pack");
return state.stream;
}
// GL_ARB_explicit_uniform_location (required for layout(location = X))
if (m_glslVersion < 430 && HasExplicitLocation(shader))
requiredExtensions.emplace_back("GL_ARB_explicit_uniform_location");
void GlslWriter::RegisterFunction(const String& name, ShaderAst::StatementPtr statement, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType retType)
{
Function func;
func.retType = retType;
func.name = name;
func.node = std::move(statement);
func.parameters.assign(parameters);
m_functions[name] = std::move(func);
}
void GlslWriter::RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
NazaraAssert(kind != ShaderAst::VariableType::Builtin, "Builtin variables should not be registered");
switch (kind)
if (!requiredExtensions.empty())
{
case ShaderAst::VariableType::Builtin: //< Only there to make compiler happy
case ShaderAst::VariableType::Variable:
break;
for (const std::string& ext : requiredExtensions)
AppendLine("#extension " + ext + " : require");
case ShaderAst::VariableType::Input:
m_currentState->inputs.emplace(type, name);
break;
case ShaderAst::VariableType::Output:
m_currentState->outputs.emplace(type, name);
break;
case ShaderAst::VariableType::Parameter:
{
if (m_currentFunction)
{
bool found = false;
for (const auto& varPtr : m_currentFunction->parameters)
{
if (varPtr->name == name)
{
found = true;
if (varPtr->type != type)
{
//TODO: AstParseError
throw std::runtime_error("Function uses parameter \"" + name.ToStdString() + "\" with a different type than specified in the function arguments");
}
break;
}
}
if (!found)
//TODO: AstParseError
throw std::runtime_error("Function has no parameter \"" + name.ToStdString() + "\"");
}
break;
}
case ShaderAst::VariableType::Uniform:
m_currentState->uniforms.emplace(type, name);
break;
AppendLine();
}
// Global variables (uniforms, input and outputs)
DeclareVariables(shader.GetUniforms(), "uniform", "Uniforms");
DeclareVariables(shader.GetInputs(), "in", "Inputs");
DeclareVariables(shader.GetOutputs(), "out", "Outputs");
std::size_t functionCount = shader.GetFunctionCount();
if (functionCount > 1)
{
AppendCommentSection("Prototypes");
for (const auto& func : shader.GetFunctions())
{
if (func.name != "main")
{
AppendFunctionPrototype(func);
AppendLine(";");
}
}
}
for (const auto& func : shader.GetFunctions())
AppendFunction(func);
return state.stream.str();
}
void GlslWriter::SetGlslVersion(unsigned int version)
@@ -122,22 +84,127 @@ namespace Nz
m_glslVersion = version;
}
void GlslWriter::Visit(const ShaderAst::Sample2D& node)
void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin)
{
Append("texture(");
Visit(node.sampler);
Append(", ");
Visit(node.coordinates);
Append(")");
switch (builtin)
{
case ShaderNodes::BuiltinEntry::VertexPosition:
Append("gl_Position");
break;
}
}
void GlslWriter::Visit(const ShaderAst::AssignOp& node)
void GlslWriter::Append(ShaderNodes::ExpressionType type)
{
switch (type)
{
case ShaderNodes::ExpressionType::Boolean:
Append("bool");
break;
case ShaderNodes::ExpressionType::Float1:
Append("float");
break;
case ShaderNodes::ExpressionType::Float2:
Append("vec2");
break;
case ShaderNodes::ExpressionType::Float3:
Append("vec3");
break;
case ShaderNodes::ExpressionType::Float4:
Append("vec4");
break;
case ShaderNodes::ExpressionType::Mat4x4:
Append("mat4");
break;
case ShaderNodes::ExpressionType::Sampler2D:
Append("sampler2D");
break;
case ShaderNodes::ExpressionType::Void:
Append("void");
break;
}
}
void GlslWriter::AppendCommentSection(const std::string& section)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
String stars((section.size() < 33) ? (36 - section.size()) / 2 : 3, '*');
m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/";
AppendLine();
}
void GlslWriter::AppendFunction(const ShaderAst::Function& func)
{
NazaraAssert(!m_context.currentFunction, "A function is already being processed");
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
AppendFunctionPrototype(func);
m_context.currentFunction = &func;
CallOnExit onExit([this] ()
{
m_context.currentFunction = nullptr;
});
EnterScope();
{
Visit(func.statement);
}
LeaveScope();
}
void GlslWriter::AppendFunctionPrototype(const ShaderAst::Function& func)
{
Append(func.returnType);
Append(" ");
Append(func.name);
Append("(");
for (std::size_t i = 0; i < func.parameters.size(); ++i)
{
if (i != 0)
Append(", ");
Append(func.parameters[i].type);
Append(" ");
Append(func.parameters[i].name);
}
Append(")\n");
}
void GlslWriter::AppendLine(const std::string& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt << '\n' << std::string(m_currentState->indentLevel, '\t');
}
void GlslWriter::EnterScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel++;
AppendLine("{");
}
void GlslWriter::LeaveScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel--;
AppendLine();
AppendLine("}");
}
void GlslWriter::Visit(const ShaderNodes::AssignOp& node)
{
Visit(node.left);
switch (node.op)
{
case ShaderAst::AssignType::Simple:
case ShaderNodes::AssignType::Simple:
Append(" = ");
break;
}
@@ -145,7 +212,7 @@ namespace Nz
Visit(node.right);
}
void GlslWriter::Visit(const ShaderAst::Branch& node)
void GlslWriter::Visit(const ShaderNodes::Branch& node)
{
bool first = true;
for (const auto& statement : node.condStatements)
@@ -174,45 +241,25 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::BinaryFunc& node)
{
switch (node.intrinsic)
{
case ShaderAst::BinaryIntrinsic::CrossProduct:
Append("cross");
break;
case ShaderAst::BinaryIntrinsic::DotProduct:
Append("dot");
break;
}
Append("(");
Visit(node.left);
Append(", ");
Visit(node.right);
Append(")");
}
void GlslWriter::Visit(const ShaderAst::BinaryOp& node)
void GlslWriter::Visit(const ShaderNodes::BinaryOp& node)
{
Visit(node.left);
switch (node.op)
{
case ShaderAst::BinaryType::Add:
case ShaderNodes::BinaryType::Add:
Append(" + ");
break;
case ShaderAst::BinaryType::Substract:
case ShaderNodes::BinaryType::Substract:
Append(" - ");
break;
case ShaderAst::BinaryType::Multiply:
case ShaderNodes::BinaryType::Multiply:
Append(" * ");
break;
case ShaderAst::BinaryType::Divide:
case ShaderNodes::BinaryType::Divide:
Append(" / ");
break;
case ShaderAst::BinaryType::Equality:
case ShaderNodes::BinaryType::Equality:
Append(" == ");
break;
}
@@ -220,18 +267,18 @@ namespace Nz
Visit(node.right);
}
void GlslWriter::Visit(const ShaderAst::BuiltinVariable& node)
void GlslWriter::Visit(const ShaderNodes::BuiltinVariable& var)
{
Append(node.var);
Append(var.type);
}
void GlslWriter::Visit(const ShaderAst::Cast& node)
void GlslWriter::Visit(const ShaderNodes::Cast& node)
{
Append(node.exprType);
Append("(");
unsigned int i = 0;
unsigned int requiredComponents = ShaderAst::Node::GetComponentCount(node.exprType);
unsigned int requiredComponents = ShaderNodes::Node::GetComponentCount(node.exprType);
while (requiredComponents > 0)
{
if (i != 0)
@@ -241,34 +288,34 @@ namespace Nz
NazaraAssert(exprPtr, "Invalid expression");
Visit(exprPtr);
requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType());
requiredComponents -= ShaderNodes::Node::GetComponentCount(exprPtr->GetExpressionType());
}
Append(")");
}
void GlslWriter::Visit(const ShaderAst::Constant& node)
void GlslWriter::Visit(const ShaderNodes::Constant& node)
{
switch (node.exprType)
{
case ShaderAst::ExpressionType::Boolean:
case ShaderNodes::ExpressionType::Boolean:
Append((node.values.bool1) ? "true" : "false");
break;
case ShaderAst::ExpressionType::Float1:
Append(String::Number(node.values.vec1));
case ShaderNodes::ExpressionType::Float1:
Append(std::to_string(node.values.vec1));
break;
case ShaderAst::ExpressionType::Float2:
Append("vec2(" + String::Number(node.values.vec2.x) + ", " + String::Number(node.values.vec2.y) + ")");
case ShaderNodes::ExpressionType::Float2:
Append("vec2(" + std::to_string(node.values.vec2.x) + ", " + std::to_string(node.values.vec2.y) + ")");
break;
case ShaderAst::ExpressionType::Float3:
Append("vec3(" + String::Number(node.values.vec3.x) + ", " + String::Number(node.values.vec3.y) + ", " + String::Number(node.values.vec3.z) + ")");
case ShaderNodes::ExpressionType::Float3:
Append("vec3(" + std::to_string(node.values.vec3.x) + ", " + std::to_string(node.values.vec3.y) + ", " + std::to_string(node.values.vec3.z) + ")");
break;
case ShaderAst::ExpressionType::Float4:
Append("vec4(" + String::Number(node.values.vec4.x) + ", " + String::Number(node.values.vec4.y) + ", " + String::Number(node.values.vec4.z) + ", " + String::Number(node.values.vec4.w) + ")");
case ShaderNodes::ExpressionType::Float4:
Append("vec4(" + std::to_string(node.values.vec4.x) + ", " + std::to_string(node.values.vec4.y) + ", " + std::to_string(node.values.vec4.z) + ", " + std::to_string(node.values.vec4.w) + ")");
break;
default:
@@ -276,9 +323,9 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::DeclareVariable& node)
void GlslWriter::Visit(const ShaderNodes::DeclareVariable& node)
{
Append(node.variable->GetExpressionType());
Append(node.variable->type);
Append(" ");
Append(node.variable->name);
if (node.expression)
@@ -292,21 +339,76 @@ namespace Nz
AppendLine(";");
}
void GlslWriter::Visit(const ShaderAst::ExpressionStatement& node)
void GlslWriter::Visit(const ShaderNodes::ExpressionStatement& node)
{
Visit(node.expression);
Append(";");
}
void GlslWriter::Visit(const ShaderAst::NamedVariable& node)
void GlslWriter::Visit(const ShaderNodes::Identifier& node)
{
Append(node.name);
Visit(node.var);
}
void GlslWriter::Visit(const ShaderAst::StatementBlock& node)
void GlslWriter::Visit(const ShaderNodes::InputVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::IntrinsicCall& node)
{
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
Append("cross");
break;
case ShaderNodes::IntrinsicType::DotProduct:
Append("dot");
break;
}
m_currentState->stream << '(';
for (std::size_t i = 0; i < node.parameters.size(); ++i)
{
if (i != 0)
m_currentState->stream << ", ";
Visit(node.parameters[i]);
m_currentState->stream << ' ';
Visit(node.parameters[i]);
}
m_currentState->stream << ")\n";
}
void GlslWriter::Visit(const ShaderNodes::LocalVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::ParameterVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::OutputVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::Sample2D& node)
{
Append("texture(");
Visit(node.sampler);
Append(", ");
Visit(node.coordinates);
Append(")");
}
void GlslWriter::Visit(const ShaderNodes::StatementBlock& node)
{
bool first = true;
for (const ShaderAst::StatementPtr& statement : node.statements)
for (const ShaderNodes::StatementPtr& statement : node.statements)
{
if (!first)
AppendLine();
@@ -317,7 +419,7 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::SwizzleOp& node)
void GlslWriter::Visit(const ShaderNodes::SwizzleOp& node)
{
Visit(node.expression);
Append(".");
@@ -326,166 +428,55 @@ namespace Nz
{
switch (node.components[i])
{
case ShaderAst::SwizzleComponent::First:
case ShaderNodes::SwizzleComponent::First:
Append("x");
break;
case ShaderAst::SwizzleComponent::Second:
case ShaderNodes::SwizzleComponent::Second:
Append("y");
break;
case ShaderAst::SwizzleComponent::Third:
case ShaderNodes::SwizzleComponent::Third:
Append("z");
break;
case ShaderAst::SwizzleComponent::Fourth:
case ShaderNodes::SwizzleComponent::Fourth:
Append("w");
break;
}
}
}
void GlslWriter::Append(ShaderAst::BuiltinEntry builtin)
void GlslWriter::Visit(const ShaderNodes::UniformVariable& var)
{
switch (builtin)
Append(var.name);
}
bool GlslWriter::HasExplicitBinding(const ShaderAst& shader)
{
for (const auto& uniform : shader.GetUniforms())
{
case ShaderAst::BuiltinEntry::VertexPosition:
Append("gl_Position");
break;
if (uniform.bindingIndex.has_value())
return true;
}
return false;
}
void GlslWriter::Append(ShaderAst::ExpressionType type)
bool GlslWriter::HasExplicitLocation(const ShaderAst& shader)
{
switch (type)
for (const auto& input : shader.GetInputs())
{
case ShaderAst::ExpressionType::Boolean:
Append("bool");
break;
case ShaderAst::ExpressionType::Float1:
Append("float");
break;
case ShaderAst::ExpressionType::Float2:
Append("vec2");
break;
case ShaderAst::ExpressionType::Float3:
Append("vec3");
break;
case ShaderAst::ExpressionType::Float4:
Append("vec4");
break;
case ShaderAst::ExpressionType::Mat4x4:
Append("mat4");
break;
case ShaderAst::ExpressionType::Sampler2D:
Append("sampler2D");
break;
case ShaderAst::ExpressionType::Void:
Append("void");
break;
if (input.locationIndex.has_value())
return true;
}
}
void GlslWriter::Append(const String& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt;
}
void GlslWriter::AppendCommentSection(const String& section)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
String stars((section.GetSize() < 33) ? (36 - section.GetSize()) / 2 : 3, '*');
m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/";
AppendLine();
}
void GlslWriter::AppendFunction(Function& func)
{
NazaraAssert(!m_currentFunction, "A function is already being processed");
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentFunction = &func;
CallOnExit onExit([this] ()
for (const auto& output : shader.GetOutputs())
{
m_currentFunction = nullptr;
});
func.node->Register(*this);
Append(func.retType);
m_currentState->stream << ' ';
Append(func.name);
m_currentState->stream << '(';
for (std::size_t i = 0; i < func.parameters.size(); ++i)
{
if (i != 0)
m_currentState->stream << ", ";
Append(func.parameters[i]->type);
m_currentState->stream << ' ';
Append(func.parameters[i]->name);
if (output.locationIndex.has_value())
return true;
}
m_currentState->stream << ")\n";
EnterScope();
{
Visit(func.node);
}
LeaveScope();
return false;
}
void GlslWriter::AppendLine(const String& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt << '\n' << String(m_currentState->indentLevel, '\t');
}
void GlslWriter::DeclareVariables(const VariableContainer& variables, const String& keyword, const String& section)
{
if (!variables.empty())
{
if (!section.IsEmpty())
AppendCommentSection(section);
for (const auto& pair : variables)
{
if (!keyword.IsEmpty())
{
Append(keyword);
Append(" ");
}
Append(pair.first);
Append(" ");
Append(pair.second);
AppendLine(";");
}
AppendLine();
}
}
void GlslWriter::EnterScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel++;
AppendLine("{");
}
void GlslWriter::LeaveScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel--;
AppendLine();
AppendLine("}");
}
}

View File

@@ -3,275 +3,40 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz
{
Node::~Node() = default;
ExpressionCategory Expression::GetExpressionCategory() const
void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters, ShaderNodes::ExpressionType returnType)
{
return ExpressionCategory::RValue;
auto& functionEntry = m_functions.emplace_back();
functionEntry.name = std::move(name);
functionEntry.parameters = std::move(parameters);
functionEntry.returnType = returnType;
functionEntry.statement = std::move(statement);
}
void ExpressionStatement::Register(ShaderWriter& visitor)
void ShaderAst::AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
{
expression->Register(visitor);
auto& inputEntry = m_inputs.emplace_back();
inputEntry.name = std::move(name);
inputEntry.locationIndex = std::move(locationIndex);
inputEntry.type = type;
}
void ExpressionStatement::Visit(ShaderVisitor& visitor)
void ShaderAst::AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
{
visitor.Visit(*this);
auto& outputEntry = m_outputs.emplace_back();
outputEntry.name = std::move(name);
outputEntry.locationIndex = std::move(locationIndex);
outputEntry.type = type;
}
void ConditionalStatement::Register(ShaderWriter& visitor)
void ShaderAst::AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> bindingIndex)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Register(visitor);
}
void ConditionalStatement::Visit(ShaderVisitor& visitor)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Visit(visitor);
}
void StatementBlock::Register(ShaderWriter& visitor)
{
for (auto& statementPtr : statements)
statementPtr->Register(visitor);
}
void StatementBlock::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory Variable::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType Variable::GetExpressionType() const
{
return type;
}
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
{
}
void BuiltinVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void NamedVariable::Register(ShaderWriter& visitor)
{
visitor.RegisterVariable(kind, name, type);
}
void NamedVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void DeclareVariable::Register(ShaderWriter& visitor)
{
variable->Register(visitor);
if (expression)
expression->Register(visitor);
}
void DeclareVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType AssignOp::GetExpressionType() const
{
return left->GetExpressionType();
}
void AssignOp::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void AssignOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryOp::GetExpressionType() const
{
ShaderAst::ExpressionType exprType = ShaderAst::ExpressionType::Void;
switch (op)
{
case ShaderAst::BinaryType::Add:
case ShaderAst::BinaryType::Substract:
exprType = left->GetExpressionType();
break;
case ShaderAst::BinaryType::Divide:
case ShaderAst::BinaryType::Multiply:
//FIXME
exprType = static_cast<ExpressionType>(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType())));
break;
case ShaderAst::BinaryType::Equality:
exprType = ExpressionType::Boolean;
break;
}
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
return exprType;
}
void BinaryOp::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void BinaryOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void Branch::Register(ShaderWriter& visitor)
{
for (ConditionalStatement& statement : condStatements)
{
statement.condition->Register(visitor);
statement.statement->Register(visitor);
}
if (elseStatement)
elseStatement->Register(visitor);
}
void Branch::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Constant::GetExpressionType() const
{
return exprType;
}
void Constant::Register(ShaderWriter&)
{
}
void Constant::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Cast::GetExpressionType() const
{
return exprType;
}
void Cast::Register(ShaderWriter& visitor)
{
auto it = expressions.begin();
(*it)->Register(visitor);
for (; it != expressions.end(); ++it)
{
if (!*it)
break;
(*it)->Register(visitor);
}
}
void Cast::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory SwizzleOp::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType SwizzleOp::GetExpressionType() const
{
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
}
void SwizzleOp::Register(ShaderWriter& visitor)
{
expression->Register(visitor);
}
void SwizzleOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Sample2D::GetExpressionType() const
{
return ExpressionType::Float4;
}
void Sample2D::Register(ShaderWriter& visitor)
{
sampler->Register(visitor);
coordinates->Register(visitor);
}
void Sample2D::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryFunc::GetExpressionType() const
{
switch (intrinsic)
{
case BinaryIntrinsic::CrossProduct:
return left->GetExpressionType();
case BinaryIntrinsic::DotProduct:
return ExpressionType::Float1;
}
NazaraAssert(false, "Unhandled builtin");
return ExpressionType::Void;
}
void BinaryFunc::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void BinaryFunc::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
auto& uniformEntry = m_uniforms.emplace_back();
uniformEntry.bindingIndex = std::move(bindingIndex);
uniformEntry.name = std::move(name);
uniformEntry.type = type;
}
}

View File

@@ -0,0 +1,179 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
Node::~Node() = default;
ExpressionCategory Expression::GetExpressionCategory() const
{
return ExpressionCategory::RValue;
}
void ExpressionStatement::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void ConditionalStatement::Visit(ShaderVisitor& visitor)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Visit(visitor);
}
void StatementBlock::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void DeclareVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory Identifier::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType Identifier::GetExpressionType() const
{
assert(var);
return var->type;
}
void Identifier::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType AssignOp::GetExpressionType() const
{
return left->GetExpressionType();
}
void AssignOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryOp::GetExpressionType() const
{
ShaderNodes::ExpressionType exprType = ShaderNodes::ExpressionType::Void;
switch (op)
{
case ShaderNodes::BinaryType::Add:
case ShaderNodes::BinaryType::Substract:
exprType = left->GetExpressionType();
break;
case ShaderNodes::BinaryType::Divide:
case ShaderNodes::BinaryType::Multiply:
//FIXME
exprType = static_cast<ExpressionType>(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType())));
break;
case ShaderNodes::BinaryType::Equality:
exprType = ExpressionType::Boolean;
break;
}
NazaraAssert(exprType != ShaderNodes::ExpressionType::Void, "Unhandled builtin");
return exprType;
}
void BinaryOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void Branch::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Constant::GetExpressionType() const
{
return exprType;
}
void Constant::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Cast::GetExpressionType() const
{
return exprType;
}
void Cast::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory SwizzleOp::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType SwizzleOp::GetExpressionType() const
{
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
}
void SwizzleOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Sample2D::GetExpressionType() const
{
return ExpressionType::Float4;
}
void Sample2D::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType IntrinsicCall::GetExpressionType() const
{
switch (intrinsic)
{
case IntrinsicType::CrossProduct:
return parameters.front()->GetExpressionType();
case IntrinsicType::DotProduct:
return ExpressionType::Float1;
}
NazaraAssert(false, "Unhandled builtin");
return ExpressionType::Void;
}
void IntrinsicCall::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
}

View File

@@ -3,13 +3,15 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz::ShaderNodes
{
namespace
{
class ShaderSerializerVisitor : public ShaderVisitor
class ShaderSerializerVisitor : public ShaderVisitor, public ShaderVarVisitor
{
public:
ShaderSerializerVisitor(ShaderSerializerBase& serializer) :
@@ -22,11 +24,6 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const BinaryFunc& node) override
{
Serialize(node);
}
void Visit(const BinaryOp& node) override
{
Serialize(node);
@@ -37,11 +34,6 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const BuiltinVariable& node) override
{
Serialize(node);
}
void Visit(const Cast& node) override
{
Serialize(node);
@@ -62,7 +54,12 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const NamedVariable& node) override
void Visit(const Identifier& node) override
{
Serialize(node);
}
void Visit(const IntrinsicCall& node) override
{
Serialize(node);
}
@@ -82,6 +79,37 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const ShaderNodes::BuiltinVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::InputVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::LocalVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::OutputVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::ParameterVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::UniformVariable& var) override
{
Serialize(var);
}
private:
template<typename T>
void Serialize(const T& node)
@@ -101,13 +129,6 @@ namespace Nz::ShaderAst
Node(node.right);
}
void ShaderSerializerBase::Serialize(BinaryFunc& node)
{
Enum(node.intrinsic);
Node(node.left);
Node(node.right);
}
void ShaderSerializerBase::Serialize(BinaryOp& node)
{
Enum(node.op);
@@ -129,7 +150,7 @@ namespace Nz::ShaderAst
void ShaderSerializerBase::Serialize(BuiltinVariable& node)
{
Enum(node.var);
Enum(node.type);
Enum(node.type);
}
@@ -170,7 +191,7 @@ namespace Nz::ShaderAst
void ShaderSerializerBase::Serialize(DeclareVariable& node)
{
Node(node.variable);
Variable(node.variable);
Node(node.expression);
}
@@ -179,10 +200,22 @@ namespace Nz::ShaderAst
Node(node.expression);
}
void ShaderSerializerBase::Serialize(Identifier& node)
{
Variable(node.var);
}
void ShaderSerializerBase::Serialize(IntrinsicCall& node)
{
Enum(node.intrinsic);
Container(node.parameters);
for (auto& param : node.parameters)
Node(param);
}
void ShaderSerializerBase::Serialize(NamedVariable& node)
{
Value(node.name);
Enum(node.kind);
Enum(node.type);
}
@@ -272,6 +305,18 @@ namespace Nz::ShaderAst
m_stream << val;
}
void ShaderSerializer::Variable(VariablePtr& var)
{
VariableType nodeType = (var) ? var->GetType() : VariableType::None;
m_stream << static_cast<Int32>(nodeType);
if (var)
{
ShaderSerializerVisitor visitor(*this);
var->Visit(visitor);
}
}
ByteArray Serialize(const StatementPtr& shader)
{
ByteArray byteArray;
@@ -309,27 +354,26 @@ namespace Nz::ShaderAst
NodeType nodeType = static_cast<NodeType>(nodeTypeInt);
#define HandleNodeType(Type) case NodeType:: Type : node = std::make_shared<Type>(); break
#define HandleType(Type) case NodeType:: Type : node = std::make_shared<Type>(); break
switch (nodeType)
{
case NodeType::None: break;
HandleNodeType(AssignOp);
HandleNodeType(BinaryFunc);
HandleNodeType(BinaryOp);
HandleNodeType(Branch);
HandleNodeType(BuiltinVariable);
HandleNodeType(Cast);
HandleNodeType(Constant);
HandleNodeType(ConditionalStatement);
HandleNodeType(DeclareVariable);
HandleNodeType(ExpressionStatement);
HandleNodeType(NamedVariable);
HandleNodeType(Sample2D);
HandleNodeType(SwizzleOp);
HandleNodeType(StatementBlock);
HandleType(AssignOp);
HandleType(BinaryOp);
HandleType(Branch);
HandleType(Cast);
HandleType(Constant);
HandleType(ConditionalStatement);
HandleType(DeclareVariable);
HandleType(ExpressionStatement);
HandleType(Identifier);
HandleType(IntrinsicCall);
HandleType(Sample2D);
HandleType(SwizzleOp);
HandleType(StatementBlock);
}
#undef HandleNodeType
#undef HandleType
if (node)
{
@@ -372,5 +416,32 @@ namespace Nz::ShaderAst
{
m_stream >> val;
}
void ShaderUnserializer::Variable(VariablePtr& var)
{
Int32 nodeTypeInt;
m_stream >> nodeTypeInt;
VariableType nodeType = static_cast<VariableType>(nodeTypeInt);
#define HandleType(Type) case VariableType:: Type : var = std::make_shared<Type>(); break
switch (nodeType)
{
case VariableType::None: break;
HandleType(BuiltinVariable);
HandleType(InputVariable);
HandleType(LocalVariable);
HandleType(OutputVariable);
HandleType(UniformVariable);
}
#undef HandleType
if (var)
{
ShaderSerializerVisitor visitor(*this);
var->Visit(visitor);
}
}
}

View File

@@ -3,20 +3,49 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderValidator.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderVariables.hpp>
#include <vector>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz
{
struct AstError
{
std::string errMsg;
};
bool ShaderValidator::Validate(const StatementPtr& shader, std::string* error)
struct ShaderValidator::Context
{
struct Local
{
std::string name;
ShaderNodes::ExpressionType type;
};
const ShaderAst::Function* currentFunction;
std::vector<Local> declaredLocals;
std::vector<std::size_t> blockLocalIndex;
};
bool ShaderValidator::Validate(std::string* error)
{
try
{
shader->Visit(*this);
for (std::size_t i = 0; i < m_shader.GetFunctionCount(); ++i)
{
const auto& func = m_shader.GetFunction(i);
Context currentContext;
currentContext.currentFunction = &func;
m_context = &currentContext;
CallOnExit resetContext([&] { m_context = nullptr; });
func.statement->Visit(*this);
}
return true;
}
catch (const AstError& e)
@@ -28,14 +57,14 @@ namespace Nz::ShaderAst
}
}
const ExpressionPtr& ShaderValidator::MandatoryExpr(const ExpressionPtr& node)
const ShaderNodes::ExpressionPtr& ShaderValidator::MandatoryExpr(const ShaderNodes::ExpressionPtr& node)
{
MandatoryNode(node);
return node;
}
const NodePtr& ShaderValidator::MandatoryNode(const NodePtr& node)
const ShaderNodes::NodePtr& ShaderValidator::MandatoryNode(const ShaderNodes::NodePtr& node)
{
if (!node)
throw AstError{ "Invalid node" };
@@ -43,90 +72,76 @@ namespace Nz::ShaderAst
return node;
}
void ShaderValidator::TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right)
void ShaderValidator::TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right)
{
if (left->GetExpressionType() != right->GetExpressionType())
return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType());
}
void ShaderValidator::TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right)
{
if (left != right)
throw AstError{ "Left expression type must match right expression type" };
}
void ShaderValidator::Visit(const AssignOp& node)
void ShaderValidator::Visit(const ShaderNodes::AssignOp& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
TypeMustMatch(node.left, node.right);
Visit(node.left);
Visit(node.right);
}
void ShaderValidator::Visit(const BinaryFunc& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
TypeMustMatch(node.left, node.right);
switch (node.intrinsic)
{
case BinaryIntrinsic::CrossProduct:
{
if (node.left->GetExpressionType() != ExpressionType::Float3)
throw AstError{ "CrossProduct only works with Float3 expressions" };
}
case BinaryIntrinsic::DotProduct:
break;
}
if (node.left->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue)
throw AstError { "Assignation is only possible with a l-value" };
Visit(node.left);
Visit(node.right);
}
void ShaderValidator::Visit(const BinaryOp& node)
void ShaderValidator::Visit(const ShaderNodes::BinaryOp& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
ExpressionType leftType = node.left->GetExpressionType();
ExpressionType rightType = node.right->GetExpressionType();
ShaderNodes::ExpressionType leftType = node.left->GetExpressionType();
ShaderNodes::ExpressionType rightType = node.right->GetExpressionType();
switch (node.op)
{
case BinaryType::Add:
case BinaryType::Equality:
case BinaryType::Substract:
case ShaderNodes::BinaryType::Add:
case ShaderNodes::BinaryType::Equality:
case ShaderNodes::BinaryType::Substract:
TypeMustMatch(node.left, node.right);
break;
case BinaryType::Multiply:
case BinaryType::Divide:
case ShaderNodes::BinaryType::Multiply:
case ShaderNodes::BinaryType::Divide:
{
switch (leftType)
{
case ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float1:
{
if (Node::GetComponentType(rightType) != ExpressionType::Float1)
if (ShaderNodes::Node::GetComponentType(rightType) != ShaderNodes::ExpressionType::Float1)
throw AstError{ "Left expression type is not compatible with right expression type" };
break;
}
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
case ShaderNodes::ExpressionType::Float2:
case ShaderNodes::ExpressionType::Float3:
case ShaderNodes::ExpressionType::Float4:
{
if (leftType != rightType && rightType != ExpressionType::Float1)
if (leftType != rightType && rightType != ShaderNodes::ExpressionType::Float1)
throw AstError{ "Left expression type is not compatible with right expression type" };
break;
}
case ExpressionType::Mat4x4:
case ShaderNodes::ExpressionType::Mat4x4:
{
switch (rightType)
{
case ExpressionType::Float1:
case ExpressionType::Float4:
case ExpressionType::Mat4x4:
case ShaderNodes::ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float4:
case ShaderNodes::ExpressionType::Mat4x4:
break;
default:
@@ -146,7 +161,7 @@ namespace Nz::ShaderAst
Visit(node.right);
}
void ShaderValidator::Visit(const Branch& node)
void ShaderValidator::Visit(const ShaderNodes::Branch& node)
{
for (const auto& condStatement : node.condStatements)
{
@@ -155,11 +170,7 @@ namespace Nz::ShaderAst
}
}
void ShaderValidator::Visit(const BuiltinVariable& /*node*/)
{
}
void ShaderValidator::Visit(const Cast& node)
void ShaderValidator::Visit(const ShaderNodes::Cast& node)
{
unsigned int componentCount = 0;
unsigned int requiredComponents = node.GetComponentCount(node.exprType);
@@ -176,55 +187,203 @@ namespace Nz::ShaderAst
throw AstError{ "Component count doesn't match required component count" };
}
void ShaderValidator::Visit(const Constant& /*node*/)
void ShaderValidator::Visit(const ShaderNodes::Constant& /*node*/)
{
}
void ShaderValidator::Visit(const DeclareVariable& node)
void ShaderValidator::Visit(const ShaderNodes::DeclareVariable& node)
{
assert(m_context);
if (node.expression)
Visit(node.expression);
auto& local = m_context->declaredLocals.emplace_back();
local.name = node.variable->name;
local.type = node.variable->type;
}
void ShaderValidator::Visit(const ShaderNodes::ExpressionStatement& node)
{
Visit(MandatoryNode(node.expression));
}
void ShaderValidator::Visit(const ExpressionStatement& node)
void ShaderValidator::Visit(const ShaderNodes::Identifier& node)
{
Visit(MandatoryNode(node.expression));
assert(m_context);
if (!node.var)
throw AstError{ "Invalid variable" };
//< FIXME: Use variable visitor
switch (node.var->GetType())
{
case ShaderNodes::VariableType::BuiltinVariable:
break;
case ShaderNodes::VariableType::InputVariable:
{
auto& namedVar = static_cast<ShaderNodes::InputVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetInputCount(); ++i)
{
const auto& input = m_shader.GetInput(i);
if (input.name == namedVar.name)
{
TypeMustMatch(input.type, namedVar.type);
return;
}
}
throw AstError{ "Input not found" };
}
case ShaderNodes::VariableType::LocalVariable:
{
auto& localVar = static_cast<ShaderNodes::LocalVariable&>(*node.var);
const auto& vars = m_context->declaredLocals;
auto it = std::find_if(vars.begin(), vars.end(), [&](const auto& var) { return var.name == localVar.name; });
if (it == vars.end())
throw AstError{ "Local variable not found in this block" };
TypeMustMatch(it->type, localVar.type);
break;
}
case ShaderNodes::VariableType::OutputVariable:
{
auto& outputVar = static_cast<ShaderNodes::OutputVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetOutputCount(); ++i)
{
const auto& input = m_shader.GetOutput(i);
if (input.name == outputVar.name)
{
TypeMustMatch(input.type, outputVar.type);
return;
}
}
throw AstError{ "Output not found" };
}
case ShaderNodes::VariableType::ParameterVariable:
{
assert(m_context->currentFunction);
auto& parameter = static_cast<ShaderNodes::ParameterVariable&>(*node.var);
const auto& parameters = m_context->currentFunction->parameters;
auto it = std::find_if(parameters.begin(), parameters.end(), [&](const auto& parameter) { return parameter.name == parameter.name; });
if (it == parameters.end())
throw AstError{ "Parameter not found in function" };
TypeMustMatch(it->type, parameter.type);
break;
}
case ShaderNodes::VariableType::UniformVariable:
{
auto& uniformVar = static_cast<ShaderNodes::UniformVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetUniformCount(); ++i)
{
const auto& uniform = m_shader.GetUniform(i);
if (uniform.name == uniformVar.name)
{
TypeMustMatch(uniform.type, uniformVar.type);
return;
}
}
throw AstError{ "Uniform not found" };
}
default:
break;
}
}
void ShaderValidator::Visit(const NamedVariable& node)
void ShaderValidator::Visit(const ShaderNodes::IntrinsicCall& node)
{
if (node.name.empty())
throw AstError{ "Variable has empty name" };
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
case ShaderNodes::IntrinsicType::DotProduct:
{
if (node.parameters.size() != 2)
throw AstError { "Expected 2 parameters" };
for (auto& param : node.parameters)
MandatoryNode(param);
ShaderNodes::ExpressionType type = node.parameters.front()->GetExpressionType();
for (std::size_t i = 1; i < node.parameters.size(); ++i)
{
if (type != node.parameters[i]->GetExpressionType())
throw AstError{ "All type must match" };
}
break;
}
}
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
{
if (node.parameters[0]->GetExpressionType() != ShaderNodes::ExpressionType::Float3)
throw AstError{ "CrossProduct only works with Float3 expressions" };
break;
}
case ShaderNodes::IntrinsicType::DotProduct:
break;
}
for (auto& param : node.parameters)
Visit(param);
}
void ShaderValidator::Visit(const Sample2D& node)
void ShaderValidator::Visit(const ShaderNodes::Sample2D& node)
{
if (MandatoryExpr(node.sampler)->GetExpressionType() != ExpressionType::Sampler2D)
if (MandatoryExpr(node.sampler)->GetExpressionType() != ShaderNodes::ExpressionType::Sampler2D)
throw AstError{ "Sampler must be a Sampler2D" };
if (MandatoryExpr(node.coordinates)->GetExpressionType() != ExpressionType::Float2)
if (MandatoryExpr(node.coordinates)->GetExpressionType() != ShaderNodes::ExpressionType::Float2)
throw AstError{ "Coordinates must be a Float2" };
Visit(node.sampler);
Visit(node.coordinates);
}
void ShaderValidator::Visit(const StatementBlock& node)
void ShaderValidator::Visit(const ShaderNodes::StatementBlock& node)
{
assert(m_context);
m_context->blockLocalIndex.push_back(m_context->declaredLocals.size());
for (const auto& statement : node.statements)
Visit(MandatoryNode(statement));
assert(m_context->declaredLocals.size() >= m_context->blockLocalIndex.back());
m_context->declaredLocals.resize(m_context->blockLocalIndex.back());
m_context->blockLocalIndex.pop_back();
}
void ShaderValidator::Visit(const SwizzleOp& node)
void ShaderValidator::Visit(const ShaderNodes::SwizzleOp& node)
{
if (node.componentCount > 4)
throw AstError{ "Cannot swizzle more than four elements" };
switch (MandatoryExpr(node.expression)->GetExpressionType())
{
case ExpressionType::Float1:
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
case ShaderNodes::ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float2:
case ShaderNodes::ExpressionType::Float3:
case ShaderNodes::ExpressionType::Float4:
break;
default:
@@ -234,9 +393,9 @@ namespace Nz::ShaderAst
Visit(node.expression);
}
bool Validate(const StatementPtr& shader, std::string* error)
bool ValidateShader(const ShaderAst& shader, std::string* error)
{
ShaderValidator validator;
return validator.Validate(shader, error);
ShaderValidator validator(shader);
return validator.Validate(error);
}
}

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
ShaderVarVisitor::~ShaderVarVisitor() = default;
void ShaderVarVisitor::Visit(const ShaderNodes::VariablePtr& node)
{
node->Visit(*this);
}
}

View File

@@ -0,0 +1,77 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderVariables.hpp>
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
ShaderNodes::Variable::~Variable() = default;
VariableType BuiltinVariable::GetType() const
{
return VariableType::BuiltinVariable;
}
void BuiltinVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType InputVariable::GetType() const
{
return VariableType::InputVariable;
}
void InputVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType LocalVariable::GetType() const
{
return VariableType::LocalVariable;
}
void LocalVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType OutputVariable::GetType() const
{
return VariableType::OutputVariable;
}
void OutputVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType ParameterVariable::GetType() const
{
return VariableType::ParameterVariable;
}
void ParameterVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType UniformVariable::GetType() const
{
return VariableType::UniformVariable;
}
void UniformVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
}

View File

@@ -9,7 +9,7 @@ namespace Nz
{
ShaderVisitor::~ShaderVisitor() = default;
void ShaderVisitor::EnableCondition(const String& name, bool cond)
void ShaderVisitor::EnableCondition(const std::string& name, bool cond)
{
if (cond)
m_conditions.insert(name);
@@ -17,12 +17,12 @@ namespace Nz
m_conditions.erase(name);
}
bool ShaderVisitor::IsConditionEnabled(const String& name) const
bool ShaderVisitor::IsConditionEnabled(const std::string& name) const
{
return m_conditions.count(name) != 0;
}
void ShaderVisitor::Visit(const ShaderAst::NodePtr& node)
void ShaderVisitor::Visit(const ShaderNodes::NodePtr& node)
{
node->Visit(*this);
}

View File

@@ -7,4 +7,5 @@
namespace Nz
{
ShaderWriter::~ShaderWriter() = default;
}

View File

@@ -19,7 +19,7 @@ class CastVec : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@@ -49,7 +49,7 @@ void CastVec<ToComponentCount>::BuildNodeEdition(QFormLayout* layout)
}
template<std::size_t ToComponentCount>
Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(m_input);
assert(count == 1);
@@ -60,7 +60,7 @@ Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::Shader
{
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
std::array<Nz::ShaderAst::ExpressionPtr, 4> expr;
std::array<Nz::ShaderNodes::ExpressionPtr, 4> expr;
expr[0] = expressions[0];
for (std::size_t i = 0; i < overflowComponentCount; ++i)
expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
@@ -71,13 +71,13 @@ Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::Shader
}
else if (ToComponentCount < fromComponentCount)
{
std::array<Nz::ShaderAst::SwizzleComponent, ToComponentCount> swizzleComponents;
std::array<Nz::ShaderNodes::SwizzleComponent, ToComponentCount> swizzleComponents;
for (std::size_t i = 0; i < ToComponentCount; ++i)
swizzleComponents[i] = static_cast<Nz::ShaderAst::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderAst::SwizzleComponent::First) + i);
swizzleComponents[i] = static_cast<Nz::ShaderNodes::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderNodes::SwizzleComponent::First) + i);
return std::apply([&](auto... components)
{
std::initializer_list<Nz::ShaderAst::SwizzleComponent> componentList{ components... };
std::initializer_list<Nz::ShaderNodes::SwizzleComponent> componentList{ components... };
return Nz::ShaderBuilder::Swizzle(expressions[0], componentList);
}, swizzleComponents);
}

View File

@@ -71,7 +71,7 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Value"), spinbox);
}
Nz::ShaderAst::ExpressionPtr FloatValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr FloatValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);

View File

@@ -28,7 +28,7 @@ class FloatValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
private:
bool ComputePreview(QPixmap& pixmap) override;

View File

@@ -107,7 +107,7 @@ void InputValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Input"), inputSelection);
}
Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);
@@ -116,22 +116,22 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (inputEntry.type)
{
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled input type");
}();
return Nz::ShaderBuilder::Input(inputEntry.name, expression);
return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, expression));
}
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
@@ -145,7 +145,7 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
switch (inputEntry.type)
{
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
//case InputType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1:
return FloatData::Type();

View File

@@ -19,7 +19,7 @@ class InputValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Input"; }
QString name() const override { return "Input"; }

View File

@@ -51,10 +51,10 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Output"), outputSelection);
}
Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
using namespace Nz::ShaderAst;
using namespace Nz::ShaderBuilder;
using namespace Nz::ShaderNodes;
assert(count == 1);
@@ -63,22 +63,22 @@ Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::Expressio
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (outputEntry.type)
{
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled output type");
}();
auto output = Nz::ShaderBuilder::Output(outputEntry.name, expression);
auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, expression));
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
}
@@ -94,8 +94,8 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes:
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
switch (outputEntry.type)
{
//case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
//case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
//case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
//case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2:
case InOutType::Float3:
case InOutType::Float4:

View File

@@ -16,7 +16,7 @@ class OutputValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override { return "Output"; }
QString name() const override { return "Output"; }

View File

@@ -91,7 +91,7 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap)
return true;
}
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(m_texture);
assert(m_uv);

View File

@@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode
SampleTexture(ShaderGraph& graph);
~SampleTexture() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Sample texture"; }
QString name() const override { return "SampleTexture"; }

View File

@@ -4,7 +4,7 @@
#define NAZARA_SHADERNODES_SHADERNODE_HPP
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeDataModel>
#include <QtGui/QPixmap>
#include <optional>
@@ -23,7 +23,7 @@ class ShaderNode : public QtNodes::NodeDataModel
inline void DisablePreview();
void EnablePreview(bool enable = true);
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
virtual Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const = 0;
inline ShaderGraph& GetGraph();
inline const ShaderGraph& GetGraph() const;
inline const std::string& GetVariableName() const;

View File

@@ -106,7 +106,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Texture"), textureSelection);
}
Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr TextureValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
if (!m_currentTextureIndex)
throw std::runtime_error("invalid texture input");
@@ -115,18 +115,18 @@ Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::Expressi
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (textureEntry.type)
{
case TextureType::Sampler2D: return Nz::ShaderAst::ExpressionType::Sampler2D;
case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D;
}
assert(false);
throw std::runtime_error("Unhandled texture type");
}();
return Nz::ShaderBuilder::Uniform(textureEntry.name, expression);
return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Uniform(textureEntry.name, expression));
}
auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType

View File

@@ -18,7 +18,7 @@ class TextureValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Texture"; }
QString name() const override { return "Texture"; }

View File

@@ -6,14 +6,14 @@
#include <ShaderNode/DataModels/ShaderNode.hpp>
#include <ShaderNode/DataTypes/VecData.hpp>
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
class VecBinOp : public ShaderNode
{
public:
VecBinOp(ShaderGraph& graph);
~VecBinOp() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
unsigned int nPorts(QtNodes::PortType portType) const override;
@@ -37,10 +37,10 @@ class VecBinOp : public ShaderNode
std::shared_ptr<VecData> m_output;
};
class VecAdd : public VecBinOp<Nz::ShaderAst::BinaryType::Add>
class VecAdd : public VecBinOp<Nz::ShaderNodes::BinaryType::Add>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Add>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Add>::VecBinOp;
QString caption() const override;
QString name() const override;
@@ -48,10 +48,10 @@ class VecAdd : public VecBinOp<Nz::ShaderAst::BinaryType::Add>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecMul : public VecBinOp<Nz::ShaderAst::BinaryType::Multiply>
class VecMul : public VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Multiply>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>::VecBinOp;
QString caption() const override;
QString name() const override;
@@ -59,10 +59,10 @@ class VecMul : public VecBinOp<Nz::ShaderAst::BinaryType::Multiply>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecSub : public VecBinOp<Nz::ShaderAst::BinaryType::Substract>
class VecSub : public VecBinOp<Nz::ShaderNodes::BinaryType::Substract>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Substract>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Substract>::VecBinOp;
QString caption() const override;
QString name() const override;
@@ -70,10 +70,10 @@ class VecSub : public VecBinOp<Nz::ShaderAst::BinaryType::Substract>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecDiv : public VecBinOp<Nz::ShaderAst::BinaryType::Divide>
class VecDiv : public VecBinOp<Nz::ShaderNodes::BinaryType::Divide>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Divide>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Divide>::VecBinOp;
QString caption() const override;
QString name() const override;

View File

@@ -1,15 +1,15 @@
#include <ShaderNode/DataModels/VecBinOp.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
VecBinOp<BinOp>::VecBinOp(ShaderGraph& graph) :
ShaderNode(graph)
{
UpdateOutput();
}
template<Nz::ShaderAst::BinaryType BinOp>
Nz::ShaderAst::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
template<Nz::ShaderNodes::BinaryType BinOp>
Nz::ShaderNodes::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
@@ -17,7 +17,7 @@ Nz::ShaderAst::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderAst::Expre
return builder(expressions[0], expressions[1]);
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
{
assert(portIndex == 0 || portIndex == 1);
@@ -25,7 +25,7 @@ QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/,
return VecData::Type();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
{
switch (portType)
@@ -37,14 +37,14 @@ unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
return 0;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
std::shared_ptr<QtNodes::NodeData> VecBinOp<BinOp>::outData(QtNodes::PortIndex port)
{
assert(port == 0);
return m_output;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
{
assert(index == 0 || index == 1);
@@ -65,7 +65,7 @@ void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int in
UpdateOutput();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QtNodes::NodeValidationState VecBinOp<BinOp>::validationState() const
{
if (!m_lhs || !m_rhs)
@@ -77,7 +77,7 @@ QtNodes::NodeValidationState VecBinOp<BinOp>::validationState() const
return QtNodes::NodeValidationState::Valid;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QString VecBinOp<BinOp>::validationMessage() const
{
if (!m_lhs || !m_rhs)
@@ -89,7 +89,7 @@ QString VecBinOp<BinOp>::validationMessage() const
return QString();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
{
if (!m_lhs || !m_rhs)
@@ -99,7 +99,7 @@ bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
return true;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
void VecBinOp<BinOp>::UpdateOutput()
{
if (validationState() != QtNodes::NodeValidationState::Valid)

View File

@@ -1,5 +1,5 @@
#include <ShaderNode/DataModels/VecDot.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
VecDot::VecDot(ShaderGraph& graph) :
ShaderNode(graph)
@@ -8,11 +8,11 @@ ShaderNode(graph)
UpdateOutput();
}
Nz::ShaderAst::ExpressionPtr VecDot::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecDot::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using namespace Nz::ShaderAst;
return BinaryFunc::Build(BinaryIntrinsic::DotProduct, expressions[0], expressions[1]);
using namespace Nz::ShaderNodes;
return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] });
}
QString VecDot::caption() const

View File

@@ -13,7 +13,7 @@ class VecDot : public ShaderNode
VecDot(ShaderGraph& graph);
~VecDot() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@@ -1,5 +1,5 @@
#include <ShaderNode/DataModels/VecFloatMul.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
VecFloatMul::VecFloatMul(ShaderGraph& graph) :
ShaderNode(graph)
@@ -7,10 +7,10 @@ ShaderNode(graph)
UpdateOutput();
}
Nz::ShaderAst::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using namespace Nz::ShaderAst;
using namespace Nz::ShaderNodes;
return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]);
}

View File

@@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode
VecFloatMul(ShaderGraph& graph);
~VecFloatMul() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@@ -29,7 +29,7 @@ class VecValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
private:
bool ComputePreview(QPixmap& pixmap) override;

View File

@@ -94,7 +94,7 @@ void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
}
template<std::size_t ComponentCount>
Nz::ShaderAst::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);

View File

@@ -3,7 +3,7 @@
#ifndef NAZARA_SHADERNODES_TEXTUREDATA_HPP
#define NAZARA_SHADERNODES_TEXTUREDATA_HPP
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeData>
#include <QtGui/QImage>

View File

@@ -2,13 +2,13 @@
#include <cassert>
#include <stdexcept>
Nz::ShaderAst::ExpressionType VecData::GetExpressionType() const
Nz::ShaderNodes::ExpressionType VecData::GetExpressionType() const
{
switch (componentCount)
{
case 2: return Nz::ShaderAst::ExpressionType::Float2;
case 3: return Nz::ShaderAst::ExpressionType::Float3;
case 4: return Nz::ShaderAst::ExpressionType::Float4;
case 2: return Nz::ShaderNodes::ExpressionType::Float2;
case 3: return Nz::ShaderNodes::ExpressionType::Float3;
case 4: return Nz::ShaderNodes::ExpressionType::Float4;
default:
break;
}

View File

@@ -3,7 +3,7 @@
#ifndef NAZARA_SHADERNODES_VECDATA_HPP
#define NAZARA_SHADERNODES_VECDATA_HPP
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeData>
#include <QtGui/QImage>
@@ -13,7 +13,7 @@ struct VecData : public QtNodes::NodeData
inline QtNodes::NodeDataType type() const override;
Nz::ShaderAst::ExpressionType GetExpressionType() const;
Nz::ShaderNodes::ExpressionType GetExpressionType() const;
static inline QtNodes::NodeDataType Type();
@@ -27,28 +27,28 @@ struct VecExpressionTypeHelper;
template<>
struct VecExpressionTypeHelper<1>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float1;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float1;
};
template<>
struct VecExpressionTypeHelper<2>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float2;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float2;
};
template<>
struct VecExpressionTypeHelper<3>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float3;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float3;
};
template<>
struct VecExpressionTypeHelper<4>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float4;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float4;
};
template<std::size_t N> constexpr Nz::ShaderAst::ExpressionType VecExpressionType = VecExpressionTypeHelper<N>::template ExpressionType;
template<std::size_t N> constexpr Nz::ShaderNodes::ExpressionType VecExpressionType = VecExpressionTypeHelper<N>::template ExpressionType;
struct VecTypeDummy {};

View File

@@ -46,9 +46,9 @@ m_flowScene(BuildRegistry())
});
// Test
AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0);
AddOutput("RenderTarget0", InOutType::Float4);
AddTexture("Potato", TextureType::Sampler2D);
AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0, 0);
AddOutput("RenderTarget0", InOutType::Float4, 0);
AddTexture("Potato", TextureType::Sampler2D, 1);
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
@@ -79,10 +79,11 @@ ShaderGraph::~ShaderGraph()
m_flowScene.clearScene();
}
std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex)
std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
{
std::size_t index = m_inputs.size();
auto& inputEntry = m_inputs.emplace_back();
inputEntry.locationIndex = locationIndex;
inputEntry.name = std::move(name);
inputEntry.role = role;
inputEntry.roleIndex = roleIndex;
@@ -93,10 +94,11 @@ std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole ro
return index;
}
std::size_t ShaderGraph::AddOutput(std::string name, InOutType type)
std::size_t ShaderGraph::AddOutput(std::string name, InOutType type, std::size_t locationIndex)
{
std::size_t index = m_outputs.size();
auto& outputEntry = m_outputs.emplace_back();
outputEntry.locationIndex = locationIndex;
outputEntry.name = std::move(name);
outputEntry.type = type;
@@ -105,10 +107,11 @@ std::size_t ShaderGraph::AddOutput(std::string name, InOutType type)
return index;
}
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type)
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type, std::size_t bindingIndex)
{
std::size_t index = m_textures.size();
auto& textureEntry = m_textures.emplace_back();
textureEntry.bindingIndex = bindingIndex;
textureEntry.name = std::move(name);
textureEntry.type = type;
@@ -141,6 +144,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject inputDoc = inputDocRef.toObject();
InputEntry& input = m_inputs.emplace_back();
input.locationIndex = static_cast<std::size_t>(inputDoc["locationIndex"].toInt(0));
input.name = inputDoc["name"].toString().toStdString();
input.role = DecodeEnum<InputRole>(inputDoc["role"].toString().toStdString()).value();
input.roleIndex = static_cast<std::size_t>(inputDoc["roleIndex"].toInt(0));
@@ -155,6 +159,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject outputDoc = outputDocRef.toObject();
OutputEntry& output = m_outputs.emplace_back();
output.locationIndex = static_cast<std::size_t>(outputDoc["locationIndex"].toInt(0));
output.name = outputDoc["name"].toString().toStdString();
output.type = DecodeEnum<InOutType>(outputDoc["type"].toString().toStdString()).value();
}
@@ -167,6 +172,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject textureDoc = textureDocRef.toObject();
TextureEntry& texture = m_textures.emplace_back();
texture.bindingIndex = static_cast<std::size_t>(textureDoc["bindingIndex"].toInt(0));
texture.name = textureDoc["name"].toString().toStdString();
texture.type = DecodeEnum<TextureType>(textureDoc["type"].toString().toStdString()).value();
}
@@ -189,6 +195,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& input : m_inputs)
{
QJsonObject inputDoc;
inputDoc["locationIndex"] = int(input.locationIndex);
inputDoc["name"] = QString::fromStdString(input.name);
inputDoc["role"] = QString(EnumToString(input.role));
inputDoc["roleIndex"] = int(input.roleIndex);
@@ -204,6 +211,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& output : m_outputs)
{
QJsonObject outputDoc;
outputDoc["locationIndex"] = int(output.locationIndex);
outputDoc["name"] = QString::fromStdString(output.name);
outputDoc["type"] = QString(EnumToString(output.type));
@@ -217,6 +225,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& texture : m_textures)
{
QJsonObject textureDoc;
textureDoc["bindingIndex"] = int(texture.bindingIndex);
textureDoc["name"] = QString::fromStdString(texture.name);
textureDoc["type"] = QString(EnumToString(texture.type));
@@ -247,9 +256,9 @@ QJsonObject ShaderGraph::Save()
return sceneJson;
}
Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
{
std::vector<Nz::ShaderAst::StatementPtr> statements;
std::vector<Nz::ShaderNodes::StatementPtr> statements;
QHash<QUuid, unsigned int> usageCount;
std::function<void(QtNodes::Node*)> DetectVariables;
@@ -278,13 +287,13 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
DetectVariables(node);
});
QHash<QUuid, Nz::ShaderAst::ExpressionPtr> variableExpressions;
QHash<QUuid, Nz::ShaderNodes::ExpressionPtr> variableExpressions;
unsigned int varCount = 0;
std::unordered_set<std::string> usedVariableNames;
std::function<Nz::ShaderAst::ExpressionPtr(QtNodes::Node*)> HandleNode;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
std::function<Nz::ShaderNodes::ExpressionPtr(QtNodes::Node*)> HandleNode;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderNodes::ExpressionPtr
{
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid)
@@ -298,7 +307,7 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
assert(it != usageCount.end());
std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In);
Nz::StackArray<Nz::ShaderAst::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount);
Nz::StackArray<Nz::ShaderNodes::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderNodes::ExpressionPtr, inputCount);
std::size_t i = 0;
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
@@ -316,8 +325,8 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
const std::string& variableName = shaderNode->GetVariableName();
if (*it > 1 || !variableName.empty())
{
Nz::ShaderAst::ExpressionPtr varExpression;
if (expression->GetExpressionCategory() == Nz::ShaderAst::ExpressionCategory::RValue)
Nz::ShaderNodes::ExpressionPtr varExpression;
if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue)
{
std::string name;
if (variableName.empty())
@@ -330,10 +339,10 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
usedVariableNames.insert(name);
auto variable = Nz::ShaderBuilder::Variable(std::move(name), expression->GetExpressionType());
auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType());
statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, expression));
varExpression = variable;
varExpression = Nz::ShaderBuilder::Identifier(variable);
}
else
varExpression = expression;
@@ -354,13 +363,14 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
}
});
return Nz::ShaderAst::StatementBlock::Build(std::move(statements));
return Nz::ShaderNodes::StatementBlock::Build(std::move(statements));
}
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex)
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
{
assert(inputIndex < m_inputs.size());
auto& inputEntry = m_inputs[inputIndex];
inputEntry.locationIndex = locationIndex;
inputEntry.name = std::move(name);
inputEntry.role = role;
inputEntry.roleIndex = roleIndex;
@@ -369,10 +379,11 @@ void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutTyp
OnInputUpdate(this, inputIndex);
}
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type)
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex)
{
assert(outputIndex < m_outputs.size());
auto& outputEntry = m_outputs[outputIndex];
outputEntry.locationIndex = locationIndex;
outputEntry.name = std::move(name);
outputEntry.type = type;

View File

@@ -4,7 +4,7 @@
#define NAZARA_SHADERNODES_SHADERGRAPH_HPP
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/FlowScene>
#include <ShaderNode/Enums.hpp>
#include <ShaderNode/Previews/PreviewModel.hpp>
@@ -23,9 +23,9 @@ class ShaderGraph
ShaderGraph();
~ShaderGraph();
std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex);
std::size_t AddOutput(std::string name, InOutType type);
std::size_t AddTexture(std::string name, TextureType type);
std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
std::size_t AddOutput(std::string name, InOutType type, std::size_t locationIndex);
std::size_t AddTexture(std::string name, TextureType type, std::size_t bindingIndex);
void Clear();
@@ -44,14 +44,15 @@ class ShaderGraph
void Load(const QJsonObject& data);
QJsonObject Save();
Nz::ShaderAst::StatementPtr ToAst();
Nz::ShaderNodes::StatementPtr ToAst();
void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex);
void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type);
void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex);
void UpdateTexturePreview(std::size_t texture, QImage preview);
struct InputEntry
{
std::size_t locationIndex;
std::size_t roleIndex;
std::string name;
InputRole role;
@@ -60,12 +61,14 @@ class ShaderGraph
struct OutputEntry
{
std::size_t locationIndex;
std::string name;
InOutType type;
};
struct TextureEntry
{
std::size_t bindingIndex;
std::string name;
TextureType type;
QImage preview;

View File

@@ -23,6 +23,8 @@ QDialog(parent)
for (std::size_t i = 0; i < InputRoleCount; ++i)
m_roleList->addItem(EnumToString(static_cast<InputRole>(i)));
m_locationIndex = new QSpinBox;
m_roleIndex = new QSpinBox;
QFormLayout* formLayout = new QFormLayout;
@@ -30,6 +32,7 @@ QDialog(parent)
formLayout->addRow(tr("Type"), m_typeList);
formLayout->addRow(tr("Role"), m_roleList);
formLayout->addRow(tr("Role index"), m_roleIndex);
formLayout->addRow(tr("Input index"), m_locationIndex);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &InputEditDialog::OnAccept);
@@ -46,6 +49,7 @@ InputEditDialog::InputEditDialog(const InputInfo& input, QWidget* parent) :
InputEditDialog(parent)
{
m_inputName->setText(QString::fromStdString(input.name));
m_locationIndex->setValue(int(input.locationIndex));
m_roleIndex->setValue(int(input.roleIndex));
m_roleList->setCurrentText(EnumToString(input.role));
m_typeList->setCurrentText(EnumToString(input.type));
@@ -54,6 +58,7 @@ InputEditDialog(parent)
InputInfo InputEditDialog::GetInputInfo() const
{
InputInfo inputInfo;
inputInfo.locationIndex = static_cast<std::size_t>(m_locationIndex->value());
inputInfo.name = m_inputName->text().toStdString();
inputInfo.role = static_cast<InputRole>(m_roleList->currentIndex());
inputInfo.roleIndex = static_cast<std::size_t>(m_roleIndex->value());

View File

@@ -12,6 +12,7 @@ class QSpinBox;
struct InputInfo
{
std::size_t locationIndex;
std::size_t roleIndex;
std::string name;
InputRole role;
@@ -33,6 +34,7 @@ class InputEditDialog : public QDialog
QComboBox* m_roleList;
QComboBox* m_typeList;
QLineEdit* m_inputName;
QSpinBox* m_locationIndex;
QSpinBox* m_roleIndex;
};

View File

@@ -39,7 +39,7 @@ void InputEditor::OnAddInput()
connect(dialog, &QDialog::accepted, [this, dialog]
{
InputInfo inputInfo = dialog->GetInputInfo();
m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex);
});
dialog->open();
@@ -60,7 +60,7 @@ void InputEditor::OnEditInput(int inputIndex)
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
{
InputInfo inputInfo = dialog->GetInputInfo();
m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex);
});
dialog->open();

View File

@@ -1,5 +1,7 @@
#include <ShaderNode/Widgets/MainWindow.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Renderer/GlslWriter.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <ShaderNode/Widgets/InputEditor.hpp>
#include <ShaderNode/Widgets/OutputEditor.hpp>
@@ -84,8 +86,6 @@ void MainWindow::BuildMenu()
QMenu* shader = menu->addMenu(tr("&Shader"));
{
QtNodes::FlowScene* scene = &m_shaderGraph.GetScene();
QAction* loadShader = shader->addAction(tr("Load..."));
QObject::connect(loadShader, &QAction::triggered, this, &MainWindow::OnLoad);
QAction* saveShader = shader->addAction(tr("Save..."));
@@ -101,8 +101,52 @@ void MainWindow::OnCompileToGLSL()
{
try
{
Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst();
Nz::File file("shader.shader", Nz::OpenMode_WriteOnly);
file.Write(Nz::ShaderNodes::Serialize(shaderAst));
//TODO: Put in another function
auto GetExpressionFromInOut = [&] (InOutType type)
{
switch (type)
{
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled input type");
};
auto GetExpressionFromTexture = [&](TextureType type)
{
switch (type)
{
case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D;
}
assert(false);
throw std::runtime_error("Unhandled texture type");
};
Nz::ShaderAst shader;
for (const auto& input : m_shaderGraph.GetInputs())
shader.AddInput(input.name, GetExpressionFromInOut(input.type), input.locationIndex);
for (const auto& output : m_shaderGraph.GetOutputs())
shader.AddOutput(output.name, GetExpressionFromInOut(output.type), output.locationIndex);
for (const auto& uniform : m_shaderGraph.GetTextures())
shader.AddUniform(uniform.name, GetExpressionFromTexture(uniform.type), uniform.bindingIndex);
shader.AddFunction("main", shaderAst);
Nz::GlslWriter writer;
Nz::String glsl = writer.Generate(m_shaderGraph.ToAst());
Nz::String glsl = writer.Generate(shader);
std::cout << glsl << std::endl;

View File

@@ -4,6 +4,7 @@
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
OutputEditDialog::OutputEditDialog(QWidget* parent) :
@@ -18,9 +19,12 @@ QDialog(parent)
for (std::size_t i = 0; i < InOutTypeCount; ++i)
m_typeList->addItem(EnumToString(static_cast<InOutType>(i)));
m_locationIndex = new QSpinBox;
QFormLayout* formLayout = new QFormLayout;
formLayout->addRow(tr("Name"), m_outputName);
formLayout->addRow(tr("Type"), m_typeList);
formLayout->addRow(tr("Output index"), m_locationIndex);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &OutputEditDialog::OnAccept);
@@ -33,16 +37,18 @@ QDialog(parent)
setLayout(verticalLayout);
}
OutputEditDialog::OutputEditDialog(const OutputInfo& input, QWidget* parent) :
OutputEditDialog::OutputEditDialog(const OutputInfo& output, QWidget* parent) :
OutputEditDialog(parent)
{
m_outputName->setText(QString::fromStdString(input.name));
m_typeList->setCurrentText(EnumToString(input.type));
m_locationIndex->setValue(int(output.locationIndex));
m_outputName->setText(QString::fromStdString(output.name));
m_typeList->setCurrentText(EnumToString(output.type));
}
OutputInfo OutputEditDialog::GetOutputInfo() const
{
OutputInfo inputInfo;
inputInfo.locationIndex = static_cast<std::size_t>(m_locationIndex->value());
inputInfo.name = m_outputName->text().toStdString();
inputInfo.type = static_cast<InOutType>(m_typeList->currentIndex());

View File

@@ -8,9 +8,11 @@
class QComboBox;
class QLineEdit;
class QSpinBox;
struct OutputInfo
{
std::size_t locationIndex;
std::string name;
InOutType type;
};
@@ -19,7 +21,7 @@ class OutputEditDialog : public QDialog
{
public:
OutputEditDialog(QWidget* parent = nullptr);
OutputEditDialog(const OutputInfo& input, QWidget* parent = nullptr);
OutputEditDialog(const OutputInfo& output, QWidget* parent = nullptr);
~OutputEditDialog() = default;
OutputInfo GetOutputInfo() const;
@@ -29,6 +31,7 @@ class OutputEditDialog : public QDialog
QComboBox* m_typeList;
QLineEdit* m_outputName;
QSpinBox* m_locationIndex;
};
#include <ShaderNode/Widgets/OutputEditDialog.inl>

View File

@@ -38,8 +38,8 @@ void OutputEditor::OnAddOutput()
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog]
{
OutputInfo inputInfo = dialog->GetOutputInfo();
m_shaderGraph.AddOutput(std::move(inputInfo.name), inputInfo.type);
OutputInfo outputInfo = dialog->GetOutputInfo();
m_shaderGraph.AddOutput(std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex);
});
dialog->open();
@@ -57,8 +57,8 @@ void OutputEditor::OnEditOutput(int inputIndex)
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
{
OutputInfo inputInfo = dialog->GetOutputInfo();
m_shaderGraph.UpdateOutput(inputIndex, std::move(inputInfo.name), inputInfo.type);
OutputInfo outputInfo = dialog->GetOutputInfo();
m_shaderGraph.UpdateOutput(inputIndex, std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex);
});
dialog->open();