Shader: Many fixes

This commit is contained in:
Jérôme Leclercq
2022-03-04 18:23:01 +01:00
parent 1919bd3302
commit a2f4f3c802
13 changed files with 161 additions and 84 deletions

View File

@@ -333,7 +333,7 @@ namespace Nz::ShaderAst
{
m_stream << s_magicNumber << s_currentVersion;
m_stream << module.shaderLangVersion;
m_stream << module.metadata->shaderLangVersion;
Serialize(*module.rootNode);
m_stream.FlushBits();
@@ -531,7 +531,10 @@ namespace Nz::ShaderAst
ModulePtr module = std::make_shared<Module>();
m_stream >> module->shaderLangVersion;
std::shared_ptr<Module::Metadata> metadata = std::make_shared<Module::Metadata>();
m_stream >> metadata->shaderLangVersion;
module->metadata = std::move(metadata);
module->rootNode = ShaderBuilder::MultiStatement();
ShaderSerializerVisitor visitor(*this);

View File

@@ -115,7 +115,7 @@ namespace Nz::ShaderAst
ModulePtr SanitizeVisitor::Sanitize(const Module& module, const Options& options, std::string* error)
{
ModulePtr clone = std::make_shared<Module>();
clone->shaderLangVersion = module.shaderLangVersion;
clone->metadata = module.metadata;
Context currentContext;
currentContext.options = options;

View File

@@ -298,7 +298,7 @@ namespace Nz
}
}
void GlslWriter::Append(const ShaderAst::MethodType& methodType)
void GlslWriter::Append(const ShaderAst::MethodType& /*methodType*/)
{
throw std::runtime_error("unexpected method type");
}
@@ -311,6 +311,7 @@ namespace Nz
case ShaderAst::PrimitiveType::Float32: return Append("float");
case ShaderAst::PrimitiveType::Int32: return Append("int");
case ShaderAst::PrimitiveType::UInt32: return Append("uint");
case ShaderAst::PrimitiveType::String: throw std::runtime_error("unexpected string constant");
}
}
@@ -324,6 +325,8 @@ namespace Nz
case ShaderAst::PrimitiveType::Int32: Append("i"); break;
case ShaderAst::PrimitiveType::UInt32: Append("u"); break;
case ShaderAst::PrimitiveType::String: throw std::runtime_error("unexpected string type");
}
Append("sampler");
@@ -363,6 +366,7 @@ namespace Nz
case ShaderAst::PrimitiveType::Float32: break;
case ShaderAst::PrimitiveType::Int32: Append("i"); break;
case ShaderAst::PrimitiveType::UInt32: Append("u"); break;
case ShaderAst::PrimitiveType::String: throw std::runtime_error("unexpected string type");
}
Append("vec");
@@ -1201,6 +1205,11 @@ namespace Nz
Append(";");
}
void GlslWriter::Visit(ShaderAst::ImportStatement& /*node*/)
{
/* nothing to do */
}
void GlslWriter::Visit(ShaderAst::MultiStatement& node)
{
AppendStatementList(node.statements);

View File

@@ -75,14 +75,7 @@ namespace Nz
inline bool HasValue() const { return locationIndex.HasValue(); }
};
struct LangWriter::NzslAttribute
{
const ShaderAst::ExpressionValue<UInt32>& version;
inline bool HasValue() const { return version.HasValue(); }
};
struct LangWriter::SetAttribute
{
const ShaderAst::ExpressionValue<UInt32>& setIndex;
@@ -100,6 +93,7 @@ namespace Nz
struct LangWriter::State
{
const States* states = nullptr;
ShaderAst::Module* module;
std::stringstream stream;
std::unordered_map<std::size_t, std::string> constantNames;
std::unordered_map<std::size_t, ShaderAst::StructDescription*> structs;
@@ -118,6 +112,7 @@ namespace Nz
});
ShaderAst::ModulePtr sanitizedModule = ShaderAst::Sanitize(module);
state.module = sanitizedModule.get();
AppendHeader();
@@ -195,6 +190,7 @@ namespace Nz
case ShaderAst::PrimitiveType::Float32: return Append("f32");
case ShaderAst::PrimitiveType::Int32: return Append("i32");
case ShaderAst::PrimitiveType::UInt32: return Append("u32");
case ShaderAst::PrimitiveType::String: return Append("string");
}
}
@@ -459,11 +455,7 @@ namespace Nz
Append(")");
}
void LangWriter::AppendAttribute(NzslAttribute nzslVersion)
{
}
void LangWriter::AppendAttribute(SetAttribute set)
{
if (!set.HasValue())
@@ -1101,6 +1093,23 @@ namespace Nz
void LangWriter::AppendHeader()
{
// Nothing yet
UInt32 shaderLangVersion = m_currentState->module->metadata->shaderLangVersion;
UInt32 majorVersion = shaderLangVersion / 100;
shaderLangVersion -= majorVersion * 100;
UInt32 minorVersion = shaderLangVersion / 10;
shaderLangVersion -= minorVersion * 100;
UInt32 patchVersion = shaderLangVersion;
// nzsl_version
Append("[nzsl_version(\"", majorVersion, ".", minorVersion);
if (patchVersion != 0)
Append(".", patchVersion);
AppendLine("\")]");
AppendLine("module;");
AppendLine();
}
}

