Shader: Add support for depth_write and early_fragment_tests attributes (+ FragDepth builtin)

This commit is contained in:
Jérôme Leclercq
2021-06-01 12:32:24 +02:00
parent 465837ff12
commit 16e2f5f819
12 changed files with 456 additions and 136 deletions

View File

@@ -11,7 +11,14 @@
namespace Nz::ShaderLang
{
namespace
{
{
std::unordered_map<std::string, ShaderAst::DepthWriteMode> s_depthWriteModes = {
{ "greater", ShaderAst::DepthWriteMode::Greater },
{ "less", ShaderAst::DepthWriteMode::Less },
{ "replace", ShaderAst::DepthWriteMode::Replace },
{ "unchanged", ShaderAst::DepthWriteMode::Unchanged },
};
std::unordered_map<std::string, ShaderAst::PrimitiveType> s_identifierToBasicType = {
{ "bool", ShaderAst::PrimitiveType::Boolean },
{ "i32", ShaderAst::PrimitiveType::Int32 },
@@ -20,12 +27,14 @@ namespace Nz::ShaderLang
};
std::unordered_map<std::string, ShaderAst::AttributeType> s_identifierToAttributeType = {
{ "binding", ShaderAst::AttributeType::Binding },
{ "builtin", ShaderAst::AttributeType::Builtin },
{ "entry", ShaderAst::AttributeType::Entry },
{ "layout", ShaderAst::AttributeType::Layout },
{ "location", ShaderAst::AttributeType::Location },
{ "opt", ShaderAst::AttributeType::Option },
{ "binding", ShaderAst::AttributeType::Binding },
{ "builtin", ShaderAst::AttributeType::Builtin },
{ "depth_write", ShaderAst::AttributeType::DepthWrite },
{ "early_fragment_tests", ShaderAst::AttributeType::EarlyFragmentTests },
{ "entry", ShaderAst::AttributeType::Entry },
{ "layout", ShaderAst::AttributeType::Layout },
{ "location", ShaderAst::AttributeType::Location },
{ "opt", ShaderAst::AttributeType::Option },
};
std::unordered_map<std::string, ShaderStageType> s_entryPoints = {
@@ -35,6 +44,7 @@ namespace Nz::ShaderLang
std::unordered_map<std::string, ShaderAst::BuiltinEntry> s_builtinMapping = {
{ "fragcoord", ShaderAst::BuiltinEntry::FragCoord },
{ "fragdepth", ShaderAst::BuiltinEntry::FragDepth },
{ "position", ShaderAst::BuiltinEntry::VertexPosition }
};
@@ -483,11 +493,55 @@ namespace Nz::ShaderLang
for (const auto& [attributeType, arg] : attributes)
{
switch (attributeType)
{
{
case ShaderAst::AttributeType::DepthWrite:
{
if (func->depthWrite)
throw AttributeError{ "attribute depth_write can only be present once" };
if (!std::holds_alternative<std::string>(arg))
throw AttributeError{ "attribute entry requires a string parameter" };
const std::string& argStr = std::get<std::string>(arg);
auto it = s_depthWriteModes.find(argStr);
if (it == s_depthWriteModes.end())
throw AttributeError{ ("invalid parameter " + argStr + " for depth_write attribute").c_str() };
func->depthWrite = it->second;
break;
}
case ShaderAst::AttributeType::EarlyFragmentTests:
{
if (func->earlyFragmentTests)
throw AttributeError{ "attribute early_fragment_tests can only be present once" };
if (std::holds_alternative<std::string>(arg))
{
const std::string& argStr = std::get<std::string>(arg);
if (argStr == "true" || argStr == "on")
func->earlyFragmentTests = true;
else if (argStr == "false" || argStr == "off")
func->earlyFragmentTests = false;
else
throw AttributeError{ "expected boolean value (got " + argStr + ")" };
}
else if (std::holds_alternative<std::monostate>(arg))
{
// No parameter, default to true
func->earlyFragmentTests = true;
}
else
throw AttributeError{ "unexpected value for early_fragment_tests" };
break;
}
case ShaderAst::AttributeType::Entry:
{
if (func->entryStage)
throw AttributeError{ "attribute entry must be present once" };
throw AttributeError{ "attribute entry can only be present once" };
if (!std::holds_alternative<std::string>(arg))
throw AttributeError{ "attribute entry requires a string parameter" };