diff --git a/javascript/MaterialXTest/browser/shaderGenerator.spec.js b/javascript/MaterialXTest/browser/shaderGenerator.spec.js index df44297d46..7ca1d74b32 100644 --- a/javascript/MaterialXTest/browser/shaderGenerator.spec.js +++ b/javascript/MaterialXTest/browser/shaderGenerator.spec.js @@ -34,17 +34,17 @@ describe('Generate Shaders', function () const generators = [] if (typeof mx.EsslShaderGenerator != 'undefined') - generators.push(new mx.EsslShaderGenerator()); + generators.push(mx.EsslShaderGenerator.create()); if (typeof mx.GlslShaderGenerator != 'undefined') - generators.push(new mx.GlslShaderGenerator()); + generators.push(mx.GlslShaderGenerator.create()); if (typeof mx.MslShaderGenerator != 'undefined') - generators.push(new mx.MslShaderGenerator()); + generators.push(mx.MslShaderGenerator.create()); if (typeof mx.OslShaderGenerator != 'undefined') - generators.push(new mx.OslShaderGenerator()); + generators.push(mx.OslShaderGenerator.create()); if (typeof mx.VkShaderGenerator != 'undefined') - generators.push(new mx.VkShaderGenerator()); + generators.push(mx.VkShaderGenerator.create()); if (typeof mx.MdlShaderGenerator != 'undefined') - generators.push(new mx.MdlShaderGenerator()); + generators.push(mx.MdlShaderGenerator.create()); const elem = mx.findRenderableElement(doc); for (let gen of generators) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index 02167b8c51..821a848ba2 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -1486,7 +1486,7 @@ export class Viewer this.mx = mtlxIn; // Initialize base document - this.generator = new this.mx.EsslShaderGenerator(); + this.generator = this.mx.EsslShaderGenerator.create(); this.genContext = new this.mx.GenContext(this.generator); this.document = this.mx.createDocument(); diff --git a/javascript/README.md b/javascript/README.md index 05c4c8a214..0fd3c00214 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -179,7 +179,7 @@ Make sure to consume `JsMaterialXGenShader.js` instead of `JsMaterialXCore.js` a #### Generating Essl Shader Code & Compiling with WebGL To generate WebGL 2 compatible shader code a generator context and an instance of the `EsslShaderGenerator` class is required. ```javascript -const gen = new mx.EsslShaderGenerator(); +const gen = mx.EsslShaderGenerator.create(); const genContext = new mx.GenContext(gen); ``` The standard libraries need to be loaded and imported into the document. This step is required as the standard libraries contain all the definitions and snippets needed for assembly of the shader code. diff --git a/python/MaterialXTest/genshader.py b/python/MaterialXTest/genshader.py index 0b541df24d..b6a81ba4b5 100644 --- a/python/MaterialXTest/genshader.py +++ b/python/MaterialXTest/genshader.py @@ -54,6 +54,7 @@ def test_ShaderInterface(self): self.assertTrue(foundTarget) context = mx_gen_shader.GenContext(shadergen) context.registerSourceCodeSearchPath(searchPath) + shadergen.registerTypeDefs(doc); # Test generator with complete mode context.getOptions().shaderInterfaceType = mx_gen_shader.ShaderInterfaceType.SHADER_INTERFACE_COMPLETE; diff --git a/python/Scripts/generateshader.py b/python/Scripts/generateshader.py index b00311eb2e..9b4cbfee9b 100644 --- a/python/Scripts/generateshader.py +++ b/python/Scripts/generateshader.py @@ -107,6 +107,7 @@ def main(): codeSearchPath.append(os.path.dirname(inputFilename)) context = mx_gen_shader.GenContext(shadergen) context.registerSourceCodeSearchPath(codeSearchPath) + shadergen.registerTypeDefs(doc); # If we're generating Vulkan-compliant GLSL then set the binding context if opts.vulkanCompliantGlsl: diff --git a/resources/Materials/TestSuite/stdlib/structs/struct_texcoord.mtlx b/resources/Materials/TestSuite/stdlib/structs/struct_texcoord.mtlx new file mode 100644 index 0000000000..f4fde221b4 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/structs/struct_texcoord.mtlx @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/structs/struct_texcoordGroup.mtlx b/resources/Materials/TestSuite/stdlib/structs/struct_texcoordGroup.mtlx new file mode 100644 index 0000000000..aa56798831 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/structs/struct_texcoordGroup.mtlx @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/JsMaterialX/JsMaterialXGenEssl/JsEsslShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenEssl/JsEsslShaderGenerator.cpp index 96e9dfac59..18f472a871 100644 --- a/source/JsMaterialX/JsMaterialXGenEssl/JsEsslShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenEssl/JsEsslShaderGenerator.cpp @@ -13,7 +13,7 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(EsslShaderGenerator) { - ems::class_>("EsslShaderGenerator") - .smart_ptr_constructor("EsslShaderGenerator", &std::make_shared) - ; + ems::class_>("EsslShaderGenerator") + .constructor() + BIND_CLASS_FUNC("create", mx::EsslShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/JsMaterialX/JsMaterialXGenGlsl/JsGlslShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenGlsl/JsGlslShaderGenerator.cpp index 311296790f..d6da5b35e3 100644 --- a/source/JsMaterialX/JsMaterialXGenGlsl/JsGlslShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenGlsl/JsGlslShaderGenerator.cpp @@ -13,7 +13,7 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(GlslShaderGenerator) { - ems::class_>("GlslShaderGenerator") - .smart_ptr_constructor("GlslShaderGenerator", &std::make_shared) - ; + ems::class_>("GlslShaderGenerator") + .constructor() + BIND_CLASS_FUNC("create", mx::GlslShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/JsMaterialX/JsMaterialXGenMdl/JsMdlShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenMdl/JsMdlShaderGenerator.cpp index 9f075a3457..ca00a51c0f 100644 --- a/source/JsMaterialX/JsMaterialXGenMdl/JsMdlShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenMdl/JsMdlShaderGenerator.cpp @@ -14,6 +14,6 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(MdlShaderGenerator) { ems::class_>("MdlShaderGenerator") - .smart_ptr_constructor("MdlShaderGenerator", &std::make_shared) - ; + .constructor() + BIND_CLASS_FUNC("create", mx::MdlShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/JsMaterialX/JsMaterialXGenMsl/JsMslShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenMsl/JsMslShaderGenerator.cpp index 38e0649ac9..533eafa3a7 100644 --- a/source/JsMaterialX/JsMaterialXGenMsl/JsMslShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenMsl/JsMslShaderGenerator.cpp @@ -13,7 +13,7 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(MslShaderGenerator) { - ems::class_>("MslShaderGenerator") - .smart_ptr_constructor("MslShaderGenerator", &std::make_shared) - ; + ems::class_>("MslShaderGenerator") + .constructor() + BIND_CLASS_FUNC("create", mx::MslShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/JsMaterialX/JsMaterialXGenOsl/JsOslShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenOsl/JsOslShaderGenerator.cpp index ebafa25363..83120954ab 100644 --- a/source/JsMaterialX/JsMaterialXGenOsl/JsOslShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenOsl/JsOslShaderGenerator.cpp @@ -14,6 +14,6 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(OslShaderGenerator) { ems::class_>("OslShaderGenerator") - .smart_ptr_constructor("OslShaderGenerator", &std::make_shared) - ; + .constructor() + BIND_CLASS_FUNC("create", mx::OslShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/JsMaterialX/JsMaterialXGenShader/JsTypeDesc.cpp b/source/JsMaterialX/JsMaterialXGenShader/JsTypeDesc.cpp index 92e1c27b69..cf16ce82c5 100644 --- a/source/JsMaterialX/JsMaterialXGenShader/JsTypeDesc.cpp +++ b/source/JsMaterialX/JsMaterialXGenShader/JsTypeDesc.cpp @@ -27,4 +27,9 @@ EMSCRIPTEN_BINDINGS(TypeDesc) .function("isAggregate", &mx::TypeDesc::isAggregate) .function("getName", &mx::TypeDesc::getName) ; + + ems::class_("TypeSystem") + .smart_ptr>("TypeSystemPtr") + .class_function("create", &mx::TypeSystem::create) + ; } diff --git a/source/JsMaterialX/JsMaterialXGenVk/JsVkShaderGenerator.cpp b/source/JsMaterialX/JsMaterialXGenVk/JsVkShaderGenerator.cpp index 191f62664c..6d24e67824 100644 --- a/source/JsMaterialX/JsMaterialXGenVk/JsVkShaderGenerator.cpp +++ b/source/JsMaterialX/JsMaterialXGenVk/JsVkShaderGenerator.cpp @@ -13,7 +13,7 @@ namespace mx = MaterialX; EMSCRIPTEN_BINDINGS(VkShaderGenerator) { - ems::class_>("VkShaderGenerator") - .smart_ptr_constructor("VkShaderGenerator", &std::make_shared) - ; + ems::class_>("VkShaderGenerator") + .constructor() + BIND_CLASS_FUNC("create", mx::VkShaderGenerator, create, 0, 1, mx::TypeSystemPtr); } diff --git a/source/MaterialXGenGlsl/EsslShaderGenerator.cpp b/source/MaterialXGenGlsl/EsslShaderGenerator.cpp index 4e3c8528d7..b9a5780245 100644 --- a/source/MaterialXGenGlsl/EsslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/EsslShaderGenerator.cpp @@ -13,10 +13,10 @@ MATERIALX_NAMESPACE_BEGIN const string EsslShaderGenerator::TARGET = "essl"; const string EsslShaderGenerator::VERSION = "300 es"; // Current target is WebGL 2.0 -EsslShaderGenerator::EsslShaderGenerator() : - GlslShaderGenerator() +EsslShaderGenerator::EsslShaderGenerator(TypeSystemPtr typeSystem) : + GlslShaderGenerator(typeSystem) { - _syntax = EsslSyntax::create(); + _syntax = EsslSyntax::create(typeSystem); // Add in ESSL specific keywords const StringSet reservedWords = { "precision", "highp", "mediump", "lowp" }; _syntax->registerReservedWords(reservedWords); diff --git a/source/MaterialXGenGlsl/EsslShaderGenerator.h b/source/MaterialXGenGlsl/EsslShaderGenerator.h index c4b5703989..f9da816055 100644 --- a/source/MaterialXGenGlsl/EsslShaderGenerator.h +++ b/source/MaterialXGenGlsl/EsslShaderGenerator.h @@ -20,9 +20,18 @@ using EsslShaderGeneratorPtr = shared_ptr; class MX_GENGLSL_API EsslShaderGenerator : public GlslShaderGenerator { public: - EsslShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + EsslShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Return a unique identifier for the target this generator is for const string& getTarget() const override { return TARGET; } diff --git a/source/MaterialXGenGlsl/EsslSyntax.cpp b/source/MaterialXGenGlsl/EsslSyntax.cpp index 8760bf1fc5..fb391645af 100644 --- a/source/MaterialXGenGlsl/EsslSyntax.cpp +++ b/source/MaterialXGenGlsl/EsslSyntax.cpp @@ -12,7 +12,7 @@ MATERIALX_NAMESPACE_BEGIN -EsslSyntax::EsslSyntax() +EsslSyntax::EsslSyntax(TypeSystemPtr typeSystem) : GlslSyntax(typeSystem) { } diff --git a/source/MaterialXGenGlsl/EsslSyntax.h b/source/MaterialXGenGlsl/EsslSyntax.h index 21e8929510..309e096477 100644 --- a/source/MaterialXGenGlsl/EsslSyntax.h +++ b/source/MaterialXGenGlsl/EsslSyntax.h @@ -17,9 +17,9 @@ MATERIALX_NAMESPACE_BEGIN class MX_GENGLSL_API EsslSyntax : public GlslSyntax { public: - EsslSyntax(); + EsslSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index 3c3a56b1d7..7a083097f7 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -41,8 +41,8 @@ const string GlslShaderGenerator::VERSION = "400"; // GlslShaderGenerator methods // -GlslShaderGenerator::GlslShaderGenerator() : - HwShaderGenerator(GlslSyntax::create()) +GlslShaderGenerator::GlslShaderGenerator(TypeSystemPtr typeSystem) : + HwShaderGenerator(typeSystem, GlslSyntax::create(typeSystem)) { // // Register all custom node implementation classes @@ -735,7 +735,7 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, throw ExceptionShaderGenError("NodeDef '" + nodedef.getName() + "' has no outputs defined"); } - const TypeDesc outputType = TypeDesc::get(outputs[0]->getType()); + const TypeDesc outputType = context.getTypeDesc(outputs[0]->getType()); if (implElement->isA()) { diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h index c3dc78b5aa..bbe24d1061 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.h +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h @@ -22,9 +22,18 @@ using GlslShaderGeneratorPtr = shared_ptr; class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator { public: - GlslShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + GlslShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Generate a shader starting from the given element, translating /// the element and all dependencies upstream into shader code. diff --git a/source/MaterialXGenGlsl/GlslSyntax.cpp b/source/MaterialXGenGlsl/GlslSyntax.cpp index 7054725b76..7abf472fc1 100644 --- a/source/MaterialXGenGlsl/GlslSyntax.cpp +++ b/source/MaterialXGenGlsl/GlslSyntax.cpp @@ -17,8 +17,8 @@ namespace class GlslStringTypeSyntax : public StringTypeSyntax { public: - GlslStringTypeSyntax() : - StringTypeSyntax("int", "0", "0") { } + GlslStringTypeSyntax(const Syntax* parent) : + StringTypeSyntax(parent, "int", "0", "0") { } string getValue(const Value& /*value*/, bool /*uniform*/) const override { @@ -29,8 +29,8 @@ class GlslStringTypeSyntax : public StringTypeSyntax class GlslArrayTypeSyntax : public ScalarTypeSyntax { public: - GlslArrayTypeSyntax(const string& name) : - ScalarTypeSyntax(name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) + GlslArrayTypeSyntax(const Syntax* parent, const string& name) : + ScalarTypeSyntax(parent, name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) { } @@ -51,8 +51,8 @@ class GlslArrayTypeSyntax : public ScalarTypeSyntax class GlslFloatArrayTypeSyntax : public GlslArrayTypeSyntax { public: - explicit GlslFloatArrayTypeSyntax(const string& name) : - GlslArrayTypeSyntax(name) + explicit GlslFloatArrayTypeSyntax(const Syntax* parent, const string& name) : + GlslArrayTypeSyntax(parent, name) { } @@ -67,8 +67,8 @@ class GlslFloatArrayTypeSyntax : public GlslArrayTypeSyntax class GlslIntegerArrayTypeSyntax : public GlslArrayTypeSyntax { public: - explicit GlslIntegerArrayTypeSyntax(const string& name) : - GlslArrayTypeSyntax(name) + explicit GlslIntegerArrayTypeSyntax(const Syntax* parent, const string& name) : + GlslArrayTypeSyntax(parent, name) { } @@ -96,7 +96,8 @@ const StringVec GlslSyntax::VEC4_MEMBERS = { ".x", ".y", ".z", ".w" }; // GlslSyntax methods // -GlslSyntax::GlslSyntax() +GlslSyntax::GlslSyntax(TypeSystemPtr typeSystem) : + Syntax(typeSystem) { // Add in all reserved words and keywords in GLSL registerReservedWords( @@ -157,6 +158,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::FLOAT, std::make_shared( + this, "float", "0.0", "0.0")); @@ -164,11 +166,13 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::FLOATARRAY, std::make_shared( + this, "float")); registerTypeSyntax( Type::INTEGER, std::make_shared( + this, "int", "0", "0")); @@ -176,11 +180,13 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::INTEGERARRAY, std::make_shared( + this, "int")); registerTypeSyntax( Type::BOOLEAN, std::make_shared( + this, "bool", "false", "false")); @@ -188,6 +194,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::COLOR3, std::make_shared( + this, "vec3", "vec3(0.0)", "vec3(0.0)", @@ -198,6 +205,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::COLOR4, std::make_shared( + this, "vec4", "vec4(0.0)", "vec4(0.0)", @@ -208,6 +216,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::VECTOR2, std::make_shared( + this, "vec2", "vec2(0.0)", "vec2(0.0)", @@ -218,6 +227,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::VECTOR3, std::make_shared( + this, "vec3", "vec3(0.0)", "vec3(0.0)", @@ -228,6 +238,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::VECTOR4, std::make_shared( + this, "vec4", "vec4(0.0)", "vec4(0.0)", @@ -238,6 +249,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::MATRIX33, std::make_shared( + this, "mat3", "mat3(1.0)", "mat3(1.0)")); @@ -245,17 +257,19 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::MATRIX44, std::make_shared( + this, "mat4", "mat4(1.0)", "mat4(1.0)")); registerTypeSyntax( Type::STRING, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( Type::FILENAME, std::make_shared( + this, "sampler2D", EMPTY_STRING, EMPTY_STRING)); @@ -263,6 +277,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::BSDF, std::make_shared( + this, "BSDF", "BSDF(vec3(0.0),vec3(1.0))", EMPTY_STRING, @@ -272,6 +287,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::EDF, std::make_shared( + this, "EDF", "EDF(0.0)", "EDF(0.0)", @@ -281,6 +297,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::VDF, std::make_shared( + this, "BSDF", "BSDF(vec3(0.0),vec3(1.0))", EMPTY_STRING)); @@ -288,6 +305,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::SURFACESHADER, std::make_shared( + this, "surfaceshader", "surfaceshader(vec3(0.0),vec3(0.0))", EMPTY_STRING, @@ -297,6 +315,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::VOLUMESHADER, std::make_shared( + this, "volumeshader", "volumeshader(vec3(0.0),vec3(0.0))", EMPTY_STRING, @@ -306,6 +325,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::DISPLACEMENTSHADER, std::make_shared( + this, "displacementshader", "displacementshader(vec3(0.0),1.0)", EMPTY_STRING, @@ -315,6 +335,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::LIGHTSHADER, std::make_shared( + this, "lightshader", "lightshader(vec3(0.0),vec3(0.0))", EMPTY_STRING, @@ -324,6 +345,7 @@ GlslSyntax::GlslSyntax() registerTypeSyntax( Type::MATERIAL, std::make_shared( + this, "material", "material(vec3(0.0),vec3(0.0))", EMPTY_STRING, @@ -401,10 +423,10 @@ string GlslStructTypeSyntax::getValue(const Value& value, bool /* uniform */) co separator = ","; const string& memberTypeName = memberValue->getTypeString(); - TypeDesc memberTypeDesc = TypeDesc::get(memberTypeName); + const TypeDesc memberTypeDesc = _parent->getType(memberTypeName); // Recursively use the syntax to generate the output, so we can supported nested structs. - result += _parentSyntax->getValue(memberTypeDesc, *memberValue, true); + result += _parent->getValue(memberTypeDesc, *memberValue, true); } result += ")"; diff --git a/source/MaterialXGenGlsl/GlslSyntax.h b/source/MaterialXGenGlsl/GlslSyntax.h index 1e82e354bd..4e4327a962 100644 --- a/source/MaterialXGenGlsl/GlslSyntax.h +++ b/source/MaterialXGenGlsl/GlslSyntax.h @@ -19,9 +19,9 @@ MATERIALX_NAMESPACE_BEGIN class MX_GENGLSL_API GlslSyntax : public Syntax { public: - GlslSyntax(); + GlslSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } const string& getInputQualifier() const override { return INPUT_QUALIFIER; } const string& getOutputQualifier() const override { return OUTPUT_QUALIFIER; } @@ -35,6 +35,10 @@ class MX_GENGLSL_API GlslSyntax : public Syntax /// the shader generator. The enumeration may be converted to a different type than the input. bool remapEnumeration(const string& value, TypeDesc type, const string& enumNames, std::pair& result) const override; + StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue, + const string& uniformDefaultValue, const string& typeAlias, + const string& typeDefinition) const override; + static const string INPUT_QUALIFIER; static const string OUTPUT_QUALIFIER; static const string UNIFORM_QUALIFIER; @@ -45,11 +49,6 @@ class MX_GENGLSL_API GlslSyntax : public Syntax static const StringVec VEC2_MEMBERS; static const StringVec VEC3_MEMBERS; static const StringVec VEC4_MEMBERS; - - protected: - StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue, - const string& uniformDefaultValue, const string& typeAlias, - const string& typeDefinition) const override; }; /// Specialization of TypeSyntax for aggregate types. diff --git a/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp index 31b1b6758b..b53a1ef7d2 100644 --- a/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/LightCompoundNodeGlsl.cpp @@ -34,7 +34,8 @@ void LightCompoundNodeGlsl::initialize(const InterfaceElement& element, GenConte NodeDefPtr nodeDef = graph.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { - _lightUniforms.add(TypeDesc::get(input->getType()), input->getName()); + const TypeDesc type = context.getTypeDesc(input->getType()); + _lightUniforms.add(type, input->getName()); } } diff --git a/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp index c7b4df2bb6..0f3fb71ef9 100644 --- a/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/LightShaderNodeGlsl.cpp @@ -44,7 +44,8 @@ void LightShaderNodeGlsl::initialize(const InterfaceElement& element, GenContext NodeDefPtr nodeDef = impl.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { - _lightUniforms.add(TypeDesc::get(input->getType()), input->getName(), input->getValue()); + const TypeDesc type = context.getTypeDesc(input->getType()); + _lightUniforms.add(type, input->getName(), input->getValue()); } } diff --git a/source/MaterialXGenGlsl/VkShaderGenerator.cpp b/source/MaterialXGenGlsl/VkShaderGenerator.cpp index 5a91d96ff5..5ce890ef90 100644 --- a/source/MaterialXGenGlsl/VkShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/VkShaderGenerator.cpp @@ -11,10 +11,10 @@ MATERIALX_NAMESPACE_BEGIN const string VkShaderGenerator::TARGET = "genglsl"; const string VkShaderGenerator::VERSION = "450"; -VkShaderGenerator::VkShaderGenerator() : - GlslShaderGenerator() +VkShaderGenerator::VkShaderGenerator(TypeSystemPtr typeSystem) : + GlslShaderGenerator(typeSystem) { - _syntax = VkSyntax::create(); + _syntax = VkSyntax::create(typeSystem); // Add in Vulkan specific keywords const StringSet reservedWords = { "texture2D", "sampler" }; _syntax->registerReservedWords(reservedWords); diff --git a/source/MaterialXGenGlsl/VkShaderGenerator.h b/source/MaterialXGenGlsl/VkShaderGenerator.h index d13957836d..8c0e809600 100644 --- a/source/MaterialXGenGlsl/VkShaderGenerator.h +++ b/source/MaterialXGenGlsl/VkShaderGenerator.h @@ -21,9 +21,18 @@ using VkShaderGeneratorPtr = shared_ptr; class MX_GENGLSL_API VkShaderGenerator : public GlslShaderGenerator { public: - VkShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + VkShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Return a unique identifier for the target this generator is for const string& getTarget() const override { return TARGET; } diff --git a/source/MaterialXGenGlsl/VkSyntax.cpp b/source/MaterialXGenGlsl/VkSyntax.cpp index 6ff52a8648..563190ad51 100644 --- a/source/MaterialXGenGlsl/VkSyntax.cpp +++ b/source/MaterialXGenGlsl/VkSyntax.cpp @@ -7,7 +7,7 @@ MATERIALX_NAMESPACE_BEGIN -VkSyntax::VkSyntax() +VkSyntax::VkSyntax(TypeSystemPtr typeSystem) : GlslSyntax(typeSystem) { } diff --git a/source/MaterialXGenGlsl/VkSyntax.h b/source/MaterialXGenGlsl/VkSyntax.h index a7d512ee95..ff0d277638 100644 --- a/source/MaterialXGenGlsl/VkSyntax.h +++ b/source/MaterialXGenGlsl/VkSyntax.h @@ -17,9 +17,9 @@ MATERIALX_NAMESPACE_BEGIN class MX_GENGLSL_API VkSyntax : public GlslSyntax { public: - VkSyntax(); + VkSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } const string& getInputQualifier() const override { return INPUT_QUALIFIER; } }; diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index 0f983cf8f2..566de99277 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -82,10 +82,18 @@ const std::unordered_map MdlShaderGenerator::GEOMPROP_DEFINITION // MdlShaderGenerator methods // -MdlShaderGenerator::MdlShaderGenerator() : - ShaderGenerator(MdlSyntax::create()) +MdlShaderGenerator::MdlShaderGenerator(TypeSystemPtr typeSystem) : + ShaderGenerator(typeSystem, MdlSyntax::create(typeSystem)) { - // Register built-in implementations + // Register custom types to handle enumeration output + _typeSystem->registerType(Type::MDL_COORDINATESPACE); + _typeSystem->registerType(Type::MDL_ADDRESSMODE); + _typeSystem->registerType(Type::MDL_FILTERLOOKUPMODE); + _typeSystem->registerType(Type::MDL_FILTERTYPE); + _typeSystem->registerType(Type::MDL_DISTRIBUTIONTYPE); + _typeSystem->registerType(Type::MDL_SCATTER_MODE); + + // Register build-in implementations // registerImplementation("IM_surfacematerial_" + MdlShaderGenerator::TARGET, MaterialNodeMdl::create); @@ -352,7 +360,7 @@ ShaderNodeImplPtr MdlShaderGenerator::getImplementation(const NodeDef& nodedef, throw ExceptionShaderGenError("NodeDef '" + nodedef.getName() + "' has no outputs defined"); } - const TypeDesc outputType = TypeDesc::get(outputs[0]->getType()); + const TypeDesc outputType = _typeSystem->getType(outputs[0]->getType()); if (implElement->isA()) { diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.h b/source/MaterialXGenMdl/MdlShaderGenerator.h index ac64e7c882..da54636178 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.h +++ b/source/MaterialXGenMdl/MdlShaderGenerator.h @@ -53,9 +53,18 @@ using MdlShaderGeneratorPtr = shared_ptr; class MX_GENMDL_API MdlShaderGenerator : public ShaderGenerator { public: - MdlShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + MdlShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Return a unique identifier for the target this generator is for const string& getTarget() const override { return TARGET; } diff --git a/source/MaterialXGenMdl/MdlSyntax.cpp b/source/MaterialXGenMdl/MdlSyntax.cpp index f8c99bb286..c08556cc04 100644 --- a/source/MaterialXGenMdl/MdlSyntax.cpp +++ b/source/MaterialXGenMdl/MdlSyntax.cpp @@ -13,19 +13,6 @@ MATERIALX_NAMESPACE_BEGIN -// Custom types to handle enumeration output -namespace Type -{ - -TYPEDESC_REGISTER_TYPE(MDL_COORDINATESPACE, "coordinatespace") -TYPEDESC_REGISTER_TYPE(MDL_ADDRESSMODE, "addressmode") -TYPEDESC_REGISTER_TYPE(MDL_FILTERLOOKUPMODE, "filterlookup") -TYPEDESC_REGISTER_TYPE(MDL_FILTERTYPE, "filtertype") -TYPEDESC_REGISTER_TYPE(MDL_DISTRIBUTIONTYPE, "distributiontype") -TYPEDESC_REGISTER_TYPE(MDL_SCATTER_MODE, "scatter_mode") - -} // namespace Type - namespace { @@ -34,8 +21,8 @@ const string MARKER_MDL_VERSION_SUFFIX = "MDL_VERSION_SUFFIX"; class MdlFilenameTypeSyntax : public ScalarTypeSyntax { public: - MdlFilenameTypeSyntax() : - ScalarTypeSyntax("texture_2d", "texture_2d()", "texture_2d()") + MdlFilenameTypeSyntax(const Syntax* parent) : + ScalarTypeSyntax(parent, "texture_2d", "texture_2d()", "texture_2d()") { } @@ -81,8 +68,8 @@ class MdlFilenameTypeSyntax : public ScalarTypeSyntax class MdlArrayTypeSyntax : public ScalarTypeSyntax { public: - MdlArrayTypeSyntax(const string& name) : - ScalarTypeSyntax(name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) + MdlArrayTypeSyntax(const Syntax* parent, const string& name) : + ScalarTypeSyntax(parent, name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) { } @@ -102,8 +89,8 @@ class MdlArrayTypeSyntax : public ScalarTypeSyntax class MdlFloatArrayTypeSyntax : public MdlArrayTypeSyntax { public: - explicit MdlFloatArrayTypeSyntax(const string& name) : - MdlArrayTypeSyntax(name) + explicit MdlFloatArrayTypeSyntax(const Syntax* parent, const string& name) : + MdlArrayTypeSyntax(parent, name) { } @@ -118,8 +105,8 @@ class MdlFloatArrayTypeSyntax : public MdlArrayTypeSyntax class MdlIntegerArrayTypeSyntax : public MdlArrayTypeSyntax { public: - explicit MdlIntegerArrayTypeSyntax(const string& name) : - MdlArrayTypeSyntax(name) + explicit MdlIntegerArrayTypeSyntax(const Syntax* parent, const string& name) : + MdlArrayTypeSyntax(parent, name) { } @@ -141,8 +128,8 @@ class MdlIntegerArrayTypeSyntax : public MdlArrayTypeSyntax class MdlColor4TypeSyntax : public AggregateTypeSyntax { public: - MdlColor4TypeSyntax() : - AggregateTypeSyntax("color4", "mk_color4(0.0)", "mk_color4(0.0)", + MdlColor4TypeSyntax(const Syntax* parent) : + AggregateTypeSyntax(parent, "color4", "mk_color4(0.0)", "mk_color4(0.0)", EMPTY_STRING, EMPTY_STRING, MdlSyntax::COLOR4_MEMBERS) { } @@ -168,8 +155,8 @@ class MdlColor4TypeSyntax : public AggregateTypeSyntax class MdlEnumSyntax : public AggregateTypeSyntax { public: - MdlEnumSyntax(const string& name, const string& defaultValue, const string& defaultUniformValue, const StringVec& members) : - AggregateTypeSyntax(name, defaultValue, defaultUniformValue, EMPTY_STRING, EMPTY_STRING, members) + MdlEnumSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& defaultUniformValue, const StringVec& members) : + AggregateTypeSyntax(parent, name, defaultValue, defaultUniformValue, EMPTY_STRING, EMPTY_STRING, members) { } @@ -203,7 +190,7 @@ const string MdlSyntax::PORT_NAME_PREFIX = "mxp_"; // MdlSyntax methods // -MdlSyntax::MdlSyntax() +MdlSyntax::MdlSyntax(TypeSystemPtr typeSystem) : Syntax(typeSystem) { // Add in all reserved words and keywords in MDL // Formatted as in the MDL Specification 1.9.2 for easy comparing @@ -253,6 +240,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::FLOAT, std::make_shared( + this, "float", "0.0", "0.0")); @@ -260,11 +248,13 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::FLOATARRAY, std::make_shared( + this, "float")); registerTypeSyntax( Type::INTEGER, std::make_shared( + this, "int", "0", "0")); @@ -272,11 +262,13 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::INTEGERARRAY, std::make_shared( + this, "int")); registerTypeSyntax( Type::BOOLEAN, std::make_shared( + this, "bool", "false", "false")); @@ -284,6 +276,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::COLOR3, std::make_shared( + this, "color", "color(0.0)", "color(0.0)", @@ -293,11 +286,12 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::COLOR4, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( Type::VECTOR2, std::make_shared( + this, "float2", "float2(0.0)", "float2(0.0)", @@ -308,6 +302,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::VECTOR3, std::make_shared( + this, "float3", "float3(0.0)", "float3(0.0)", @@ -318,6 +313,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::VECTOR4, std::make_shared( + this, "float4", "float4(0.0)", "float4(0.0)", @@ -328,6 +324,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MATRIX33, std::make_shared( + this, "float3x3", "float3x3(1.0)", "float3x3(1.0)")); @@ -335,6 +332,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MATRIX44, std::make_shared( + this, "float4x4", "float4x4(1.0)", "float4x4(1.0)")); @@ -342,17 +340,19 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::STRING, std::make_shared( + this, "string", "\"\"", "\"\"")); registerTypeSyntax( Type::FILENAME, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( Type::BSDF, std::make_shared( + this, "material", "material()", "material()")); @@ -360,6 +360,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::EDF, std::make_shared( + this, "material", "material()", "material()")); @@ -367,6 +368,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::VDF, std::make_shared( + this, "material", "material()", "material()")); @@ -374,6 +376,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::SURFACESHADER, std::make_shared( + this, "material", "material()", "material()")); @@ -381,6 +384,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::VOLUMESHADER, std::make_shared( + this, "material", "material()", "material()")); @@ -388,6 +392,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::DISPLACEMENTSHADER, std::make_shared( + this, "material", "material()", "material()")); @@ -395,6 +400,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::LIGHTSHADER, std::make_shared( + this, "material", "material()", "material()")); @@ -402,6 +408,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MATERIAL, std::make_shared( + this, "material", "material()", "material()")); @@ -409,6 +416,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_ADDRESSMODE, std::make_shared( + this, "mx_addressmode_type", "mx_addressmode_type_periodic", "mx_addressmode_type_periodic", @@ -417,6 +425,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_COORDINATESPACE, std::make_shared( + this, "mx_coordinatespace_type", "mx_coordinatespace_type_model", "mx_coordinatespace_type_model", @@ -425,6 +434,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_FILTERLOOKUPMODE, std::make_shared( + this, "mx_filterlookup_type", "mx_filterlookup_type_linear", "mx_filterlookup_type_linear", @@ -433,6 +443,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_FILTERTYPE, std::make_shared( + this, "mx_filter_type", "mx_filter_type_gaussian", "mx_filter_type_gaussian", @@ -441,6 +452,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_DISTRIBUTIONTYPE, std::make_shared( + this, "mx_distribution_type", "mx_distribution_type_ggx", "mx_distribution_type_ggx", @@ -449,6 +461,7 @@ MdlSyntax::MdlSyntax() registerTypeSyntax( Type::MDL_SCATTER_MODE, std::make_shared( + this, "mx_scatter_mode", "mx_scatter_mode_R", "mx_scatter_mode_R", diff --git a/source/MaterialXGenMdl/MdlSyntax.h b/source/MaterialXGenMdl/MdlSyntax.h index a3a7aee6e1..d12ddb230e 100644 --- a/source/MaterialXGenMdl/MdlSyntax.h +++ b/source/MaterialXGenMdl/MdlSyntax.h @@ -25,9 +25,9 @@ using MdlSyntaxPtr = shared_ptr; class MX_GENMDL_API MdlSyntax : public Syntax { public: - MdlSyntax(); + MdlSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } const string& getConstantQualifier() const override { return CONST_QUALIFIER; }; const string& getUniformQualifier() const override { return UNIFORM_QUALIFIER; }; diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index b61f62131e..b5a6177a1c 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -45,8 +45,8 @@ const string MslShaderGenerator::VERSION = "2.3"; // MslShaderGenerator methods // -MslShaderGenerator::MslShaderGenerator() : - HwShaderGenerator(MslSyntax::create()) +MslShaderGenerator::MslShaderGenerator(TypeSystemPtr typeSystem) : + HwShaderGenerator(typeSystem, MslSyntax::create(typeSystem)) { // // Register all custom node implementation classes @@ -1250,7 +1250,7 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, throw ExceptionShaderGenError("NodeDef '" + nodedef.getName() + "' has no outputs defined"); } - const TypeDesc outputType = TypeDesc::get(outputs[0]->getType()); + const TypeDesc outputType = _typeSystem->getType(outputs[0]->getType()); if (implElement->isA()) { diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h index 6796f545d3..62d2dc4f9c 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.h +++ b/source/MaterialXGenMsl/MslShaderGenerator.h @@ -25,9 +25,18 @@ using MslShaderGeneratorPtr = shared_ptr; class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator { public: - MslShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + MslShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Generate a shader starting from the given element, translating /// the element and all dependencies upstream into shader code. diff --git a/source/MaterialXGenMsl/MslSyntax.cpp b/source/MaterialXGenMsl/MslSyntax.cpp index 30f44c5d1c..81b427259c 100644 --- a/source/MaterialXGenMsl/MslSyntax.cpp +++ b/source/MaterialXGenMsl/MslSyntax.cpp @@ -17,8 +17,8 @@ namespace class MslStringTypeSyntax : public StringTypeSyntax { public: - MslStringTypeSyntax() : - StringTypeSyntax("int", "0", "0") { } + MslStringTypeSyntax(const Syntax* parent) : + StringTypeSyntax(parent, "int", "0", "0") { } string getValue(const Value& /*value*/, bool /*uniform*/) const override { @@ -29,8 +29,8 @@ class MslStringTypeSyntax : public StringTypeSyntax class MslArrayTypeSyntax : public ScalarTypeSyntax { public: - MslArrayTypeSyntax(const string& name) : - ScalarTypeSyntax(name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) + MslArrayTypeSyntax(const Syntax* parent, const string& name) : + ScalarTypeSyntax(parent, name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) { } @@ -51,8 +51,8 @@ class MslArrayTypeSyntax : public ScalarTypeSyntax class MslFloatArrayTypeSyntax : public MslArrayTypeSyntax { public: - explicit MslFloatArrayTypeSyntax(const string& name) : - MslArrayTypeSyntax(name) + explicit MslFloatArrayTypeSyntax(const Syntax* parent, const string& name) : + MslArrayTypeSyntax(parent, name) { } @@ -67,8 +67,8 @@ class MslFloatArrayTypeSyntax : public MslArrayTypeSyntax class MslIntegerArrayTypeSyntax : public MslArrayTypeSyntax { public: - explicit MslIntegerArrayTypeSyntax(const string& name) : - MslArrayTypeSyntax(name) + explicit MslIntegerArrayTypeSyntax(const Syntax* parent, const string& name) : + MslArrayTypeSyntax(parent, name) { } @@ -97,7 +97,7 @@ const StringVec MslSyntax::VEC4_MEMBERS = { ".x", ".y", ".z", ".w" }; // MslSyntax methods // -MslSyntax::MslSyntax() +MslSyntax::MslSyntax(TypeSystemPtr typeSystem) : Syntax(typeSystem) { // Add in all reserved words and keywords in MSL registerReservedWords( @@ -139,6 +139,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::FLOAT, std::make_shared( + this, "float", "0.0", "0.0")); @@ -146,11 +147,13 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::FLOATARRAY, std::make_shared( + this, "float")); registerTypeSyntax( Type::INTEGER, std::make_shared( + this, "int", "0", "0")); @@ -158,11 +161,13 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::INTEGERARRAY, std::make_shared( + this, "int")); registerTypeSyntax( Type::BOOLEAN, std::make_shared( + this, "bool", "false", "false")); @@ -170,6 +175,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::COLOR3, std::make_shared( + this, "vec3", "vec3(0.0)", "vec3(0.0)", @@ -180,6 +186,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::COLOR4, std::make_shared( + this, "vec4", "vec4(0.0)", "vec4(0.0)", @@ -190,6 +197,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::VECTOR2, std::make_shared( + this, "vec2", "vec2(0.0)", "vec2(0.0)", @@ -200,6 +208,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::VECTOR3, std::make_shared( + this, "vec3", "vec3(0.0)", "vec3(0.0)", @@ -210,6 +219,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::VECTOR4, std::make_shared( + this, "vec4", "vec4(0.0)", "vec4(0.0)", @@ -220,6 +230,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::MATRIX33, std::make_shared( + this, "mat3", "mat3(1.0)", "mat3(1.0)")); @@ -227,17 +238,19 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::MATRIX44, std::make_shared( + this, "mat4", "mat4(1.0)", "mat4(1.0)")); registerTypeSyntax( Type::STRING, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( Type::FILENAME, std::make_shared( + this, "MetalTexture", EMPTY_STRING, EMPTY_STRING)); @@ -245,6 +258,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::BSDF, std::make_shared( + this, "BSDF", "BSDF{float3(0.0),float3(1.0)}", EMPTY_STRING, @@ -254,6 +268,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::EDF, std::make_shared( + this, "EDF", "EDF(0.0)", "EDF(0.0)", @@ -263,6 +278,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::VDF, std::make_shared( + this, "BSDF", "BSDF{float3(0.0),float3(1.0)}", EMPTY_STRING)); @@ -270,6 +286,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::SURFACESHADER, std::make_shared( + this, "surfaceshader", "surfaceshader{float3(0.0),float3(0.0)}", EMPTY_STRING, @@ -279,6 +296,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::VOLUMESHADER, std::make_shared( + this, "volumeshader", "volumeshader{float3(0.0),float3(0.0)}", EMPTY_STRING, @@ -288,6 +306,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::DISPLACEMENTSHADER, std::make_shared( + this, "displacementshader", "displacementshader{float3(0.0),1.0}", EMPTY_STRING, @@ -297,6 +316,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::LIGHTSHADER, std::make_shared( + this, "lightshader", "lightshader{float3(0.0),float3(0.0)}", EMPTY_STRING, @@ -306,6 +326,7 @@ MslSyntax::MslSyntax() registerTypeSyntax( Type::MATERIAL, std::make_shared( + this, "material", "material{float3(0.0),float3(0.0)}", EMPTY_STRING, diff --git a/source/MaterialXGenMsl/MslSyntax.h b/source/MaterialXGenMsl/MslSyntax.h index 22469e2193..1836a7503e 100644 --- a/source/MaterialXGenMsl/MslSyntax.h +++ b/source/MaterialXGenMsl/MslSyntax.h @@ -19,9 +19,9 @@ MATERIALX_NAMESPACE_BEGIN class MX_GENMSL_API MslSyntax : public Syntax { public: - MslSyntax(); + MslSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } const string& getInputQualifier() const override { return INPUT_QUALIFIER; } const string& getOutputQualifier() const override { return OUTPUT_QUALIFIER; } diff --git a/source/MaterialXGenMsl/Nodes/LightCompoundNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/LightCompoundNodeMsl.cpp index d7d5d8ceaa..d0ee8a4dee 100644 --- a/source/MaterialXGenMsl/Nodes/LightCompoundNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/LightCompoundNodeMsl.cpp @@ -34,7 +34,7 @@ void LightCompoundNodeMsl::initialize(const InterfaceElement& element, GenContex NodeDefPtr nodeDef = graph.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { - _lightUniforms.add(TypeDesc::get(input->getType()), input->getName()); + _lightUniforms.add(context.getTypeDesc(input->getType()), input->getName()); } } diff --git a/source/MaterialXGenMsl/Nodes/LightShaderNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/LightShaderNodeMsl.cpp index b556415dae..1c3bd40a21 100644 --- a/source/MaterialXGenMsl/Nodes/LightShaderNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/LightShaderNodeMsl.cpp @@ -44,7 +44,8 @@ void LightShaderNodeMsl::initialize(const InterfaceElement& element, GenContext& NodeDefPtr nodeDef = impl.getNodeDef(); for (InputPtr input : nodeDef->getActiveInputs()) { - _lightUniforms.add(TypeDesc::get(input->getType()), input->getName(), input->getValue()); + const TypeDesc type = context.getTypeDesc(input->getType()); + _lightUniforms.add(type, input->getName(), input->getValue()); } } diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp index 75cfd47f3b..774c15bd41 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.cpp +++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp @@ -24,8 +24,8 @@ const string OslShaderGenerator::TARGET = "genosl"; // OslShaderGenerator methods // -OslShaderGenerator::OslShaderGenerator() : - ShaderGenerator(OslSyntax::create()) +OslShaderGenerator::OslShaderGenerator(TypeSystemPtr typeSystem) : + ShaderGenerator(typeSystem, OslSyntax::create(typeSystem)) { // Register built-in implementations diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h index e5cf13977e..d81c19e2c0 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.h +++ b/source/MaterialXGenOsl/OslShaderGenerator.h @@ -23,9 +23,18 @@ using OslShaderGeneratorPtr = shared_ptr; class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator { public: - OslShaderGenerator(); - - static ShaderGeneratorPtr create() { return std::make_shared(); } + /// Constructor. + OslShaderGenerator(TypeSystemPtr typeSystem); + + /// Creator function. + /// If a TypeSystem is not provided it will be created internally. + /// Optionally pass in an externally created TypeSystem here, + /// if you want to keep type descriptions alive after the lifetime + /// of the shader generator. + static ShaderGeneratorPtr create(TypeSystemPtr typeSystem = nullptr) + { + return std::make_shared(typeSystem ? typeSystem : TypeSystem::create()); + } /// Return a unique identifier for the target this generator is for const string& getTarget() const override { return TARGET; } diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp index a85821c4fd..4d5651d375 100644 --- a/source/MaterialXGenOsl/OslSyntax.cpp +++ b/source/MaterialXGenOsl/OslSyntax.cpp @@ -17,8 +17,8 @@ namespace class OslBooleanTypeSyntax : public ScalarTypeSyntax { public: - OslBooleanTypeSyntax() : - ScalarTypeSyntax("int", "0", "0", EMPTY_STRING, "#define true 1\n#define false 0") + OslBooleanTypeSyntax(const Syntax* parent) : + ScalarTypeSyntax(parent, "int", "0", "0", EMPTY_STRING, "#define true 1\n#define false 0") { } @@ -31,8 +31,8 @@ class OslBooleanTypeSyntax : public ScalarTypeSyntax class OslArrayTypeSyntax : public ScalarTypeSyntax { public: - OslArrayTypeSyntax(const string& name) : - ScalarTypeSyntax(name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) + OslArrayTypeSyntax(const Syntax* parent, const string& name) : + ScalarTypeSyntax(parent, name, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING) { } @@ -57,8 +57,8 @@ class OslArrayTypeSyntax : public ScalarTypeSyntax class OslFloatArrayTypeSyntax : public OslArrayTypeSyntax { public: - explicit OslFloatArrayTypeSyntax(const string& name) : - OslArrayTypeSyntax(name) + explicit OslFloatArrayTypeSyntax(const Syntax* parent, const string& name) : + OslArrayTypeSyntax(parent, name) { } @@ -73,8 +73,8 @@ class OslFloatArrayTypeSyntax : public OslArrayTypeSyntax class OslIntegerArrayTypeSyntax : public OslArrayTypeSyntax { public: - explicit OslIntegerArrayTypeSyntax(const string& name) : - OslArrayTypeSyntax(name) + explicit OslIntegerArrayTypeSyntax(const Syntax* parent, const string& name) : + OslArrayTypeSyntax(parent, name) { } @@ -91,10 +91,10 @@ class OslIntegerArrayTypeSyntax : public OslArrayTypeSyntax class OslStructTypeSyntax : public AggregateTypeSyntax { public: - OslStructTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + OslStructTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING, const StringVec& members = EMPTY_MEMBERS) : - AggregateTypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) + AggregateTypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) { } @@ -121,8 +121,8 @@ class OslStructTypeSyntax : public AggregateTypeSyntax class OslColor4TypeSyntax : public OslStructTypeSyntax { public: - OslColor4TypeSyntax() : - OslStructTypeSyntax("color4", "color4(color(0.0), 0.0)", "{color(0.0), 0.0}", EMPTY_STRING, EMPTY_STRING, OslSyntax::COLOR4_MEMBERS) + OslColor4TypeSyntax(const Syntax* parent) : + OslStructTypeSyntax(parent, "color4", "color4(color(0.0), 0.0)", "{color(0.0), 0.0}", EMPTY_STRING, EMPTY_STRING, OslSyntax::COLOR4_MEMBERS) { } @@ -155,10 +155,10 @@ class OslColor4TypeSyntax : public OslStructTypeSyntax class OSLMatrix3TypeSyntax : public AggregateTypeSyntax { public: - OSLMatrix3TypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + OSLMatrix3TypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING, const StringVec& members = EMPTY_MEMBERS) : - AggregateTypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) + AggregateTypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) { } @@ -193,10 +193,10 @@ class OSLMatrix3TypeSyntax : public AggregateTypeSyntax class OSLFilenameTypeSyntax : public AggregateTypeSyntax { public: - OSLFilenameTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + OSLFilenameTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING, const StringVec& members = EMPTY_MEMBERS) : - AggregateTypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) + AggregateTypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) { } @@ -234,7 +234,7 @@ const StringVec OslSyntax::COLOR4_MEMBERS = { ".rgb[0]", ".rgb[1]", ".rgb[2]", " // OslSyntax methods // -OslSyntax::OslSyntax() +OslSyntax::OslSyntax(TypeSystemPtr typeSystem) : Syntax(typeSystem) { // Add in all reserved words and keywords in OSL registerReservedWords( @@ -268,6 +268,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::FLOAT, std::make_shared( + this, "float", "0.0", "0.0")); @@ -275,11 +276,13 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::FLOATARRAY, std::make_shared( + this, "float")); registerTypeSyntax( Type::INTEGER, std::make_shared( + this, "int", "0", "0")); @@ -287,17 +290,19 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::INTEGERARRAY, std::make_shared( + this, "int")); registerTypeSyntax( Type::BOOLEAN, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( // Note: the color type in OSL is a built in type and // should not use the custom OslStructTypeSyntax. Type::COLOR3, std::make_shared( + this, "color", "color(0.0)", "color(0.0)", @@ -307,11 +312,12 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::COLOR4, - std::make_shared()); + std::make_shared(this)); registerTypeSyntax( Type::VECTOR2, std::make_shared( + this, "vector2", "vector2(0.0, 0.0)", "{0.0, 0.0}", @@ -324,6 +330,7 @@ OslSyntax::OslSyntax() // should not use the custom OslStructTypeSyntax. Type::VECTOR3, std::make_shared( + this, "vector", "vector(0.0)", "vector(0.0)", @@ -334,6 +341,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::VECTOR4, std::make_shared( + this, "vector4", "vector4(0.0, 0.0, 0.0, 0.0)", "{0.0, 0.0, 0.0, 0.0}", @@ -344,6 +352,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::MATRIX33, std::make_shared( + this, "matrix", "matrix(1.0)", "matrix(1.0)")); @@ -351,6 +360,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::MATRIX44, std::make_shared( + this, "matrix", "matrix(1.0)", "matrix(1.0)")); @@ -358,6 +368,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::STRING, std::make_shared( + this, "string", "\"\"", "\"\"")); @@ -365,6 +376,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::FILENAME, std::make_shared( + this, "textureresource ", "textureresource (\"\", \"\")", "(\"\", \"\")", @@ -374,6 +386,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::BSDF, std::make_shared( + this, "BSDF", "null_closure", "0", @@ -383,6 +396,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::EDF, std::make_shared( + this, "EDF", "null_closure", "0", @@ -392,6 +406,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::VDF, std::make_shared( + this, "VDF", "null_closure", "0", @@ -401,6 +416,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::SURFACESHADER, std::make_shared( + this, "surfaceshader", "surfaceshader(null_closure, null_closure, 1.0)", "{ 0, 0, 1.0 }", @@ -410,6 +426,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::VOLUMESHADER, std::make_shared( + this, "volumeshader", "null_closure", "0", @@ -419,6 +436,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::DISPLACEMENTSHADER, std::make_shared( + this, "displacementshader", "vector(0.0)", "vector(0.0)", @@ -428,6 +446,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::LIGHTSHADER, std::make_shared( + this, "lightshader", "null_closure", "0", @@ -437,6 +456,7 @@ OslSyntax::OslSyntax() registerTypeSyntax( Type::MATERIAL, std::make_shared( + this, "MATERIAL", "null_closure", "0", diff --git a/source/MaterialXGenOsl/OslSyntax.h b/source/MaterialXGenOsl/OslSyntax.h index 5d33524c10..aad280a5cd 100644 --- a/source/MaterialXGenOsl/OslSyntax.h +++ b/source/MaterialXGenOsl/OslSyntax.h @@ -20,9 +20,9 @@ MATERIALX_NAMESPACE_BEGIN class MX_GENOSL_API OslSyntax : public Syntax { public: - OslSyntax(); + OslSyntax(TypeSystemPtr typeSystem); - static SyntaxPtr create() { return std::make_shared(); } + static SyntaxPtr create(TypeSystemPtr typeSystem) { return std::make_shared(typeSystem); } const string& getOutputQualifier() const override; const string& getConstantQualifier() const override { return EMPTY_STRING; }; diff --git a/source/MaterialXGenShader/GenContext.h b/source/MaterialXGenShader/GenContext.h index 0f565ded6e..733d8b98ce 100644 --- a/source/MaterialXGenShader/GenContext.h +++ b/source/MaterialXGenShader/GenContext.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -51,6 +52,12 @@ class MX_GENSHADER_API GenContext return _options; } + /// Return a TypeDesc for the given type name. + TypeDesc getTypeDesc(const string& name) const + { + return _sg->getTypeSystem()->getType(name); + } + /// Register a user search path for finding source code during /// code generation. void registerSourceCodeSearchPath(const FilePath& path) diff --git a/source/MaterialXGenShader/HwShaderGenerator.cpp b/source/MaterialXGenShader/HwShaderGenerator.cpp index d9862650e3..b3a3f3e132 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.cpp +++ b/source/MaterialXGenShader/HwShaderGenerator.cpp @@ -181,8 +181,8 @@ const string HwShaderGenerator::CLOSURE_CONTEXT_SUFFIX_REFLECTION("_reflection") const string HwShaderGenerator::CLOSURE_CONTEXT_SUFFIX_TRANSMISSION("_transmission"); const string HwShaderGenerator::CLOSURE_CONTEXT_SUFFIX_INDIRECT("_indirect"); -HwShaderGenerator::HwShaderGenerator(SyntaxPtr syntax) : - ShaderGenerator(syntax), +HwShaderGenerator::HwShaderGenerator(TypeSystemPtr typeSystem, SyntaxPtr syntax) : + ShaderGenerator(typeSystem, syntax), _defDefault(HwShaderGenerator::ClosureContextType::DEFAULT), _defReflection(HwShaderGenerator::ClosureContextType::REFLECTION), _defTransmission(HwShaderGenerator::ClosureContextType::TRANSMISSION), @@ -544,7 +544,7 @@ void HwShaderGenerator::emitFunctionCall(const ShaderNode& node, GenContext& con void HwShaderGenerator::bindLightShader(const NodeDef& nodeDef, unsigned int lightTypeId, GenContext& context) { - if (TypeDesc::get(nodeDef.getType()) != Type::LIGHTSHADER) + if (context.getTypeDesc(nodeDef.getType()) != Type::LIGHTSHADER) { throw ExceptionShaderGenError("Error binding light shader. Given nodedef '" + nodeDef.getName() + "' is not of lightshader type"); } diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h index d78aaf917a..8d54cd39bb 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.h +++ b/source/MaterialXGenShader/HwShaderGenerator.h @@ -330,7 +330,7 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator static const string CLOSURE_CONTEXT_SUFFIX_INDIRECT; protected: - HwShaderGenerator(SyntaxPtr syntax); + HwShaderGenerator(TypeSystemPtr typeSystem, SyntaxPtr syntax); /// Create and initialize a new HW shader for shader generation. virtual ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const; diff --git a/source/MaterialXGenShader/ShaderGenerator.cpp b/source/MaterialXGenShader/ShaderGenerator.cpp index 398232bf39..e62fd1e1a6 100644 --- a/source/MaterialXGenShader/ShaderGenerator.cpp +++ b/source/MaterialXGenShader/ShaderGenerator.cpp @@ -29,7 +29,8 @@ const string ShaderGenerator::T_FILE_TRANSFORM_UV = "$fileTransformUv"; // ShaderGenerator methods // -ShaderGenerator::ShaderGenerator(SyntaxPtr syntax) : +ShaderGenerator::ShaderGenerator(TypeSystemPtr typeSystem, SyntaxPtr syntax) : + _typeSystem(typeSystem), _syntax(syntax) { } @@ -300,7 +301,7 @@ ShaderNodeImplPtr ShaderGenerator::getImplementation(const NodeDef& nodedef, Gen throw ExceptionShaderGenError("NodeDef '" + nodedef.getName() + "' has no outputs defined"); } - const TypeDesc outputType = TypeDesc::get(outputs[0]->getType()); + const TypeDesc outputType = _typeSystem->getType(outputs[0]->getType()); if (implElement->isA()) { @@ -344,45 +345,72 @@ ShaderNodeImplPtr ShaderGenerator::getImplementation(const NodeDef& nodedef, Gen return impl; } -/// Load any struct type definitions from the document in to the type cache. -void ShaderGenerator::loadStructTypeDefs(const DocumentPtr& doc) +void ShaderGenerator::registerTypeDefs(const DocumentPtr& doc) { + /// Load any struct type definitions from the document. for (const auto& mxTypeDef : doc->getTypeDefs()) { - const auto& typeDefName = mxTypeDef->getName(); + const string& typeName = mxTypeDef->getName(); const auto& members = mxTypeDef->getMembers(); // If we don't have any member children then we're not going to consider ourselves a struct. if (members.empty()) + { continue; + } - StructTypeDesc newStructTypeDesc; + auto structMembers = std::make_shared(); for (const auto& member : members) { - auto memberName = member->getName(); - auto memberTypeName = member->getType(); - auto memberType = TypeDesc::get(memberTypeName); - auto memberDefaultValue = member->getValueString(); + const auto memberType = _typeSystem->getType(member->getType()); + const auto memberName = member->getName(); + const auto memberDefaultValue = member->getValueString(); + structMembers->emplace_back(StructMemberDesc(memberType, memberName, memberDefaultValue)); + } + + _typeSystem->registerType(typeName, TypeDesc::BASETYPE_STRUCT, TypeDesc::SEMANTIC_NONE, 1, structMembers); + } - newStructTypeDesc.addMember(memberName, memberType, memberDefaultValue); + // Create a type syntax for all struct types loaded above. + for (TypeDesc typeDesc : _typeSystem->getTypes()) + { + if (!typeDesc.isStruct()) + { + continue; } - auto structIndex = StructTypeDesc::emplace_back(newStructTypeDesc); + const string& structTypeName = typeDesc.getName(); + string defaultValue = structTypeName + "( "; + string uniformDefaultValue = EMPTY_STRING; + string typeAlias = EMPTY_STRING; + string typeDefinition = "struct " + structTypeName + " { "; - TypeDesc structTypeDesc(typeDefName, TypeDesc::BASETYPE_STRUCT, TypeDesc::SEMANTIC_NONE, 1, structIndex); + auto structMembers = typeDesc.getStructMembers(); + if (structMembers) + { + for (const auto& structMember : *structMembers) + { + const string& memberType = structMember.getType().getName(); + const string& memberName = structMember.getName(); + const string& memberDefaultValue = structMember.getDefaultValueStr(); - TypeDescRegistry(structTypeDesc, typeDefName); + defaultValue += memberDefaultValue + ", "; + typeDefinition += memberType + " " + memberName + "; "; + } + } - StructTypeDesc::get(structIndex).setTypeDesc(TypeDesc::get(typeDefName)); - } + typeDefinition += " };"; + defaultValue += " )"; - _syntax->registerStructTypeDescSyntax(); -} + StructTypeSyntaxPtr structTypeSyntax = _syntax->createStructSyntax( + structTypeName, + defaultValue, + uniformDefaultValue, + typeAlias, + typeDefinition); -/// Clear any struct type definitions loaded -void ShaderGenerator::clearStructTypeDefs() -{ - StructTypeDesc::clear(); + _syntax->registerTypeSyntax(typeDesc, structTypeSyntax); + } } namespace @@ -436,7 +464,7 @@ void ShaderGenerator::registerShaderMetadata(const DocumentPtr& doc, GenContext& if (def->getExportable()) { const string& attrName = def->getAttrName(); - const TypeDesc type = TypeDesc::get(def->getType()); + const TypeDesc type = _typeSystem->getType(def->getType()); if (!attrName.empty() && type != Type::NONE) { registry->addMetadata(attrName, type, def->getValue()); diff --git a/source/MaterialXGenShader/ShaderGenerator.h b/source/MaterialXGenShader/ShaderGenerator.h index a2f54fec2e..997ee3772e 100644 --- a/source/MaterialXGenShader/ShaderGenerator.h +++ b/source/MaterialXGenShader/ShaderGenerator.h @@ -185,17 +185,20 @@ class MX_GENSHADER_API ShaderGenerator return _unitSystem; } + /// Returns the type system + TypeSystemPtr getTypeSystem() const + { + return _typeSystem; + } + /// Return the map of token substitutions used by the generator. const StringMap& getTokenSubstitutions() const { return _tokenSubstitutions; } - /// Load any struct type definitions from the document in to the type cache. - void loadStructTypeDefs(const DocumentPtr& doc); - - /// Clear any struct type definitions loaded - void clearStructTypeDefs(); + /// Register type definitions from the document. + virtual void registerTypeDefs(const DocumentPtr& doc); /// Register metadata that should be exported to the generated shaders. /// Supported metadata includes standard UI attributes like "uiname", "uifolder", @@ -210,7 +213,7 @@ class MX_GENSHADER_API ShaderGenerator protected: /// Protected constructor - ShaderGenerator(SyntaxPtr syntax); + ShaderGenerator(TypeSystemPtr typeSystem, SyntaxPtr syntax); /// Create a new stage in a shader. virtual ShaderStagePtr createStage(const string& name, Shader& shader) const; @@ -231,6 +234,7 @@ class MX_GENSHADER_API ShaderGenerator protected: static const string T_FILE_TRANSFORM_UV; + TypeSystemPtr _typeSystem; SyntaxPtr _syntax; Factory _implFactory; ColorManagementSystemPtr _colorManagementSystem; diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 0c9f80cf8e..eee15cda3e 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -38,7 +38,7 @@ void ShaderGraph::addInputSockets(const InterfaceElement& elem, GenContext& cont const string& portValueString = portValue ? portValue->getValueString() : EMPTY_STRING; std::pair enumResult; const string& enumNames = input->getAttribute(ValueElement::ENUM_ATTRIBUTE); - const TypeDesc portType = TypeDesc::get(input->getType()); + const TypeDesc portType = context.getTypeDesc(input->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(portValueString, portType, enumNames, enumResult)) { inputSocket = addInputSocket(input->getName(), enumResult.first); @@ -64,15 +64,15 @@ void ShaderGraph::addInputSockets(const InterfaceElement& elem, GenContext& cont } } -void ShaderGraph::addOutputSockets(const InterfaceElement& elem) +void ShaderGraph::addOutputSockets(const InterfaceElement& elem, GenContext& context) { for (const OutputPtr& output : elem.getActiveOutputs()) { - addOutputSocket(output->getName(), TypeDesc::get(output->getType())); + addOutputSocket(output->getName(), context.getTypeDesc(output->getType())); } if (numOutputSockets() == 0) { - addOutputSocket("out", TypeDesc::get(elem.getType())); + addOutputSocket("out", context.getTypeDesc(elem.getType())); } } @@ -246,7 +246,7 @@ void ShaderGraph::addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geom { std::pair enumResult; const string& enumNames = nodeDefSpaceInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); - const TypeDesc portType = TypeDesc::get(nodeDefSpaceInput->getType()); + const TypeDesc portType = context.getTypeDesc(nodeDefSpaceInput->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(space, portType, enumNames, enumResult)) { spaceInput->setValue(enumResult.second); @@ -452,7 +452,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const NodeGraph& n graph->addInputSockets(*nodeDef, context); // Create output sockets from the nodegraph - graph->addOutputSockets(nodeGraph); + graph->addOutputSockets(nodeGraph, context); // Traverse all outputs and create all internal nodes for (OutputPtr graphOutput : nodeGraph.getActiveOutputs()) @@ -511,7 +511,8 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name graph->addInputSockets(*interface, context); // Create the given output socket - ShaderGraphOutputSocket* outputSocket = graph->addOutputSocket(output->getName(), TypeDesc::get(output->getType())); + const TypeDesc outputType = context.getTypeDesc(output->getType()); + ShaderGraphOutputSocket* outputSocket = graph->addOutputSocket(output->getName(), outputType); outputSocket->setPath(output->getNamePath()); const string& outputUnit = output->getUnit(); if (!outputUnit.empty()) @@ -543,7 +544,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name graph->addInputSockets(*nodeDef, context); // Create output sockets - graph->addOutputSockets(*nodeDef); + graph->addOutputSockets(*nodeDef, context); // Create this shader node in the graph. ShaderNodePtr newNode = ShaderNode::create(graph.get(), node->getName(), *nodeDef, context); @@ -579,7 +580,7 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name { const string& valueString = value->getValueString(); std::pair enumResult; - const TypeDesc type = TypeDesc::get(nodedefInput->getType()); + const TypeDesc type = context.getTypeDesc(nodedefInput->getType()); const string& enumNames = nodedefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) { diff --git a/source/MaterialXGenShader/ShaderGraph.h b/source/MaterialXGenShader/ShaderGraph.h index 3ad126923b..9187ce03ff 100644 --- a/source/MaterialXGenShader/ShaderGraph.h +++ b/source/MaterialXGenShader/ShaderGraph.h @@ -136,7 +136,7 @@ class MX_GENSHADER_API ShaderGraph : public ShaderNode void addInputSockets(const InterfaceElement& elem, GenContext& context); /// Add output sockets from an interface element (nodedef, nodegraph or node) - void addOutputSockets(const InterfaceElement& elem); + void addOutputSockets(const InterfaceElement& elem, GenContext& context); /// Traverse from the given root element and add all dependencies upstream. /// The traversal is done in the context of a material, if given, to include diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 12b9bbf548..43539b5d9b 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -186,7 +186,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, // Create interface from nodedef for (const ValueElementPtr& port : nodeDef.getActiveValueElements()) { - const TypeDesc portType = TypeDesc::get(port->getType()); + const TypeDesc portType = context.getTypeDesc(port->getType()); if (port->isA()) { newNode->addOutput(port->getName(), portType); @@ -223,7 +223,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, // Add a default output if needed if (newNode->numOutputs() == 0) { - newNode->addOutput("out", TypeDesc::get(nodeDef.getType())); + newNode->addOutput("out", context.getTypeDesc(nodeDef.getType())); } const string& nodeDefName = nodeDef.getName(); @@ -356,7 +356,7 @@ void ShaderNode::initialize(const Node& node, const NodeDef& nodeDef, GenContext const string& valueString = portValue ? portValue->getValueString() : EMPTY_STRING; std::pair enumResult; const string& enumNames = nodeDefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); - const TypeDesc type = TypeDesc::get(nodeDefInput->getType()); + const TypeDesc type = context.getTypeDesc(nodeDefInput->getType()); if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) { input->setValue(enumResult.second); diff --git a/source/MaterialXGenShader/Syntax.cpp b/source/MaterialXGenShader/Syntax.cpp index 81daa9e0a7..2ac9eb04d1 100644 --- a/source/MaterialXGenShader/Syntax.cpp +++ b/source/MaterialXGenShader/Syntax.cpp @@ -34,7 +34,8 @@ const std::unordered_map Syntax::CHANNELS_MAPPING = // Syntax methods // -Syntax::Syntax() +Syntax::Syntax(TypeSystemPtr typeSystem) : + _typeSystem(typeSystem) { } @@ -190,40 +191,24 @@ bool Syntax::remapEnumeration(const string&, TypeDesc, const string&, std::pair< return false; } -void Syntax::registerStructTypeDescSyntax() +StructTypeSyntaxPtr Syntax::createStructSyntax(const string& structTypeName, const string& defaultValue, + const string& uniformDefaultValue, const string& typeAlias, + const string& typeDefinition) const { - for (const auto& typeName : StructTypeDesc::getStructTypeNames()) - { - const auto& typeDesc = TypeDesc::get(typeName); - const auto& structTypeDesc = StructTypeDesc::get(typeDesc.getStructIndex()); - - string structTypeName = typeName; - string defaultValue = typeName + "( "; - string uniformDefaultValue = EMPTY_STRING; - string typeAlias = EMPTY_STRING; - string typeDefinition = "struct " + structTypeName + " { "; - - for (const auto& x : structTypeDesc.getMembers()) - { - string memberName = x._name; - string memberType = x._typeDesc.getName(); - string memberDefaultValue = x._defaultValueStr; - - defaultValue += memberDefaultValue + ", "; - typeDefinition += memberType + " " + memberName + "; "; - } - - typeDefinition += " };"; - defaultValue += " )"; - - registerTypeSyntax(typeDesc, createStructSyntax(structTypeName, defaultValue, uniformDefaultValue, typeAlias, typeDefinition)); - } + return std::make_shared( + this, + structTypeName, + defaultValue, + uniformDefaultValue, + typeAlias, + typeDefinition); } const StringVec TypeSyntax::EMPTY_MEMBERS; -TypeSyntax::TypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, +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), @@ -242,9 +227,9 @@ string TypeSyntax::getValue(const ShaderPort* port, bool uniform) const return getValue(*port->getValue(), uniform); } -ScalarTypeSyntax::ScalarTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, +ScalarTypeSyntax::ScalarTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias, const string& typeDefinition) : - TypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, EMPTY_MEMBERS) + TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, EMPTY_MEMBERS) { } @@ -253,9 +238,9 @@ string ScalarTypeSyntax::getValue(const Value& value, bool /*uniform*/) const return value.getValueString(); } -StringTypeSyntax::StringTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, +StringTypeSyntax::StringTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias, const string& typeDefinition) : - ScalarTypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition) + ScalarTypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition) { } @@ -264,9 +249,9 @@ string StringTypeSyntax::getValue(const Value& value, bool /*uniform*/) const return "\"" + value.getValueString() + "\""; } -AggregateTypeSyntax::AggregateTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, +AggregateTypeSyntax::AggregateTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias, const string& typeDefinition, const StringVec& members) : - TypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) + TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) { } @@ -276,9 +261,9 @@ string AggregateTypeSyntax::getValue(const Value& value, bool /*uniform*/) const return valueString.empty() ? valueString : getName() + "(" + valueString + ")"; } -StructTypeSyntax::StructTypeSyntax(const Syntax* parentSyntax, const string& name, const string& defaultValue, const string& uniformDefaultValue, +StructTypeSyntax::StructTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias, const string& typeDefinition, const StringVec& members) : - TypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members), _parentSyntax(parentSyntax) + TypeSyntax(parent, name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members) { } @@ -295,10 +280,10 @@ string StructTypeSyntax::getValue(const Value& value, bool /*uniform*/) const separator = ";"; const string& memberTypeName = memberValue->getTypeString(); - TypeDesc memberTypeDesc = TypeDesc::get(memberTypeName); + TypeDesc memberTypeDesc = _parent->getType(memberTypeName); // Recursively use the syntax to generate the output, so we can support nested structs. - const string valueStr = _parentSyntax->getValue(memberTypeDesc, *memberValue, true); + const string valueStr = _parent->getValue(memberTypeDesc, *memberValue, true); result += valueStr; } diff --git a/source/MaterialXGenShader/Syntax.h b/source/MaterialXGenShader/Syntax.h index 5faafd002a..3d580f9300 100644 --- a/source/MaterialXGenShader/Syntax.h +++ b/source/MaterialXGenShader/Syntax.h @@ -70,8 +70,6 @@ class MX_GENSHADER_API Syntax /// Multiple calls will add to the internal set of tokens. void registerInvalidTokens(const StringMap& tokens); - virtual void registerStructTypeDescSyntax(); - /// Returns a set of names that are reserved words for this language syntax. const StringSet& getReservedWords() const { return _reservedWords; } @@ -86,6 +84,9 @@ class MX_GENSHADER_API Syntax /// Returns an array of all registered type syntax objects const vector& getTypeSyntaxes() const { return _typeSyntaxes; } + /// Return a type description for the given type name. + TypeDesc getType(const string& name) const { return _typeSystem->getType(name); } + /// Returns the name syntax of the given type const string& getTypeName(TypeDesc type) const; [[deprecated]] const string& getTypeName(const TypeDesc* type) const { return getTypeName(*type); } @@ -195,6 +196,11 @@ class MX_GENSHADER_API Syntax virtual bool remapEnumeration(const string& value, TypeDesc type, const string& enumNames, std::pair& result) const; + // Create and return a type syntax for a struct type. + virtual StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue, + const string& uniformDefaultValue, const string& typeAlias, + const string& typeDefinition) const; + /// Constants with commonly used strings. static const string NEWLINE; static const string SEMICOLON; @@ -202,21 +208,9 @@ class MX_GENSHADER_API Syntax protected: /// Protected constructor - Syntax(); - - virtual StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue, - const string& uniformDefaultValue, const string& typeAlias, - const string& typeDefinition) const - { - return std::make_shared( - this, - structTypeName, - defaultValue, - uniformDefaultValue, - typeAlias, - typeDefinition); - } + Syntax(TypeSystemPtr typeSystem); + TypeSystemPtr _typeSystem; vector _typeSyntaxes; std::unordered_map _typeSyntaxIndexByType; @@ -266,9 +260,10 @@ class MX_GENSHADER_API TypeSyntax protected: /// Protected constructor - TypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + TypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias, const string& typeDefinition, const StringVec& members); + const Syntax* _parent; // parent syntax class string _name; // type name string _defaultValue; // default value syntax string _uniformDefaultValue; // default value syntax when assigned to uniforms @@ -283,7 +278,7 @@ class MX_GENSHADER_API TypeSyntax class MX_GENSHADER_API ScalarTypeSyntax : public TypeSyntax { public: - ScalarTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + ScalarTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING); string getValue(const Value& value, bool uniform) const override; @@ -293,7 +288,7 @@ class MX_GENSHADER_API ScalarTypeSyntax : public TypeSyntax class MX_GENSHADER_API StringTypeSyntax : public ScalarTypeSyntax { public: - StringTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + StringTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING); string getValue(const Value& value, bool uniform) const override; @@ -303,25 +298,22 @@ class MX_GENSHADER_API StringTypeSyntax : public ScalarTypeSyntax class MX_GENSHADER_API AggregateTypeSyntax : public TypeSyntax { public: - AggregateTypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue, + AggregateTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING, const StringVec& members = EMPTY_MEMBERS); string getValue(const Value& value, bool uniform) const override; }; -/// Specialization of TypeSyntax for aggregate types. +/// Specialization of TypeSyntax for struct types. class MX_GENSHADER_API StructTypeSyntax : public TypeSyntax { public: - StructTypeSyntax(const Syntax* parentSyntax, const string& name, const string& defaultValue, const string& uniformDefaultValue, + StructTypeSyntax(const Syntax* parent, const string& name, const string& defaultValue, const string& uniformDefaultValue, const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING, const StringVec& members = EMPTY_MEMBERS); string getValue(const Value& value, bool uniform) const override; - - protected: - const Syntax* _parentSyntax; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/TypeDesc.cpp b/source/MaterialXGenShader/TypeDesc.cpp index 5ea0e31764..fe58364aad 100644 --- a/source/MaterialXGenShader/TypeDesc.cpp +++ b/source/MaterialXGenShader/TypeDesc.cpp @@ -9,206 +9,119 @@ MATERIALX_NAMESPACE_BEGIN -namespace -{ - -using TypeDescMap = std::unordered_map; -using TypeDescNameMap = std::unordered_map; - -// Internal storage of registered type descriptors -TypeDescMap& typeMap() -{ - static TypeDescMap map; - return map; -} - -TypeDescNameMap& typeNameMap() -{ - static TypeDescNameMap map; - return map; -} - -using StructTypeDescStorage = vector; -StructTypeDescStorage& structTypeStorage() -{ - // TODO: Our use of the singleton pattern for TypeDescMap and StructTypeDestStorage - // is not thread-safe, and we should consider replacing this with thread-local - // data in the GenContext object. - static StructTypeDescStorage storage; - return storage; -} - -} // anonymous namespace - const string TypeDesc::NONE_TYPE_NAME = "none"; const string& TypeDesc::getName() const { - TypeDescNameMap& typenames = typeNameMap(); - auto it = typenames.find(_id); - return it != typenames.end() ? it->second : NONE_TYPE_NAME; + return _data ? _data->getName() : NONE_TYPE_NAME; } -TypeDesc TypeDesc::get(const string& name) +const StructMemberDescVecPtr TypeDesc::getStructMembers() const { - TypeDescMap& types = typeMap(); - auto it = types.find(name); - return it != types.end() ? it->second : Type::NONE; -} - -void TypeDesc::remove(const string& name) -{ - TypeDescNameMap& typenames = typeNameMap(); - - TypeDescMap& types = typeMap(); - - auto it = types.find(name); - if (it == types.end()) - return; - - typenames.erase(it->second.typeId()); - types.erase(it); + return _data ? _data->getStructMembers() : StructMemberDescVecPtr(); } ValuePtr TypeDesc::createValueFromStrings(const string& value) const { - ValuePtr newValue = Value::createValueFromStrings(value, getName()); if (!isStruct()) - return newValue; + { + return Value::createValueFromStrings(value, getName()); + } // Value::createValueFromStrings() can only create a valid Value for a struct if it is passed // the optional TypeDef argument, otherwise it just returns a "string" typed Value. // So if this is a struct type we need to create a new AggregateValue. - StringVec subValues = parseStructValueString(value); - - AggregateValuePtr result = AggregateValue::createAggregateValue(getName()); - auto structTypeDesc = StructTypeDesc::get(getStructIndex()); - const auto& members = structTypeDesc.getMembers(); - - if (subValues.size() != members.size()) + const StringVec subValues = parseStructValueString(value); + auto structMembers = getStructMembers(); + if (!structMembers || (subValues.size() != structMembers->size())) { std::stringstream ss; - ss << "Wrong number of initializers - expect " << members.size(); + ss << "Wrong number of initializers for struct type " << getName(); throw ExceptionShaderGenError(ss.str()); } - for (size_t i = 0; i < members.size(); ++i) + AggregateValuePtr result = AggregateValue::createAggregateValue(getName()); + for (size_t i = 0; i < structMembers->size(); ++i) { - result->appendValue( members[i]._typeDesc.createValueFromStrings(subValues[i])); + result->appendValue(structMembers->at(i).getType().createValueFromStrings(subValues[i])); } return result; } -TypeDescRegistry::TypeDescRegistry(TypeDesc type, const string& name) +TypeSystem::TypeSystem() { - TypeDescMap& types = typeMap(); - TypeDescNameMap& typenames = typeNameMap(); - types[name] = type; - typenames[type.typeId()] = name; + // Register all the standard types. + registerType(Type::BOOLEAN); + registerType(Type::INTEGER); + registerType(Type::INTEGERARRAY); + registerType(Type::FLOAT); + registerType(Type::FLOATARRAY); + registerType(Type::VECTOR2); + registerType(Type::VECTOR3); + registerType(Type::VECTOR4); + registerType(Type::COLOR3); + registerType(Type::COLOR4); + registerType(Type::MATRIX33); + registerType(Type::MATRIX44); + registerType(Type::STRING); + registerType(Type::FILENAME); + registerType(Type::BSDF); + registerType(Type::EDF); + registerType(Type::VDF); + registerType(Type::SURFACESHADER); + registerType(Type::VOLUMESHADER); + registerType(Type::DISPLACEMENTSHADER); + registerType(Type::LIGHTSHADER); + registerType(Type::MATERIAL); } -namespace Type +TypeSystemPtr TypeSystem::create() { - -/// -/// Register type descriptors for standard types. -/// -TYPEDESC_REGISTER_TYPE(NONE, "none") -TYPEDESC_REGISTER_TYPE(BOOLEAN, "boolean") -TYPEDESC_REGISTER_TYPE(INTEGER, "integer") -TYPEDESC_REGISTER_TYPE(INTEGERARRAY, "integerarray") -TYPEDESC_REGISTER_TYPE(FLOAT, "float") -TYPEDESC_REGISTER_TYPE(FLOATARRAY, "floatarray") -TYPEDESC_REGISTER_TYPE(VECTOR2, "vector2") -TYPEDESC_REGISTER_TYPE(VECTOR3, "vector3") -TYPEDESC_REGISTER_TYPE(VECTOR4, "vector4") -TYPEDESC_REGISTER_TYPE(COLOR3, "color3") -TYPEDESC_REGISTER_TYPE(COLOR4, "color4") -TYPEDESC_REGISTER_TYPE(MATRIX33, "matrix33") -TYPEDESC_REGISTER_TYPE(MATRIX44, "matrix44") -TYPEDESC_REGISTER_TYPE(STRING, "string") -TYPEDESC_REGISTER_TYPE(FILENAME, "filename") -TYPEDESC_REGISTER_TYPE(BSDF, "BSDF") -TYPEDESC_REGISTER_TYPE(EDF, "EDF") -TYPEDESC_REGISTER_TYPE(VDF, "VDF") -TYPEDESC_REGISTER_TYPE(SURFACESHADER, "surfaceshader") -TYPEDESC_REGISTER_TYPE(VOLUMESHADER, "volumeshader") -TYPEDESC_REGISTER_TYPE(DISPLACEMENTSHADER, "displacementshader") -TYPEDESC_REGISTER_TYPE(LIGHTSHADER, "lightshader") -TYPEDESC_REGISTER_TYPE(MATERIAL, "material") - -} // namespace Type - -// -// StructTypeDesc methods -// - -void StructTypeDesc::addMember(const string& name, TypeDesc type, const string& defaultValueStr) -{ - _members.emplace_back(StructTypeDesc::StructMemberTypeDesc(name, type, defaultValueStr)); -} - -vector StructTypeDesc::getStructTypeNames() -{ - StructTypeDescStorage& structs = structTypeStorage(); - vector structNames; - for (const auto& x : structs) - { - structNames.emplace_back(x.typeDesc().getName()); - } - return structNames; + return TypeSystemPtr(new TypeSystem()); } -StructTypeDesc& StructTypeDesc::get(unsigned int index) +void TypeSystem::registerType(TypeDesc type) { - StructTypeDescStorage& structs = structTypeStorage(); - return structs[index]; -} - -uint16_t StructTypeDesc::emplace_back(StructTypeDesc structTypeDesc) -{ - StructTypeDescStorage& structs = structTypeStorage(); - if (structs.size() >= std::numeric_limits::max()) + auto it = _typesByName.find(type.getName()); + if (it != _typesByName.end()) { - throw ExceptionShaderGenError("Maximum number of custom struct types has been exceeded."); + // A type with this name is already registered, + // so replace it with the new registration. + size_t i = 0; + for (const TypeDesc t : _types) + { + if (t == type) + { + _types[i] = type; + _typesByName[type.getName()] = type; + break; + } + ++i; + } } - uint16_t index = static_cast(structs.size()); - structs.emplace_back(structTypeDesc); - return index; -} - -void StructTypeDesc::clear() -{ - StructTypeDescStorage& structs = structTypeStorage(); - for (const auto& structType: structs) + else { - // Need to add typeID to structTypeDesc - and use it here to reference back to typeDesc obj and remove it. - TypeDesc::remove(structType.typeDesc().getName()); + _types.push_back(type); + _typesByName[type.getName()] = type; } - structs.clear(); } -const string& StructTypeDesc::getName() const +void TypeSystem::registerType(const string& name, uint8_t basetype, uint8_t semantic, uint16_t size, StructMemberDescVecPtr members) { - return _typedesc.getName(); -} + // Allocate a data block for the new type description. + TypeDesc::DataBlockPtr data = std::make_shared(name, members); + _dataBlocks.push_back(data); -const vector& StructTypeDesc::getMembers() const -{ - return _members; -} - -TypeDesc createStructTypeDesc(std::string_view name) -{ - return {name, TypeDesc::BASETYPE_STRUCT}; + // Register the new type + registerType(TypeDesc(name, basetype, semantic, size, data.get())); } -void registerStructTypeDesc(std::string_view name) +TypeDesc TypeSystem::getType(const string& name) const { - auto structTypeDesc = createStructTypeDesc(name); - TypeDescRegistry register_struct(structTypeDesc, string(name)); + auto it = _typesByName.find(name); + return (it != _typesByName.end() ? it->second : Type::NONE); } MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/TypeDesc.h b/source/MaterialXGenShader/TypeDesc.h index b61c598caf..091da7547a 100644 --- a/source/MaterialXGenShader/TypeDesc.h +++ b/source/MaterialXGenShader/TypeDesc.h @@ -11,26 +11,30 @@ #include #include +#include #include MATERIALX_NAMESPACE_BEGIN +class TypeDesc; +class StructMemberDesc; +using TypeDescVec = vector; +using TypeDescMap = std::unordered_map; +using StructMemberDescVec = vector; +using StructMemberDescVecPtr = shared_ptr; + /// @class TypeDesc /// A type descriptor for MaterialX data types. /// /// All types need to have a type descriptor registered in order for shader generators /// to know about the type. It can be used for type comparisons as well as getting more /// information about the type. Type descriptors for all standard library data types are -/// registered by default and can be accessed from the Type namespace, e.g. Type::FLOAT. -/// -/// To register custom types use the macro TYPEDESC_DEFINE_TYPE to define it in a header -/// and the macro TYPEDESC_REGISTER_TYPE to register it in the type registry. Registration -/// must be done in order to access the type's name later using getName() and to find the -/// type by name using TypeDesc::get(). -/// -/// The class is a POD type of 64-bits and can efficiently be stored and passed by value. -/// Type compare operations and hash operations are done using a precomputed hash value. +/// defined by default and can be accessed from the Type namespace, e.g. Type::FLOAT. +/// Custom struct types defined through typedef elements in a data library are loaded in +/// and registered by calling the ShaderGenerator::registerTypeDefs method. The TypeSystem +/// class, see below, is used to manage all type descriptions. It can be used to query the +/// registered types. /// class MX_GENSHADER_API TypeDesc { @@ -60,23 +64,39 @@ class MX_GENSHADER_API TypeDesc SEMANTIC_LAST }; + /// Data block holding large data needed by the type description. + class DataBlock + { + public: + DataBlock(const string& name, const StructMemberDescVecPtr members = nullptr) noexcept : _name(name), _members(members) {} + + const string& getName() const { return _name; } + const StructMemberDescVecPtr getStructMembers() const { return _members; } + + private: + const string _name; + const StructMemberDescVecPtr _members; + }; + + using DataBlockPtr = std::shared_ptr; + /// Empty constructor. constexpr TypeDesc() noexcept : _id(0), _basetype(BASETYPE_NONE), _semantic(SEMANTIC_NONE), _size(0), - _structIndex(0) + _data(nullptr) { } /// Constructor. - constexpr TypeDesc(std::string_view name, uint8_t basetype, uint8_t semantic = SEMANTIC_NONE, uint16_t size = 1, uint16_t structIndex = 0) noexcept : + constexpr TypeDesc(std::string_view name, uint8_t basetype, uint8_t semantic, uint16_t size, const DataBlock* data) noexcept : _id(constexpr_hash(name)), // Note: We only store the hash to keep the class size minimal. _basetype(basetype), _semantic(semantic), _size(size), - _structIndex(structIndex) + _data(data) { } @@ -123,8 +143,9 @@ class MX_GENSHADER_API TypeDesc /// Return true if the type represents a struct. bool isStruct() const { return _basetype == BASETYPE_STRUCT; } - /// Return the index for the struct member information in StructTypeDesc, the result is invalid if `isStruct()` returns false. - uint16_t getStructIndex() const { return _structIndex; } + /// Return a pointer to the struct member description. + /// Will return nullptr if this is not a struct type. + const StructMemberDescVecPtr getStructMembers() const; /// Equality operator bool operator==(TypeDesc rhs) const @@ -153,13 +174,6 @@ class MX_GENSHADER_API TypeDesc } }; - /// Return a type description by name. - /// If no type is found Type::NONE is returned. - static TypeDesc get(const string& name); - - /// Remove a type description by name, if it exists. - static void remove(const string& name); - static const string NONE_TYPE_NAME; /// Create a Value from a string for a given typeDesc @@ -177,25 +191,71 @@ class MX_GENSHADER_API TypeDesc uint8_t _basetype; uint8_t _semantic; uint16_t _size; - uint16_t _structIndex; + const DataBlock* _data; }; -/// @class TypeDescRegistry -/// Helper class for type registration. -class MX_GENSHADER_API TypeDescRegistry +/// @class StructMemberDesc +/// Type descriptor for member of a struct type. +class StructMemberDesc { - public: - TypeDescRegistry(TypeDesc type, const string& name); +public: + StructMemberDesc(TypeDesc type, const string& name, const string& defaultValueStr) : + _type(type), + _name(name), + _defaultValueStr(defaultValueStr) + { + } + + TypeDesc getType() const { return _type; } + const string& getName() const { return _name; } + const string& getDefaultValueStr() const { return _defaultValueStr; } + +private: + const TypeDesc _type; + const string _name; + const string _defaultValueStr; +}; + +using TypeSystemPtr = shared_ptr; + +/// @class TypeSystem +/// Class handling registration, storage and query of type descriptions. +class MX_GENSHADER_API TypeSystem +{ +public: + /// Create a new type system. + static TypeSystemPtr create(); + + /// Register an existing type decription. + void registerType(TypeDesc type); + + /// Create and register a new type description. + void registerType(const string& name, uint8_t basetype, uint8_t semantic, uint16_t size, StructMemberDescVecPtr members = nullptr); + + /// Return a type description by name. + /// If no type is found Type::NONE is returned. + TypeDesc getType(const string& name) const; + + /// Return all registered type descriptions. + const TypeDescVec& getTypes() const + { + return _types; + } + +protected: + // Protected constructor + TypeSystem(); + +private: + TypeDescVec _types; + TypeDescMap _typesByName; + vector _dataBlocks; }; /// Macro to define global type descriptions for commonly used types. #define TYPEDESC_DEFINE_TYPE(T, name, basetype, semantic, size) \ - static constexpr TypeDesc T(name, basetype, semantic, size); - -/// Macro to register a previously defined type in the type registry. -/// Registration must be done in order for the type to be searchable by name. -#define TYPEDESC_REGISTER_TYPE(T, name) \ - TypeDescRegistry register_##T(T, name); + inline const TypeDesc::DataBlock* T##_data() { static const TypeDesc::DataBlock _data(name); return &_data; } \ + static const TypeDesc T(name, basetype, semantic, size, T##_data()); namespace Type { @@ -229,60 +289,6 @@ TYPEDESC_DEFINE_TYPE(MATERIAL, "material", TypeDesc::BASETYPE_NONE, TypeDesc::SE } // namespace Type - -/// @class StructTypeDesc -/// A type descriptor for MaterialX struct types. -/// -/// All types need to have a type descriptor registered in order for shader generators -/// to know about the type. If the type represented is of basetype=BASETYPE_STRUCT then -/// the type also needs to have an associated StructTypeDesc that describes the members -/// of the struct. -/// -class MX_GENSHADER_API StructTypeDesc -{ - public: - struct StructMemberTypeDesc - { - StructMemberTypeDesc(string name, TypeDesc typeDesc, string defaultValueStr) : - _name(name), _typeDesc(typeDesc), _defaultValueStr(defaultValueStr) - { - } - string _name; - TypeDesc _typeDesc; - string _defaultValueStr; - }; - - /// Empty constructor. - StructTypeDesc() noexcept{} - - void addMember(const string& name, TypeDesc type, const string& defaultValueStr); - void setTypeDesc(TypeDesc typedesc) { _typedesc = typedesc; } - - /// Return a type description by index. - static StructTypeDesc& get(unsigned int index); - static vector getStructTypeNames(); - static uint16_t emplace_back(StructTypeDesc structTypeDesc); - static void clear(); - - TypeDesc typeDesc() const { return _typedesc; } - - const string& getName() const; - - const vector& getMembers() const; - - private: - TypeDesc _typedesc; - vector _members; -}; - -/// @class StructTypeDescRegistry -/// Helper class for struct type registration. -class MX_GENSHADER_API StructTypeDescRegistry -{ - public: - StructTypeDescRegistry(); -}; - MATERIALX_NAMESPACE_END #endif diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index 76692f64d3..55982968a5 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -228,8 +228,7 @@ bool isTransparentShaderGraph(OutputPtr output, const string& target, NodePtr in NodeDefPtr nodeDef = node->getNodeDef(); if (nodeDef) { - const TypeDesc nodeDefType = TypeDesc::get(nodeDef->getType()); - if (nodeDefType == Type::BSDF) + if (nodeDef->getType() == BSDF_TYPE_STRING) { InterfaceElementPtr impl = nodeDef->getImplementation(target); if (impl && impl->isA()) diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index fe419c7908..7861012761 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -621,8 +621,8 @@ void RenderView::initContext(mx::GenContext& context) context.getShaderGenerator().setUnitSystem(unitSystem); context.getOptions().targetDistanceUnit = "meter"; - // Register struct type definitions - context.getShaderGenerator().loadStructTypeDefs(_document); + // Register type definitions. + context.getShaderGenerator().registerTypeDefs(_document); } void RenderView::drawContents() diff --git a/source/MaterialXRender/LightHandler.cpp b/source/MaterialXRender/LightHandler.cpp index 0b841e5dc8..a0db622052 100644 --- a/source/MaterialXRender/LightHandler.cpp +++ b/source/MaterialXRender/LightHandler.cpp @@ -41,8 +41,7 @@ void LightHandler::findLights(DocumentPtr doc, vector& lights) lights.clear(); for (NodePtr node : doc->getNodes()) { - const TypeDesc type = TypeDesc::get(node->getType()); - if (type == Type::LIGHTSHADER) + if (node->getType() == LIGHT_SHADER_TYPE_STRING) { lights.push_back(node); } diff --git a/source/MaterialXRender/TextureBaker.inl b/source/MaterialXRender/TextureBaker.inl index ff05cb49e7..55a0711292 100644 --- a/source/MaterialXRender/TextureBaker.inl +++ b/source/MaterialXRender/TextureBaker.inl @@ -498,7 +498,8 @@ DocumentPtr TextureBaker::bakeMaterialToDoc(DocumentPtr doc DefaultColorManagementSystemPtr cms = DefaultColorManagementSystem::create(genContext.getShaderGenerator().getTarget()); cms->loadLibrary(doc); genContext.registerSourceCodeSearchPath(searchPath); - genContext.getShaderGenerator().setColorManagementSystem(cms); + _generator->setColorManagementSystem(cms); + _generator->registerTypeDefs(doc); // Compute the material tag set. StringVec materialTags = udimSet; diff --git a/source/MaterialXRender/Util.cpp b/source/MaterialXRender/Util.cpp index 9aab6b4811..89c6e4f0a8 100644 --- a/source/MaterialXRender/Util.cpp +++ b/source/MaterialXRender/Util.cpp @@ -157,12 +157,17 @@ unsigned int getUIProperties(InputPtr input, const string& target, UIProperties& if (!enumValuesAttr.empty()) { const string COMMA_SEPARATOR = ","; - const TypeDesc typeDesc = TypeDesc::get(input->getType()); string valueString; size_t index = 0; - for (const string& val : splitString(enumValuesAttr, COMMA_SEPARATOR)) + vector enumValuesParts = splitString(enumValuesAttr, COMMA_SEPARATOR); + + // Infer the size of the type by making an assumption the correct number of elements + // are provided in the value. + size_t typeDescSize = enumValuesParts.size() / uiProperties.enumeration.size(); + + for (const string& val : enumValuesParts) { - if (index < typeDesc.getSize() - 1) + if (index < typeDescSize - 1) { valueString += val + COMMA_SEPARATOR; index++; @@ -170,7 +175,7 @@ unsigned int getUIProperties(InputPtr input, const string& target, UIProperties& else { valueString += val; - uiProperties.enumerationValues.push_back(typeDesc.createValueFromStrings(valueString)); + uiProperties.enumerationValues.push_back(Value::createValueFromStrings(valueString, input->getType())); valueString.clear(); index = 0; } diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 29ee9ecebe..4a626075f9 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -1006,19 +1006,20 @@ const GlslProgram::InputMap& GlslProgram::updateUniformsList() } else { - // If we're a struct - we need to loop over each member - auto structTypeDesc = StructTypeDesc::get(typedesc.getStructIndex()); - auto aggregateValue = std::static_pointer_cast(variableValue); - - const auto& members = structTypeDesc.getMembers(); - for (size_t i = 0, n = members.size(); i < n; ++i) + auto variableStructMembers = typedesc.getStructMembers(); + if (variableStructMembers) { - const auto& member = members[i]; - auto memberTypeDesc = member._typeDesc; - auto memberVariableName = variableName + "." + member._name; - auto memberVariableValue = aggregateValue->getMemberValue(i); + // If we're a struct - we need to loop over each member + auto aggregateValue = std::static_pointer_cast(variableValue); + + for (size_t i = 0, n = variableStructMembers->size(); i < n; ++i) + { + const auto& structMember = variableStructMembers->at(i); + auto memberVariableName = variableName + "." + structMember.getName(); + auto memberVariableValue = aggregateValue->getMemberValue(i); - populateUniformInput_ref(memberTypeDesc, memberVariableName, memberVariableValue, populateUniformInput_ref); + populateUniformInput_ref(structMember.getType(), memberVariableName, memberVariableValue, populateUniformInput_ref); + } } } }; diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 470fa549b2..b9140771a8 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -1094,17 +1094,16 @@ int GetStrideOfMetalType(MTLDataType type) } else { - auto structTypeDesc = StructTypeDesc::get(variableTypeDesc.getStructIndex()); auto aggregateValue = std::static_pointer_cast(variableValue); - const auto& members = structTypeDesc.getMembers(); - for (size_t i = 0, n = members.size(); i < n; ++i) + const auto& members = variableTypeDesc.getStructMembers(); + for (size_t i = 0, n = members->size(); i < n; ++i) { - const auto& structMember = members[i]; - auto memberVariableName = variableName+"."+structMember._name; + const auto& structMember = members->at(i); + auto memberVariableName = variableName + "." + structMember.getName(); auto memberVariableValue = aggregateValue->getMemberValue(i); - populateUniformInput_ref(structMember._typeDesc, memberVariableName, memberVariableValue, populateUniformInput_ref); + populateUniformInput_ref(structMember.getType(), memberVariableName, memberVariableValue, populateUniformInput_ref); } } }; diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp index 979320bd91..72e39c78da 100644 --- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp +++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp @@ -18,7 +18,8 @@ namespace mx = MaterialX; TEST_CASE("GenShader: GLSL Syntax Check", "[genglsl]") { - mx::SyntaxPtr syntax = mx::GlslSyntax::create(); + mx::TypeSystemPtr ts = mx::TypeSystem::create(); + mx::SyntaxPtr syntax = mx::GlslSyntax::create(ts); REQUIRE(syntax->getTypeName(mx::Type::FLOAT) == "float"); REQUIRE(syntax->getTypeName(mx::Type::COLOR3) == "vec3"); @@ -105,6 +106,7 @@ TEST_CASE("GenShader: GLSL Light Shaders", "[genglsl]") mx::GenContext context(mx::GlslShaderGenerator::create()); context.registerSourceCodeSearchPath(searchPath); + context.getShaderGenerator().registerTypeDefs(doc); mx::HwShaderGenerator::bindLightShader(*pointLightShader, 42, context); REQUIRE_THROWS(mx::HwShaderGenerator::bindLightShader(*spotLightShader, 42, context)); diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index 610b237163..a182d206f6 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -23,7 +23,8 @@ namespace mx = MaterialX; TEST_CASE("GenShader: MDL Syntax", "[genmdl]") { - mx::SyntaxPtr syntax = mx::MdlSyntax::create(); + mx::TypeSystemPtr ts = mx::TypeSystem::create(); + mx::SyntaxPtr syntax = mx::MdlSyntax::create(ts); REQUIRE(syntax->getTypeName(mx::Type::FLOAT) == "float"); REQUIRE(syntax->getTypeName(mx::Type::COLOR3) == "color"); diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp index 32baaec5f0..762cfbd19a 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp @@ -21,12 +21,12 @@ namespace mx = MaterialX; TEST_CASE("GenShader: MSL Syntax Check", "[genmsl]") { - mx::SyntaxPtr syntax = mx::MslSyntax::create(); + mx::TypeSystemPtr ts = mx::TypeSystem::create(); + mx::SyntaxPtr syntax = mx::MslSyntax::create(ts); REQUIRE(syntax->getTypeName(mx::Type::FLOAT) == "float"); REQUIRE(syntax->getTypeName(mx::Type::COLOR3) == "vec3"); REQUIRE(syntax->getTypeName(mx::Type::VECTOR3) == "vec3"); - REQUIRE(syntax->getTypeName(mx::Type::BSDF) == "BSDF"); REQUIRE(syntax->getOutputTypeName(mx::Type::BSDF) == "thread BSDF&"); diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp index 6e613c85b8..95e0638fc7 100644 --- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp +++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp @@ -20,7 +20,8 @@ namespace mx = MaterialX; TEST_CASE("GenShader: OSL Syntax", "[genosl]") { - mx::SyntaxPtr syntax = mx::OslSyntax::create(); + mx::TypeSystemPtr ts = mx::TypeSystem::create(); + mx::SyntaxPtr syntax = mx::OslSyntax::create(ts); REQUIRE(syntax->getTypeName(mx::Type::FLOAT) == "float"); REQUIRE(syntax->getTypeName(mx::Type::COLOR3) == "color"); @@ -165,7 +166,7 @@ TEST_CASE("GenShader: OSL Metadata", "[genosl]") REQUIRE(stdSurf1 != nullptr); mx::ShaderGeneratorPtr generator = mx::OslShaderGenerator::create(); - mx::GenContext context(mx::OslShaderGenerator::create()); + mx::GenContext context(generator); context.registerSourceCodeSearchPath(searchPath); // Metadata to export must be registered in the context before shader generation starts. diff --git a/source/MaterialXTest/MaterialXGenShader/GenShader.cpp b/source/MaterialXTest/MaterialXGenShader/GenShader.cpp index a959283aad..83b226ffc9 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShader.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShader.cpp @@ -73,22 +73,25 @@ TEST_CASE("GenShader: Valid Libraries", "[genshader]") TEST_CASE("GenShader: TypeDesc Check", "[genshader]") { + mx::TypeSystemPtr ts = mx::TypeSystem::create(); + mx::GenContext context(mx::GlslShaderGenerator::create(ts)); + // Make sure the standard types are registered - const mx::TypeDesc floatType = mx::TypeDesc::get("float"); + const mx::TypeDesc floatType = ts->getType("float"); REQUIRE(floatType != mx::Type::NONE); REQUIRE(floatType.getBaseType() == mx::TypeDesc::BASETYPE_FLOAT); - const mx::TypeDesc integerType = mx::TypeDesc::get("integer"); + const mx::TypeDesc integerType = ts->getType("integer"); REQUIRE(integerType != mx::Type::NONE); REQUIRE(integerType.getBaseType() == mx::TypeDesc::BASETYPE_INTEGER); - const mx::TypeDesc booleanType = mx::TypeDesc::get("boolean"); + const mx::TypeDesc booleanType = ts->getType("boolean"); REQUIRE(booleanType != mx::Type::NONE); REQUIRE(booleanType.getBaseType() == mx::TypeDesc::BASETYPE_BOOLEAN); - const mx::TypeDesc color3Type = mx::TypeDesc::get("color3"); + const mx::TypeDesc color3Type = ts->getType("color3"); REQUIRE(color3Type != mx::Type::NONE); REQUIRE(color3Type.getBaseType() == mx::TypeDesc::BASETYPE_FLOAT); REQUIRE(color3Type.getSemantic() == mx::TypeDesc::SEMANTIC_COLOR); REQUIRE(color3Type.isFloat3()); - const mx::TypeDesc color4Type = mx::TypeDesc::get("color4"); + const mx::TypeDesc color4Type = ts->getType("color4"); REQUIRE(color4Type != mx::Type::NONE); REQUIRE(color4Type.getBaseType() == mx::TypeDesc::BASETYPE_FLOAT); REQUIRE(color4Type.getSemantic() == mx::TypeDesc::SEMANTIC_COLOR); @@ -96,12 +99,19 @@ TEST_CASE("GenShader: TypeDesc Check", "[genshader]") // Make sure we can register a new custom type const std::string fooTypeName = "foo"; - mx::TypeDescRegistry reg(mx::TypeDesc(fooTypeName, mx::TypeDesc::BASETYPE_FLOAT, mx::TypeDesc::SEMANTIC_COLOR, 5), fooTypeName); - const mx::TypeDesc fooType = mx::TypeDesc::get(fooTypeName); + ts->registerType(fooTypeName, mx::TypeDesc::BASETYPE_FLOAT, mx::TypeDesc::SEMANTIC_COLOR, 5); + mx::TypeDesc fooType = ts->getType(fooTypeName); + REQUIRE(fooType != mx::Type::NONE); + REQUIRE(fooType.getSemantic() == mx::TypeDesc::SEMANTIC_COLOR); + + // Make sure we can register a new type replacing an old type + ts->registerType(fooTypeName, mx::TypeDesc::BASETYPE_INTEGER, mx::TypeDesc::SEMANTIC_VECTOR, 3); + fooType = ts->getType(fooTypeName); REQUIRE(fooType != mx::Type::NONE); + REQUIRE(fooType.getSemantic() == mx::TypeDesc::SEMANTIC_VECTOR); // Make sure we can't request an unknown type - REQUIRE(mx::TypeDesc::get("bar") == mx::Type::NONE); + REQUIRE(ts->getType("bar") == mx::Type::NONE); } TEST_CASE("GenShader: Shader Translation", "[translate]") diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index b206af6ee4..b91e11c222 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -378,6 +378,8 @@ void shaderGenPerformanceTest(mx::GenContext& context) REQUIRE(docValid == true); + context.getShaderGenerator().registerTypeDefs(doc); + mx::StringVec sourceCode; mx::ShaderPtr shader = nullptr; shader = context.getShaderGenerator().generate(elements[0]->getName(), elements[0], context); @@ -576,8 +578,7 @@ void ShaderGeneratorTester::findLights(mx::DocumentPtr doc, std::vectorgetNodes()) { - const mx::TypeDesc type = mx::TypeDesc::get(node->getType()); - if (type == mx::Type::LIGHTSHADER) + if (node->getType() == mx::LIGHT_SHADER_TYPE_STRING) { lights.push_back(node); } @@ -645,9 +646,6 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons addColorManagement(); addUnitSystem(); - // Register struct typedefs from the library files. - _shaderGenerator->loadStructTypeDefs(_dependLib); - // Test suite setup addSkipFiles(); @@ -704,8 +702,6 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons preprocessDocument(doc); _shaderGenerator->registerShaderMetadata(doc, context); - _shaderGenerator->loadStructTypeDefs(doc); - // For each new file clear the implementation cache. // Since the new file might contain implementations with names // colliding with implementations in previous test cases. @@ -734,6 +730,9 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons continue; } + // Register typedefs from the document. + _shaderGenerator->registerTypeDefs(doc); + // Find and register lights findLights(_dependLib, _lights); registerLights(_dependLib, _lights, context); diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index ec3d603284..cb75d17442 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -224,6 +224,10 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) context.clearNodeImplementations(); doc->setDataLibrary(dependLib); + + // Register types from the document. + _shaderGenerator->registerTypeDefs(doc); + ioTimer.endTimer(); validateTimer.startTimer(); diff --git a/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp b/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp index a682874126..3964222d14 100644 --- a/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp +++ b/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp @@ -47,6 +47,10 @@ TEST_CASE("GenReference: OSL Reference", "[genreference]") // Create shader generator. mx::ShaderGeneratorPtr generator = mx::OslShaderGenerator::create(); + + // Register types from the library. + generator->registerTypeDefs(stdlib); + mx::GenContext context(generator); context.getOptions().addUpstreamDependencies = false; context.registerSourceCodeSearchPath(searchPath); diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index aefdf2d401..d7e80a68c3 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -189,17 +189,18 @@ Viewer::Viewer(const std::string& materialFilename, _envCamera(mx::Camera::create()), _shadowCamera(mx::Camera::create()), _lightHandler(mx::LightHandler::create()), + _typeSystem(mx::TypeSystem::create()), #ifndef MATERIALXVIEW_METAL_BACKEND - _genContext(mx::GlslShaderGenerator::create()), - _genContextEssl(mx::EsslShaderGenerator::create()), + _genContext(mx::GlslShaderGenerator::create(_typeSystem)), + _genContextEssl(mx::EsslShaderGenerator::create(_typeSystem)), #else - _genContext(mx::MslShaderGenerator::create()), + _genContext(mx::MslShaderGenerator::create(_typeSystem)), #endif #if MATERIALX_BUILD_GEN_OSL - _genContextOsl(mx::OslShaderGenerator::create()), + _genContextOsl(mx::OslShaderGenerator::create(_typeSystem)), #endif #if MATERIALX_BUILD_GEN_MDL - _genContextMdl(mx::MdlShaderGenerator::create()), + _genContextMdl(mx::MdlShaderGenerator::create(_typeSystem)), #endif _unitRegistry(mx::UnitConverterRegistry::create()), _drawEnvironment(false), @@ -1315,6 +1316,9 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie // Apply modifiers to the content document. applyModifiers(doc, _modifiers); + // Register any data types in the document. + _genContext.getShaderGenerator().registerTypeDefs(doc); + // Flatten subgraphs if requested. if (_flattenSubgraphs) { @@ -1759,9 +1763,6 @@ void Viewer::initContext(mx::GenContext& context) unitSystem->setUnitConverterRegistry(_unitRegistry); context.getShaderGenerator().setUnitSystem(unitSystem); context.getOptions().targetDistanceUnit = "meter"; - - // Initialize the struct typedefs from the stdlib - context.getShaderGenerator().loadStructTypeDefs(_stdLib); } void Viewer::loadStandardLibraries() diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h index 8f0257e1e1..283aa98ab1 100644 --- a/source/MaterialXView/Viewer.h +++ b/source/MaterialXView/Viewer.h @@ -410,6 +410,9 @@ class Viewer : public ng::Screen mx::MaterialPtr _envMaterial; mx::MeshPtr _quadMesh; + // Type system + mx::TypeSystemPtr _typeSystem; + // Shader generator contexts mx::GenContext _genContext; #ifndef MATERIALXVIEW_METAL_BACKEND diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp index f26d4f2aee..91c85d09d3 100644 --- a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp @@ -20,8 +20,8 @@ namespace mx = MaterialX; void bindPyGlslShaderGenerator(py::module& mod) { py::class_(mod, "GlslShaderGenerator") - .def_static("create", &mx::GlslShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::GlslShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("generate", &mx::GlslShaderGenerator::generate) .def("getTarget", &mx::GlslShaderGenerator::getTarget) .def("getVersion", &mx::GlslShaderGenerator::getVersion); @@ -41,8 +41,8 @@ void bindPyGlslResourceBindingContext(py::module &mod) void bindPyEsslShaderGenerator(py::module& mod) { py::class_(mod, "EsslShaderGenerator") - .def_static("create", &mx::EsslShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::EsslShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("generate", &mx::EsslShaderGenerator::generate) .def("getTarget", &mx::EsslShaderGenerator::getTarget) .def("getVersion", &mx::EsslShaderGenerator::getVersion); @@ -53,8 +53,8 @@ void bindPyEsslShaderGenerator(py::module& mod) void bindPyVkShaderGenerator(py::module& mod) { py::class_(mod, "VkShaderGenerator") - .def_static("create", &mx::VkShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::VkShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("generate", &mx::VkShaderGenerator::generate) .def("getTarget", &mx::VkShaderGenerator::getTarget) .def("getVersion", &mx::VkShaderGenerator::getVersion); diff --git a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp index d0702cfff0..9d25f0b9af 100644 --- a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp @@ -14,7 +14,7 @@ namespace mx = MaterialX; void bindPyMdlShaderGenerator(py::module& mod) { py::class_(mod, "MdlShaderGenerator") - .def_static("create", &mx::MdlShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::MdlShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("getTarget", &mx::MdlShaderGenerator::getTarget); } diff --git a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp index 48259cad07..4862c062f4 100644 --- a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp @@ -18,8 +18,8 @@ namespace mx = MaterialX; void bindPyMslShaderGenerator(py::module& mod) { py::class_(mod, "MslShaderGenerator") - .def_static("create", &mx::MslShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::MslShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("generate", &mx::MslShaderGenerator::generate) .def("getTarget", &mx::MslShaderGenerator::getTarget) .def("getVersion", &mx::MslShaderGenerator::getVersion); diff --git a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp index 7c53002669..0630b6da8e 100644 --- a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp @@ -19,8 +19,8 @@ void bindPyOslShaderGenerator(py::module& mod) mod.attr("OSL_OUTPUTS") = mx::OSL::OUTPUTS; py::class_(mod, "OslShaderGenerator") - .def_static("create", &mx::OslShaderGenerator::create) - .def(py::init<>()) + .def_static("create", &mx::OslShaderGenerator::create, py::arg("typeSystem") = nullptr) + .def(py::init()) .def("getTarget", &mx::OslShaderGenerator::getTarget) .def("generate", &mx::OslShaderGenerator::generate); } diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyGenContext.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyGenContext.cpp index 11792f317c..ba58c6d6d6 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyGenContext.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyGenContext.cpp @@ -19,6 +19,7 @@ void bindPyGenContext(py::module& mod) .def(py::init()) .def("getShaderGenerator", &mx::GenContext::getShaderGenerator) .def("getOptions", static_cast(&mx::GenContext::getOptions), py::return_value_policy::reference) + .def("getTypeDesc", &mx::GenContext::getTypeDesc) .def("registerSourceCodeSearchPath", static_cast(&mx::GenContext::registerSourceCodeSearchPath)) .def("registerSourceCodeSearchPath", static_cast(&mx::GenContext::registerSourceCodeSearchPath)) .def("resolveSourceFile", &mx::GenContext::resolveSourceFile) diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyShaderGenerator.cpp index 0c8a086e58..fdf4b94aac 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyShaderGenerator.cpp @@ -22,7 +22,6 @@ void bindPyShaderGenerator(py::module& mod) .def("setUnitSystem", &mx::ShaderGenerator::setUnitSystem) .def("getUnitSystem", &mx::ShaderGenerator::getUnitSystem) .def("getTokenSubstitutions", &mx::ShaderGenerator::getTokenSubstitutions) - .def("loadStructTypeDefs", &mx::ShaderGenerator::loadStructTypeDefs) - .def("clearStructTypeDefs", &mx::ShaderGenerator::clearStructTypeDefs) + .def("registerTypeDefs", &mx::ShaderGenerator::registerTypeDefs) .def("registerShaderMetadata", &mx::ShaderGenerator::registerShaderMetadata); } diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyTypeDesc.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyTypeDesc.cpp index dc0a6c9fe8..b4084900e2 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyTypeDesc.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyTypeDesc.cpp @@ -16,7 +16,6 @@ void bindPyTypeDesc(py::module& mod) // by the container they are stored in and should not be destroyed when // garbage collected by the python interpreter py::class_>(mod, "TypeDesc") - .def_static("get", &mx::TypeDesc::get) .def("getName", &mx::TypeDesc::getName) .def("getBaseType", &mx::TypeDesc::getBaseType) .def("getSemantic", &mx::TypeDesc::getSemantic) @@ -28,4 +27,9 @@ void bindPyTypeDesc(py::module& mod) .def("isFloat3", &mx::TypeDesc::isFloat3) .def("isFloat4", &mx::TypeDesc::isFloat4) .def("isClosure", &mx::TypeDesc::isClosure); + + py::class_(mod, "TypeSystem") + .def_static("create", &mx::TypeSystem::create) + .def("getType", &mx::TypeSystem::getType) + .def("getTypes", &mx::TypeSystem::getTypes); }