View File

@@ -230,6 +230,78 @@ namespace Nz::ShaderLang
return attributes;
}
void Parser::ParseModuleStatement(std::vector<ShaderAst::ExprValue> attributes)
{
Expect(Advance(), TokenType::Module);
if (m_context->module)
throw DuplicateModule{ "you must set one module statement per file" };
std::optional<UInt32> moduleVersion;
for (auto&& [attributeType, arg] : attributes)
{
switch (attributeType)
{
case ShaderAst::AttributeType::LangVersion:
{
// Version parsing
if (moduleVersion.has_value())
throw AttributeError{ "attribute " + std::string("nzsl_version") + " must be present once" };
if (!arg)
throw AttributeError{ "attribute " + std::string("nzsl_version") + " requires a parameter"};
const ShaderAst::ExpressionPtr& expr = *arg;
if (expr->GetType() != ShaderAst::NodeType::ConstantValueExpression)
throw AttributeError{ "attribute " + std::string("nzsl_version") + " expect a single string parameter" };
auto& constantValue = SafeCast<ShaderAst::ConstantValueExpression&>(*expr);
if (ShaderAst::GetExpressionType(constantValue.value) != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::String })
throw AttributeError{ "attribute " + std::string("nzsl_version") + " expect a single string parameter" };
const std::string& versionStr = std::get<std::string>(constantValue.value);
std::regex versionRegex(R"(^(\d+)(\.(\d+)(\.(\d+))?)?$)", std::regex::ECMAScript);
std::smatch versionMatch;
if (!std::regex_match(versionStr, versionMatch, versionRegex))
throw AttributeError("invalid version for attribute nzsl");
assert(versionMatch.size() == 6);
std::uint32_t version = 0;
version += std::stoi(versionMatch[1]) * 100;
if (versionMatch.length(3) > 0)
version += std::stoi(versionMatch[3]) * 10;
if (versionMatch.length(5) > 0)
version += std::stoi(versionMatch[5]) * 1;
moduleVersion = version;
break;
}
default:
throw AttributeError{ "unhandled attribute for module" };
}
}
if (!moduleVersion.has_value())
throw AttributeError{ "missing module version" };
m_context->module = std::make_shared<ShaderAst::Module>();
m_context->module->rootNode = ShaderBuilder::MultiStatement();
std::shared_ptr<ShaderAst::Module::Metadata> moduleMetadata = std::make_shared<ShaderAst::Module::Metadata>();
moduleMetadata->shaderLangVersion = *moduleVersion;
m_context->module->metadata = std::move(moduleMetadata);
Expect(Advance(), TokenType::Semicolon);
}
void Parser::ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type, ShaderAst::ExpressionPtr& initialValue)
{
name = ParseIdentifierAsName();
@@ -564,71 +636,13 @@ namespace Nz::ShaderLang
return { parameterName, std::move(parameterType) };
}
void Parser::ParseModuleStatement(std::vector<ShaderAst::ExprValue> attributes)
{
Expect(Advance(), TokenType::Module);
if (m_context->module)
throw DuplicateModule{ "you must set one module statement per file" };
std::optional<UInt32> moduleVersion;
for (auto&& [attributeType, arg] : attributes)
{
switch (attributeType)
{
case ShaderAst::AttributeType::LangVersion:
{
// Version parsing
if (moduleVersion.has_value())
throw AttributeError{ "attribute " + std::string("nzsl_version") + " must be present once" };
if (!arg)
throw AttributeError{ "attribute " + std::string("nzsl_version") + " requires a parameter"};
const ShaderAst::ExpressionPtr& expr = *arg;
if (expr->GetType() != ShaderAst::NodeType::ConstantValueExpression)
throw AttributeError{ "attribute " + std::string("nzsl_version") + " expect a single string parameter" };
auto& constantValue = SafeCast<ShaderAst::ConstantValueExpression&>(*expr);
if (ShaderAst::GetExpressionType(constantValue.value) != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::String })
throw AttributeError{ "attribute " + std::string("nzsl_version") + " expect a single string parameter" };
const std::string& versionStr = std::get<std::string>(constantValue.value);
std::regex versionRegex(R"(^(\d+)(\.(\d+)(\.(\d+))?)?$)", std::regex::ECMAScript);
std::smatch versionMatch;
if (!std::regex_match(versionStr, versionMatch, versionRegex))
throw AttributeError("invalid version for attribute nzsl");
assert(versionMatch.size() == 6);
std::uint32_t version = 0;
version += std::stoi(versionMatch[1]) * 100;
if (versionMatch.length(3) > 0)
version += std::stoi(versionMatch[3]) * 10;
if (versionMatch.length(5) > 0)
version += std::stoi(versionMatch[5]) * 1;
moduleVersion = version;
break;
}
default:
throw AttributeError{ "unhandled attribute for module" };
}
}
if (!moduleVersion.has_value())
throw AttributeError{ "missing module version" };
m_context->module = std::make_shared<ShaderAst::Module>();
m_context->module->rootNode = ShaderBuilder::MultiStatement();
m_context->module->shaderLangVersion = *moduleVersion;
Expect(Advance(), TokenType::Semicolon);
}

