Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data Library API #2054

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ashwinbhat
Copy link
Contributor

MaterialX documents are usually required to be complete self contained with all required node defintions. This is done by using the mx::importLibrary API. While processing large number of documents Import and Merge workflows can cause performance and memory challenges.

The MaterialX library aka Data library hosts defintions and thus could be referenced by a document instead of importing them.

A new set of methods have been introduced that allow registeration data library for a document.

  1. registerDataLibrary(ConstDocumentPtr dataLibrary);
  2. getRegisteredDataLibrary() const
  3. hasDataLibrary() const

Other changes include

  • Add DataLibrary support for getChildOfType and getChildrenOfType
  • Updates to redirect Document::get* calls to process datalibrary and local document.

MaterialX documents are usually required to be complete self contained with all required node defintions. This is done by using the mx::importLibrary API. While processing large number of documents Import and Merge workflows can cause performance and memory challenges.

The MaterialX library aka Data library hosts defintions and thus could be referenced by a document instead of importing them.

A new set of methods have been introduced that allow registeration data library for a document.

1. registerDataLibrary(ConstDocumentPtr dataLibrary);
2. getRegisteredDataLibrary() const
3. hasDataLibrary() const

Other changes include
- Add DataLibrary support for getChildOfType and getChildrenOfType
- Updates to redirect Document::get* calls to process datalibrary and local document.
Comment on lines -17 to -18
.def("_getChildOfType" #T, &mx::Element::getChildOfType<mx::T>) \
.def("_getChildrenOfType" #T, &mx::Element::getChildrenOfType<mx::T>, py::arg("category") = mx::EMPTY_STRING) \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bernardkwok @jstone-lucasfilm I need some guidance on these binding api
template <class T> shared_ptr<T> getChildOfType(ConstDocumentPtr datalibrary, const string& name) const
template <class T> shared_ptr<T> getChildOfType(const string& name) const

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ashwinbhat Initially I think it should be fine to omit these new Python bindings, while we're working out the details of the new API, and we can add these once the C++ API is locked down.

@@ -357,6 +357,14 @@ vector<OutputPtr> Document::getMaterialOutputs() const

vector<NodeDefPtr> Document::getMatchingNodeDefs(const string& nodeName) const
{
// Return all nodedefs from datalibrary if available
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ashwinbhat Wouldn't we also need to handle the case of a content document that contains its own custom nodes, as might be packaged and shared between studios? To handle that case, we'd want to first check for a matching nodedef in the data libraries, and then fall back to checking for a matching nodedef in the content document.

Following that pattern, perhaps we should take the same approach with the other updated methods in this pull request, including Document::getMatchingImplementation below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jstone-lucasfilm in the code below, we check in the datalibrary if available and then fallback to checking in local.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean, but couldn't there be nodedefs for the given node name in both the data library and the content document? For example, the data library might have a node named multiply, but only the content document would have the specific version of multiply that the caller is looking for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposed workflow, if the caller chooses to Register a datalibrary then the data library gets precedence. The caller can still continue to use the import mechanism.

We can update getMatchingNodeDefs so that it checks both data library and content document. Would that be preferred?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ashwinbhat I'm imagining that we want the behavior to exactly match what a user would see if they called importLibrary instead of registerDataLibrary, and I believe that would require us to check both the data library and content document, merging the matches from both of them.

Let me know your thoughts, though, and that's just one opinion on the matter!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an interesting point to discuss - should registerDataLibrary match the importLibrary behavior?

I can certainly imagine circumstances where I might even want to not fallback to any local node definition in the local document and want to be able to validate that my document only uses nodes from the dataLibrary provided.

Perhaps registerDataLibrary() has some concept of strictness? or some input that could control its "fallback" behavior?

@@ -680,6 +708,8 @@ class MX_CORE_API Document : public GraphElement
private:
class Cache;
std::unique_ptr<Cache> _cache;
// Data library for the document
ConstDocumentPtr _dataLibrary;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think other methods like initialize() and copy() probably also need to be updated to handle this extra member variable.

@@ -564,7 +564,10 @@ bool ValueElement::validate(string* message) const
const string& unittype = getUnitType();
if (!unittype.empty())
{
unitTypeDef = getDocument()->getUnitTypeDef(unittype);

unitTypeDef = getDocument()->hasDataLibrary() ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this logic isn' just in Document::getUnitTypeDef() like the other document query functions?

@@ -202,10 +202,15 @@ void ShaderGraph::addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geom
// input here and ignore the type of the geomprop. They are required to have the same type.
string geomNodeDefName = "ND_" + geomprop.getGeomProp() + "_" + input->getType().getName();
NodeDefPtr geomNodeDef = _document->getNodeDef(geomNodeDefName);
if (!geomNodeDef)
if (!geomNodeDef && _document->hasDataLibrary())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code here looks to me like we're inspecting the local document for a nodeDef first, and then falling back to the dataLibrary.

But then isn't Document::getNodeDef() above already checking the dataLibrary? so perhaps this additional secondary check isn't necessary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants