From 3225c43ea43c9254ec094eb9f801a1a978f167c1 Mon Sep 17 00:00:00 2001 From: Lee Kerley Date: Tue, 5 Aug 2025 14:59:52 -0700 Subject: [PATCH] Introduce more concrete API calls to MaterialXCore, to help make the inteface to Shader Generation more direct. Functions added to access the "bsdf" attribute on a nodedef element, to access the "sourcecode" attribute on an implementation element. Also use MaterialXCode API calls in favor of more generic getAttribute(attrName) calls. --- source/MaterialXCore/Definition.cpp | 2 + source/MaterialXCore/Definition.h | 46 +++++++++++++++++++ source/MaterialXCore/Element.h | 22 +++++++++ .../MaterialXGenMdl/Nodes/CustomNodeMdl.cpp | 4 +- .../Nodes/SourceCodeNode.cpp | 6 +-- source/MaterialXGenShader/ShaderGraph.cpp | 6 +-- source/MaterialXGenShader/ShaderNode.cpp | 6 +-- 7 files changed, 81 insertions(+), 11 deletions(-) diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp index da6c3ca3af..bebf36861c 100644 --- a/source/MaterialXCore/Definition.cpp +++ b/source/MaterialXCore/Definition.cpp @@ -23,11 +23,13 @@ const string NodeDef::TRANSLATION_NODE_GROUP = "translation"; const string NodeDef::NODE_ATTRIBUTE = "node"; const string NodeDef::NODE_GROUP_ATTRIBUTE = "nodegroup"; +const string NodeDef::BSDF_ATTRIBUTE = "bsdf"; const string TypeDef::SEMANTIC_ATTRIBUTE = "semantic"; const string TypeDef::CONTEXT_ATTRIBUTE = "context"; const string Implementation::FILE_ATTRIBUTE = "file"; const string Implementation::FUNCTION_ATTRIBUTE = "function"; const string Implementation::NODE_GRAPH_ATTRIBUTE = "nodegraph"; +const string Implementation::SOURCE_CODE_ATTRIBUTE = "sourcecode"; const string UnitDef::UNITTYPE_ATTRIBUTE = "unittype"; const string AttributeDef::ATTRNAME_ATTRIBUTE = "attrname"; const string AttributeDef::VALUE_ATTRIBUTE = "value"; diff --git a/source/MaterialXCore/Definition.h b/source/MaterialXCore/Definition.h index 0ce7761b6d..edab688100 100644 --- a/source/MaterialXCore/Definition.h +++ b/source/MaterialXCore/Definition.h @@ -133,6 +133,28 @@ class MX_CORE_API NodeDef : public InterfaceElement return getAttribute(NODE_GROUP_ATTRIBUTE); } + /// @} + /// @name BSDF attribute + /// @{ + + /// Set the bsdf attribute of the NodeDef. + void setBSDF(const string& bsdf) + { + setAttribute(BSDF_ATTRIBUTE, bsdf); + } + + /// Return true if the given NodeDef has a bsdf attribute. + bool hasBSDF() const + { + return hasAttribute(BSDF_ATTRIBUTE); + } + + /// Return the bsdf attribute of the NodeDef. + const string& getBSDF() const + { + return getAttribute(BSDF_ATTRIBUTE); + } + /// @} /// @name Implementation References /// @{ @@ -180,6 +202,7 @@ class MX_CORE_API NodeDef : public InterfaceElement static const string CATEGORY; static const string NODE_ATTRIBUTE; static const string NODE_GROUP_ATTRIBUTE; + static const string BSDF_ATTRIBUTE; static const string TEXTURE_NODE_GROUP; static const string PROCEDURAL_NODE_GROUP; @@ -249,6 +272,28 @@ class MX_CORE_API Implementation : public InterfaceElement return getAttribute(FUNCTION_ATTRIBUTE); } + /// @} + /// @name Source Code String + /// @{ + + /// Set the source code string for the Implementation. + void setSourceCode(const string& function) + { + setAttribute(SOURCE_CODE_ATTRIBUTE, function); + } + + /// Return true if the given Implementation has a source code string. + bool hasSourceCode() const + { + return hasAttribute(SOURCE_CODE_ATTRIBUTE); + } + + /// Return the source code string for the Implementation. + const string& getSourceCode() const + { + return getAttribute(SOURCE_CODE_ATTRIBUTE); + } + /// @} /// @name Nodegraph String /// @{ @@ -304,6 +349,7 @@ class MX_CORE_API Implementation : public InterfaceElement static const string FILE_ATTRIBUTE; static const string FUNCTION_ATTRIBUTE; static const string NODE_GRAPH_ATTRIBUTE; + static const string SOURCE_CODE_ATTRIBUTE; }; /// @class TypeDef diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index 89f5c87152..f5eae97d2d 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -1010,6 +1010,28 @@ class MX_CORE_API ValueElement : public TypedElement return getAttribute(IMPLEMENTATION_NAME_ATTRIBUTE); } + /// @} + /// @name Enum Names + /// @{ + + /// Set the enum names of an element. + void setEnumNames(const string& enumNames) + { + setAttribute(ENUM_ATTRIBUTE, enumNames); + } + + /// Return true if the given element has enum names. + bool hasEnumNames() const + { + return hasAttribute(ENUM_ATTRIBUTE); + } + + /// Return the enum names of an element. + const string& getEnumNames() const + { + return getAttribute(ENUM_ATTRIBUTE); + } + /// @} /// @name Typed Value /// @{ diff --git a/source/MaterialXGenMdl/Nodes/CustomNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/CustomNodeMdl.cpp index 7215b90256..2e5666f23b 100644 --- a/source/MaterialXGenMdl/Nodes/CustomNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/CustomNodeMdl.cpp @@ -60,7 +60,7 @@ void CustomCodeNodeMdl::initializeForInlineSourceCode(const InterfaceElement& el const Implementation& impl = static_cast(element); // Store the inline source because the `_functionSource` is used for the function call template string // that matched the regular MaterialX to MDL function mapping. - _inlineSourceCode = impl.getAttribute("sourcecode"); + _inlineSourceCode = impl.getSourceCode(); if (_inlineSourceCode.empty()) { throw ExceptionShaderGenError("No source code was specified for the implementation '" + impl.getName() + "'"); @@ -92,7 +92,7 @@ void CustomCodeNodeMdl::initializeForExternalSourceCode(const InterfaceElement& // Map `file` to a qualified MDL module name const Implementation& impl = static_cast(element); - string moduleName = impl.getAttribute("file"); + string moduleName = impl.getFile(); if (moduleName.empty()) { throw ExceptionShaderGenError("No source file was specified for the implementation '" + impl.getName() + "'"); diff --git a/source/MaterialXGenShader/Nodes/SourceCodeNode.cpp b/source/MaterialXGenShader/Nodes/SourceCodeNode.cpp index 07e1a54f2f..dc9f1fbb26 100644 --- a/source/MaterialXGenShader/Nodes/SourceCodeNode.cpp +++ b/source/MaterialXGenShader/Nodes/SourceCodeNode.cpp @@ -31,7 +31,7 @@ void SourceCodeNode::resolveSourceCode(const InterfaceElement& element, GenConte const Implementation& impl = static_cast(element); FilePath localPath = FilePath(impl.getActiveSourceUri()).getParentPath(); - _sourceFilename = context.resolveSourceFile(impl.getAttribute("file"), localPath); + _sourceFilename = context.resolveSourceFile(impl.getFile(), localPath); _functionSource = readFile(_sourceFilename); if (_functionSource.empty()) { @@ -52,7 +52,7 @@ void SourceCodeNode::initialize(const InterfaceElement& element, GenContext& con const Implementation& impl = static_cast(element); // Get source code from either an attribute or a file. - _functionSource = impl.getAttribute("sourcecode"); + _functionSource = impl.getSourceCode(); if (_functionSource.empty()) { resolveSourceCode(element, context); @@ -60,7 +60,7 @@ void SourceCodeNode::initialize(const InterfaceElement& element, GenContext& con // Find the function name to use // If no function is given the source will be inlined. - _functionName = impl.getAttribute("function"); + _functionName = impl.getFunction(); _inlined = _functionName.empty(); if (!_inlined) diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 5658de328c..306e4bdba3 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -37,7 +37,7 @@ void ShaderGraph::addInputSockets(const InterfaceElement& elem, GenContext& cont ValuePtr portValue = input->getResolvedValue(); const string& portValueString = portValue ? portValue->getValueString() : EMPTY_STRING; std::pair enumResult; - const string& enumNames = input->getAttribute(ValueElement::ENUM_ATTRIBUTE); + const string& enumNames = input->getEnumNames(); const TypeDesc portType = context.getTypeDesc(input->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(portValueString, portType, enumNames, enumResult)) { @@ -245,7 +245,7 @@ void ShaderGraph::addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geom if (spaceInput && nodeDefSpaceInput) { std::pair enumResult; - const string& enumNames = nodeDefSpaceInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); + const string& enumNames = nodeDefSpaceInput->getEnumNames(); const TypeDesc portType = context.getTypeDesc(nodeDefSpaceInput->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(space, portType, enumNames, enumResult)) { @@ -589,7 +589,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name const string& valueString = value->getValueString(); std::pair enumResult; const TypeDesc type = context.getTypeDesc(nodedefInput->getType()); - const string& enumNames = nodedefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); + const string& enumNames = nodedefInput->getEnumNames(); if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) { inputSocket->setValue(enumResult.second); diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 73f56b17e6..a85942fe8d 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -195,7 +195,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, ShaderInput* input; const string& portValue = port->getResolvedValueString(); std::pair enumResult; - const string& enumNames = port->getAttribute(ValueElement::ENUM_ATTRIBUTE); + const string& enumNames = port->getEnumNames(); if (context.getShaderGenerator().getSyntax().remapEnumeration(portValue, portType, enumNames, enumResult)) { input = newNode->addInput(port->getName(), enumResult.first); @@ -263,7 +263,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, newNode->_classification = Classification::BSDF | Classification::CLOSURE; // Add additional classifications for BSDF reflection and/or transmission. - const string& bsdfType = nodeDef.getAttribute("bsdf"); + const string& bsdfType = nodeDef.getBSDF(); if (bsdfType == BSDF_R) { newNode->_classification |= Classification::BSDF_R; @@ -358,7 +358,7 @@ void ShaderNode::initialize(const Node& node, const NodeDef& nodeDef, GenContext // We explicitly check the valueString is not empty before checking the enumeration, // because otherwise the enumeration value would always return nullptr std::pair enumResult; - const string& enumNames = nodeDefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); + const string& enumNames = nodeDefInput->getEnumNames(); const TypeDesc type = context.getTypeDesc(nodeDefInput->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) {