View File

@@ -106,6 +106,7 @@ namespace Nz
return SpirvOp::OpIAdd;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -124,6 +125,7 @@ namespace Nz
return SpirvOp::OpISub;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -144,6 +146,7 @@ namespace Nz
return SpirvOp::OpUDiv;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -197,7 +200,8 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
return SpirvOp::OpIMul;
default:
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -217,6 +221,9 @@ namespace Nz
case ShaderAst::PrimitiveType::Int32:
case ShaderAst::PrimitiveType::UInt32:
return SpirvOp::OpIEqual;
case ShaderAst::PrimitiveType::String:
break;
}
break;
@@ -236,6 +243,7 @@ namespace Nz
return SpirvOp::OpUGreaterThan;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -256,6 +264,7 @@ namespace Nz
return SpirvOp::OpUGreaterThanEqual;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -276,6 +285,7 @@ namespace Nz
return SpirvOp::OpULessThanEqual;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -296,6 +306,7 @@ namespace Nz
return SpirvOp::OpULessThan;
case ShaderAst::PrimitiveType::Boolean:
case ShaderAst::PrimitiveType::String:
break;
}
@@ -315,6 +326,9 @@ namespace Nz
case ShaderAst::PrimitiveType::Int32:
case ShaderAst::PrimitiveType::UInt32:
return SpirvOp::OpINotEqual;
case ShaderAst::PrimitiveType::String:
break;
}
break;
@@ -482,6 +496,9 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
castOp = SpirvOp::OpConvertUToF;
break;
case ShaderAst::PrimitiveType::String:
throw std::runtime_error("unexpected string type");
}
break;
}
@@ -503,6 +520,9 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
castOp = SpirvOp::OpSConvert;
break;
case ShaderAst::PrimitiveType::String:
throw std::runtime_error("unexpected string type");
}
break;
}
@@ -524,9 +544,15 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
break; //< Already handled
case ShaderAst::PrimitiveType::String:
throw std::runtime_error("unexpected string type");
}
break;
}
case ShaderAst::PrimitiveType::String:
throw std::runtime_error("unexpected string type");
}
assert(castOp);
@@ -809,6 +835,9 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
op = (node.intrinsic == ShaderAst::IntrinsicType::Max) ? GLSLstd450UMax : GLSLstd450UMin;
break;
case ShaderAst::PrimitiveType::String:
throw std::runtime_error("unexpected string type");
}
UInt32 firstParam = EvaluateExpression(node.parameters[0]);

View File

@@ -725,6 +725,9 @@ namespace Nz
case ShaderAst::PrimitiveType::UInt32:
return Integer{ 32, false };
case ShaderAst::PrimitiveType::String:
break;
}
throw std::runtime_error("unexpected type");