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

Improve material network creation times by caching the nodes returned by Arnold #1813

Merged
merged 4 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [usd#1776](https://github.com/Autodesk/arnold-usd/issues/1776) - Fix incorrect PointInstancer instance orientations in the render delegate.
- [usd#1769](https://github.com/Autodesk/arnold-usd/issues/1769) - Fix curve uvs when they are vertex interpolated.
- [usd#1808](https://github.com/Autodesk/arnold-usd/issues/1808) - Fix the error "Cannot load _htoa_pygeo library required for volume rendering in Solaris" in Houdini 19.5+.
- [usd#1812](https://github.com/Autodesk/arnold-usd/issues/1812) - Improve Material network creation by caching the node entries and the osl code.

## [7.2.5.0] - 2023-12-13

Expand Down
35 changes: 31 additions & 4 deletions libs/render_delegate/node_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,8 @@ HdArnoldNodeGraph::NodeDataPtr HdArnoldNodeGraph::GetNode(
const SdfPath& path, const AtString& nodeType,
const ConnectedInputs &connectedInputs, bool &isMaterialx)
{
static std::unordered_map<std::string, const AtNodeEntry *> _shaderNodeEntryCache;
static std::unordered_map<std::string, AtString> _oslCodeCache;
const auto nodeIt = _nodes.find(path);
// If the node already exists, we are checking if the node type is the same
// as the requested node type. While this is not meaningful for applications
Expand Down Expand Up @@ -823,7 +825,23 @@ HdArnoldNodeGraph::NodeDataPtr HdArnoldNodeGraph::GetNode(
#if ARNOLD_VERSION_NUM >= 70104
const char *nodeTypeChar = nodeType.c_str();
#if ARNOLD_VERSION_NUM > 70203
const AtNodeEntry* shaderNodeEntry = AiMaterialxGetNodeEntryFromDefinition(nodeTypeChar, params);

// Create a key with the params and the nodeType name
std::string nodeEntryKey(nodeType.c_str());
if (pxrMtlxPath.c_str()) nodeEntryKey += pxrMtlxPath.c_str();
const auto shaderNodeEntryIt = _shaderNodeEntryCache.find(nodeEntryKey);
if (shaderNodeEntryIt == _shaderNodeEntryCache.end()) {
// First check if the nodeType is an arnold shader
const AtNodeEntry* nodeEntry = AiNodeEntryLookUp(nodeType);
if (nodeEntry) {
_shaderNodeEntryCache[nodeEntryKey] = nodeEntry;
} else {
_shaderNodeEntryCache[nodeEntryKey] = AiMaterialxGetNodeEntryFromDefinition(nodeTypeChar, params);
}

}

const AtNodeEntry* shaderNodeEntry = _shaderNodeEntryCache[nodeEntryKey];
#else
// arnold backwards compatibility. We used to rely on the nodedef prefix to identify
// the shader type
Expand All @@ -843,25 +861,34 @@ HdArnoldNodeGraph::NodeDataPtr HdArnoldNodeGraph::GetNode(
node = _renderDelegate->CreateArnoldNode(AtString(AiNodeEntryGetName(shaderNodeEntry)), nodeName);
if (AiNodeIs(node, str::osl)) {
isMaterialx = true;
// As we cache the osl code to reduce the number of calls to AiMaterialxGetOslShaderCode, we construct a key
// with the param names
std::string oslShaderKey = nodeEntryKey;

// In order to get the Osl code for this shader, we need to provide the list
// of attribute connections, through the params map.
// We want to add them on top of the eventual PxrMtlPath that was set above
auto inputsIt = connectedInputs.find(path);
if (inputsIt != connectedInputs.end()) {
for(const TfToken &attrName : inputsIt->second) {
AiParamValueMapSetStr(params, AtString(attrName.GetText()), AtString(""));
oslShaderKey += attrName.GetString();
}
}

// Get the OSL description of this mtlx shader. Its attributes will be prefixed with
// "param_shader_"
// The params argument was added in Arnold 7.2.0.0
AtString oslCode;
const auto oslCodeIt = _oslCodeCache.find(oslShaderKey);
if (oslCodeIt == _oslCodeCache.end()) {
#if ARNOLD_VERSION_NUM > 70104
oslCode = AiMaterialxGetOslShaderCode(nodeType.c_str(), "shader", params);
_oslCodeCache[oslShaderKey] = AiMaterialxGetOslShaderCode(nodeType.c_str(), "shader", params);
#elif ARNOLD_VERSION_NUM >= 70104
oslCode = AiMaterialxGetOslShaderCode(nodeType.c_str(), "shader");
_oslCodeCache[oslShaderKey] = AiMaterialxGetOslShaderCode(nodeType.c_str(), "shader");
#endif
}

AtString oslCode = _oslCodeCache[oslShaderKey];
// Set the OSL code. This will create a new AtNodeEntry with parameters
// based on the osl code
if (!oslCode.empty())
Expand Down