Shader: Add initial support for options (WIP)

This commit is contained in:
Jérôme Leclercq
2021-04-17 14:43:00 +02:00
parent 7da02c8708
commit 87ce2edc6e
45 changed files with 586 additions and 113 deletions

View File

@@ -28,7 +28,8 @@ namespace Nz::ShaderLang
{ "builtin", ShaderAst::AttributeType::Builtin },
{ "entry", ShaderAst::AttributeType::Entry },
{ "layout", ShaderAst::AttributeType::Layout },
{ "location", ShaderAst::AttributeType::Location },
{ "location", ShaderAst::AttributeType::Location },
{ "opt", ShaderAst::AttributeType::Option },
};
std::unordered_map<std::string, ShaderStageType> s_entryPoints = {
@@ -90,6 +91,13 @@ namespace Nz::ShaderLang
assert(attributes.empty());
attributes = ParseAttributes();
break;
case TokenType::Option:
if (!attributes.empty())
throw UnexpectedToken{};
context.root->statements.push_back(ParseOptionDeclaration());
break;
case TokenType::FunctionDeclaration:
context.root->statements.push_back(ParseFunctionDeclaration(std::move(attributes)));
@@ -450,14 +458,15 @@ namespace Nz::ShaderLang
Expect(Advance(), TokenType::ClosingCurlyBracket);
std::optional<ShaderStageType> entryPoint;
auto func = ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
for (const auto& [attributeType, arg] : attributes)
{
switch (attributeType)
{
case ShaderAst::AttributeType::Entry:
{
if (entryPoint)
if (func->entryStage)
throw AttributeError{ "attribute entry must be present once" };
if (!std::holds_alternative<std::string>(arg))
@@ -469,7 +478,19 @@ namespace Nz::ShaderLang
if (it == s_entryPoints.end())
throw AttributeError{ ("invalid parameter " + argStr + " for entry attribute").c_str() };
entryPoint = it->second;
func->entryStage = it->second;
break;
}
case ShaderAst::AttributeType::Option:
{
if (!func->optionName.empty())
throw AttributeError{ "attribute option must be present once" };
if (!std::holds_alternative<std::string>(arg))
throw AttributeError{ "attribute option requires a string parameter" };
func->optionName = std::get<std::string>(arg);
break;
}
@@ -477,8 +498,8 @@ namespace Nz::ShaderLang
throw AttributeError{ "unhandled attribute for function" };
}
}
return ShaderBuilder::DeclareFunction(entryPoint, std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
return func;
}
ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter()
@@ -492,6 +513,29 @@ namespace Nz::ShaderLang
return { parameterName, parameterType };
}
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
{
Expect(Advance(), TokenType::Option);
std::string optionName = ParseIdentifierAsName();
Expect(Advance(), TokenType::Colon);
ShaderAst::ExpressionType optionType = ParseType();
ShaderAst::ExpressionPtr initialValue;
if (Peek().type == TokenType::Assign)
{
Consume();
initialValue = ParseExpression();
}
Expect(Advance(), TokenType::Semicolon);
return ShaderBuilder::DeclareOption(std::move(optionName), std::move(optionType), std::move(initialValue));
}
ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector<ShaderAst::Attribute> attributes)
{
Expect(Advance(), TokenType::Struct);
@@ -871,12 +915,35 @@ namespace Nz::ShaderLang
break;
case TokenType::OpenParenthesis:
return ParseParenthesisExpression();
case TokenType::SelectOpt:
return ParseSelectOptExpression();
default:
throw UnexpectedToken{};
}
}
ShaderAst::ExpressionPtr Parser::ParseSelectOptExpression()
{
Expect(Advance(), TokenType::SelectOpt);
Expect(Advance(), TokenType::OpenParenthesis);
std::string optionName = ParseIdentifierAsName();
Expect(Advance(), TokenType::Comma);
ShaderAst::ExpressionPtr trueExpr = ParseExpression();
Expect(Advance(), TokenType::Comma);
ShaderAst::ExpressionPtr falseExpr = ParseExpression();
Expect(Advance(), TokenType::ClosingParenthesis);
return ShaderBuilder::SelectOption(std::move(optionName), std::move(trueExpr), std::move(falseExpr));
}
ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType()
{