Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

297 lines
8.8 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXGenShader/Syntax.h>
#include <MaterialXGenShader/TypeDesc.h>
#include <MaterialXGenShader/ShaderGenerator.h>
#include <MaterialXGenShader/GenContext.h>
#include <MaterialXCore/Value.h>
MATERIALX_NAMESPACE_BEGIN
const string Syntax::NEWLINE = "\n";
const string Syntax::SEMICOLON = ";";
const string Syntax::COMMA = ",";
const string Syntax::INDENTATION = " ";
const string Syntax::STRING_QUOTE = "\"";
const string Syntax::INCLUDE_STATEMENT = "#include";
const string Syntax::SINGLE_LINE_COMMENT = "// ";
const string Syntax::BEGIN_MULTI_LINE_COMMENT = "/* ";
const string Syntax::END_MULTI_LINE_COMMENT = " */";
const std::unordered_map<char, size_t> Syntax::CHANNELS_MAPPING =
{
{ 'r', 0 }, { 'x', 0 },
{ 'g', 1 }, { 'y', 1 },
{ 'b', 2 }, { 'z', 2 },
{ 'a', 3 }, { 'w', 3 }
};
//
// Syntax methods
//
Syntax::Syntax(TypeSystemPtr typeSystem) :
_typeSystem(typeSystem)
{
}
void Syntax::registerTypeSyntax(TypeDesc type, TypeSyntaxPtr syntax)
{
auto it = _typeSyntaxIndexByType.find(type);
if (it != _typeSyntaxIndexByType.end())
{
_typeSyntaxes[it->second] = syntax;
}
else
{
_typeSyntaxes.push_back(syntax);
_typeSyntaxIndexByType[type] = _typeSyntaxes.size() - 1;
}
// Make this type a restricted name
registerReservedWords({ syntax->getName() });
}
void Syntax::registerReservedWords(const StringSet& names)
{
_reservedWords.insert(names.begin(), names.end());
}
void Syntax::registerInvalidTokens(const StringMap& tokens)
{
_invalidTokens.insert(tokens.begin(), tokens.end());
}
/// Returns the type syntax object for a named type.
/// Throws an exception if a type syntax is not defined for the given type.
const TypeSyntax& Syntax::getTypeSyntax(TypeDesc type) const
{
auto it = _typeSyntaxIndexByType.find(type);
if (it == _typeSyntaxIndexByType.end())
{
throw ExceptionShaderGenError("No syntax is defined for the given type '" + type.getName() + "'.");
}
return *_typeSyntaxes[it->second];
}
string Syntax::getValue(const ShaderPort* port, bool uniform) const
{
const TypeSyntax& syntax = getTypeSyntax(port->getType());
return syntax.getValue(port, uniform);
}
string Syntax::getValue(TypeDesc type, const Value& value, bool uniform) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
return syntax.getValue(value, uniform);
}
const string& Syntax::getDefaultValue(TypeDesc type, bool uniform) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
return syntax.getDefaultValue(uniform);
}
const string& Syntax::getTypeName(TypeDesc type) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
return syntax.getName();
}
string Syntax::getOutputTypeName(TypeDesc type) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
const string& outputModifier = getOutputQualifier();
return outputModifier.size() ? outputModifier + " " + syntax.getName() : syntax.getName();
}
const string& Syntax::getTypeAlias(TypeDesc type) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
return syntax.getTypeAlias();
}
const string& Syntax::getTypeDefinition(TypeDesc type) const
{
const TypeSyntax& syntax = getTypeSyntax(type);
return syntax.getTypeDefinition();
}
bool Syntax::typeSupported(const TypeDesc*) const
{
return true;
}
string Syntax::getArrayVariableSuffix(TypeDesc type, const Value& value) const
{
if (type.isArray())
{
if (value.isA<vector<float>>())
{
const size_t size = value.asA<vector<float>>().size();
return "[" + std::to_string(size) + "]";
}
else if (value.isA<vector<int>>())
{
const size_t size = value.asA<vector<int>>().size();
return "[" + std::to_string(size) + "]";
}
}
return string();
}
static bool isInvalidChar(char c)
{
return !isalnum(c) && c != '_';
}
void Syntax::makeValidName(string& name) const
{
std::replace_if(name.begin(), name.end(), isInvalidChar, '_');
name = replaceSubstrings(name, _invalidTokens);
}
void Syntax::makeIdentifier(string& name, IdentifierMap& identifiers) const
{
makeValidName(name);
auto it = identifiers.find(name);
if (it != identifiers.end())
{
// Name is not unique so append the counter and keep
// incrementing until a unique name is found.
string name2;
do
{
name2 = name + std::to_string(it->second++);
} while (identifiers.count(name2));
name = name2;
}
// Save it among the known identifiers.
identifiers[name] = 1;
}
string Syntax::getVariableName(const string& name, TypeDesc /*type*/, IdentifierMap& identifiers) const
{
// Default implementation just makes an identifier, but derived
// classes can override this for custom variable naming.
string variable = name;
makeIdentifier(variable, identifiers);
return variable;
}
bool Syntax::remapEnumeration(const string&, TypeDesc, const string&, std::pair<TypeDesc, ValuePtr>&) const
{
return false;
}
StructTypeSyntaxPtr Syntax::createStructSyntax(const string& structTypeName, const string& defaultValue,
const string& uniformDefaultValue, const string& typeAlias,
const string& typeDefinition) const
{
return std::make_shared<StructTypeSyntax>(
this,
structTypeName,
defaultValue,
uniformDefaultValue,
typeAlias,
typeDefinition);
}
const StringVec TypeSyntax::EMPTY_MEMBERS;
TypeSyntax::TypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue,
const string& typeAlias, const string& typeDefinition, const StringVec& members) :
_parent(parent),
_name(name),
_defaultValue(defaultValue),
_uniformDefaultValue(uniformDefaultValue),
_typeAlias(typeAlias),
_typeDefinition(typeDefinition),
_members(members)
{
}
string TypeSyntax::getValue(const ShaderPort* port, bool uniform) const
{
if (!port || !port->getValue())
{
return getDefaultValue(uniform);
}
return getValue(*port->getValue(), uniform);
}
ScalarTypeSyntax::ScalarTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue,
const string& typeAlias, const string& typeDefinition) :
TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, EMPTY_MEMBERS)
{
}
string ScalarTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
{
return value.getValueString();
}
StringTypeSyntax::StringTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue,
const string& typeAlias, const string& typeDefinition) :
ScalarTypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition)
{
}
string StringTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
{
return "\"" + value.getValueString() + "\"";
}
AggregateTypeSyntax::AggregateTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue,
const string& typeAlias, const string& typeDefinition, const StringVec& members) :
TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members)
{
}
string AggregateTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
{
const string valueString = value.getValueString();
return valueString.empty() ? valueString : getName() + "(" + valueString + ")";
}
StructTypeSyntax::StructTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue,
const string& typeAlias, const string& typeDefinition, const StringVec& members) :
TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members)
{
}
string StructTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
{
const AggregateValue& aggValue = static_cast<const AggregateValue&>(value);
string result = "{";
string separator = "";
for (const auto& memberValue : aggValue.getMembers())
{
result += separator;
separator = ";";
const string& memberTypeName = memberValue->getTypeString();
TypeDesc memberTypeDesc = _parent->getType(memberTypeName);
// Recursively use the syntax to generate the output, so we can support nested structs.
const string valueStr = _parent->getValue(memberTypeDesc, *memberValue, true);
result += valueStr;
}
result += "}";
return result;
}
MATERIALX_NAMESPACE_END