@@ -85,10 +85,14 @@ class LobePrunerImpl
85
85
LobePrunerImpl (LobePrunerImpl&&) = delete ;
86
86
LobePrunerImpl& operator =(LobePrunerImpl&&) = delete ;
87
87
88
- bool getOptimizedNodeCategory (const mx::Node& node, std::string& nodeCategory);
88
+ bool getOptimizedNodeDef (const mx::Node& node, mx::NodeDefPtr& nodeDef);
89
+
89
90
mx::StringVec getOptimizedAttributeNames (const mx::NodeDefPtr& nodeDef) const ;
90
91
91
92
PXR_NS::TfToken getOptimizedNodeId (const PXR_NS::HdMaterialNode2& node);
93
+ bool isOptimizedNodeId (const PXR_NS::TfToken& nodeId);
94
+
95
+ void optimizeLibrary (const MaterialX::DocumentPtr& library);
92
96
93
97
static const std::string ND_PREFIX;
94
98
static const std::string DARK_BASE;
@@ -105,7 +109,7 @@ class LobePrunerImpl
105
109
const mx::InputPtr& input,
106
110
const mx::NodeGraphPtr& ng,
107
111
const mx::NodeDefPtr& nd);
108
- void
112
+ mx::NodeDefPtr
109
113
ensureLibraryHasOptimizedShader (const PXR_NS::TfToken& nodeDefName, const std::string& flags);
110
114
void optimizeZeroValue (
111
115
mx::NodeGraphPtr& optimizedNodeGraph,
@@ -132,6 +136,7 @@ class LobePrunerImpl
132
136
133
137
std::unordered_map<PXR_NS::TfToken, NodeDefData, PXR_NS::TfToken::HashFunctor> _prunerData;
134
138
mx::DocumentPtr _library;
139
+ PXR_NS::TfToken::HashSet _optimizedNodeIds;
135
140
};
136
141
137
142
const std::string LobePrunerImpl::ND_PREFIX = " LPOPTIND_" ;
@@ -216,6 +221,90 @@ bool LobePrunerImpl::isLobeInput(const mx::InputPtr& input, const mx::NodeDefPtr
216
221
return true ;
217
222
}
218
223
224
+ void LobePrunerImpl::optimizeLibrary (const MaterialX::DocumentPtr& library)
225
+ {
226
+ if (!_library || _prunerData.empty ()) {
227
+ return ;
228
+ }
229
+
230
+ std::set<std::string> allDefinedNodeGraphs;
231
+ // Go thru all NodeGraphs found in the library that have an associated NodeDef:
232
+ for (const auto & ng : library->getNodeGraphs ()) {
233
+ if (ng->hasNodeDefString ()) {
234
+ allDefinedNodeGraphs.insert (ng->getName ());
235
+ }
236
+ }
237
+ for (const auto & impl : library->getImplementations ()) {
238
+ if (impl->hasNodeGraph ()) {
239
+ allDefinedNodeGraphs.insert (impl->getNodeGraph ());
240
+ }
241
+ }
242
+
243
+ for (const auto & ngName : allDefinedNodeGraphs) {
244
+ const auto ng = library->getNodeGraph (ngName);
245
+ // Go thru all the nodes of that NodeGraph
246
+ for (const auto & node : ng->getNodes ()) {
247
+ // Can this node be optimized?
248
+ const auto & nd = node->getNodeDef ();
249
+ if (!nd) {
250
+ continue ;
251
+ }
252
+
253
+ const auto ndName = PXR_NS::TfToken (nd->getName ());
254
+ const auto ndIt = _prunerData.find (ndName);
255
+ if (ndIt == _prunerData.end ()) {
256
+ continue ;
257
+ }
258
+
259
+ // This NodeGraph contains an optimizable embedded surface shader node.
260
+ std::string flags (ndIt->second ._attributeData .size (), ' x' );
261
+
262
+ bool canOptimize = false ;
263
+
264
+ auto attrIt = ndIt->second ._attributeData .cbegin ();
265
+ for (size_t i = 0 ; attrIt != ndIt->second ._attributeData .cend (); ++attrIt, ++i) {
266
+ const auto nodeinput = node->getActiveInput (attrIt->first );
267
+ float inputValue = 0 .5F ;
268
+ if (nodeinput) {
269
+ // Can not optimize if connected in any way.
270
+ if (nodeinput->hasNodeName () || nodeinput->hasOutputString ()
271
+ || nodeinput->hasInterfaceName ()) {
272
+ continue ;
273
+ }
274
+ inputValue = nodeinput->getValue ()->asA <float >();
275
+ } else {
276
+ const auto defInput = nd->getActiveInput (attrIt->first );
277
+ inputValue = defInput->getValue ()->asA <float >();
278
+ }
279
+
280
+ for (const auto & optimizableValue : attrIt->second ) {
281
+ if (optimizableValue.first == inputValue) {
282
+ if (inputValue == 0 .0F ) {
283
+ flags[i] = ' 0' ;
284
+ } else {
285
+ flags[i] = ' 1' ;
286
+ }
287
+ canOptimize = true ;
288
+ }
289
+ }
290
+ }
291
+
292
+ if (canOptimize) {
293
+ const auto optimizedNodeDef = ensureLibraryHasOptimizedShader (ndName, flags);
294
+ // Replace the node with an optimized one:
295
+ const auto nsPrefix = optimizedNodeDef->hasNamespace ()
296
+ ? optimizedNodeDef->getNamespace () + " :"
297
+ : std::string {};
298
+
299
+ node->setCategory (nsPrefix + optimizedNodeDef->getNodeString ());
300
+ if (node->hasNodeDefString ()) {
301
+ node->setNodeDefString (optimizedNodeDef->getName ());
302
+ }
303
+ }
304
+ }
305
+ }
306
+ }
307
+
219
308
void LobePrunerImpl::addOptimizableValue (
220
309
float value,
221
310
const mx::InputPtr& input,
@@ -242,7 +331,7 @@ void LobePrunerImpl::addOptimizableValue(
242
331
valueMap.find (value)->second .push_back (PXR_NS::TfToken (input->getParent ()->getName ()));
243
332
}
244
333
245
- bool LobePrunerImpl::getOptimizedNodeCategory (const mx::Node& node, std::string& nodeCategory )
334
+ bool LobePrunerImpl::getOptimizedNodeDef (const mx::Node& node, mx::NodeDefPtr& nodeDef )
246
335
{
247
336
const auto & nd = node.getNodeDef ();
248
337
if (!nd) {
@@ -288,8 +377,7 @@ bool LobePrunerImpl::getOptimizedNodeCategory(const mx::Node& node, std::string&
288
377
}
289
378
290
379
if (canOptimize) {
291
- ensureLibraryHasOptimizedShader (ndName, flags);
292
- nodeCategory = node.getCategory () + " _" + flags;
380
+ nodeDef = ensureLibraryHasOptimizedShader (ndName, flags);
293
381
return true ;
294
382
}
295
383
@@ -356,39 +444,53 @@ PXR_NS::TfToken LobePrunerImpl::getOptimizedNodeId(const PXR_NS::HdMaterialNode2
356
444
}
357
445
358
446
if (canOptimize) {
359
- ensureLibraryHasOptimizedShader (node.nodeTypeId , flags);
360
- return PXR_NS::TfToken (
361
- ND_PREFIX + nodeDef->GetFamily ().GetString () + " _" + flags + " _surfaceshader" );
447
+ return PXR_NS::TfToken (ensureLibraryHasOptimizedShader (node.nodeTypeId , flags)->getName ());
362
448
}
363
449
364
450
return retVal;
365
451
}
366
452
367
- void LobePrunerImpl::ensureLibraryHasOptimizedShader (
453
+ bool LobePrunerImpl::isOptimizedNodeId (const PXR_NS::TfToken& nodeId)
454
+ {
455
+ return _optimizedNodeIds.count (nodeId) != 0 ;
456
+ }
457
+
458
+ mx::NodeDefPtr LobePrunerImpl::ensureLibraryHasOptimizedShader (
368
459
const PXR_NS::TfToken& nodeDefName,
369
460
const std::string& flags)
370
461
{
371
462
const auto ndIt = _prunerData.find (nodeDefName);
372
463
if (ndIt == _prunerData.end ()) {
373
- return ;
464
+ return {} ;
374
465
}
375
466
376
- const auto originalNodeDef = _library->getNodeDef (nodeDefName.GetString ());
377
- const auto originalNodeGraph = _library->getNodeGraph (ndIt->second ._nodeGraphName );
378
- const std::string optimizedNodeName = originalNodeDef->getNodeString () + " _" + flags;
379
- const std::string optimizedNodeDefName = ND_PREFIX + optimizedNodeName + " _surfaceshader" ;
380
- if (_library->getNodeDef (optimizedNodeDefName)) {
467
+ const auto originalNodeDef = _library->getNodeDef (nodeDefName.GetString ());
468
+ const auto originalNodeGraph = _library->getNodeGraph (ndIt->second ._nodeGraphName );
469
+ const auto nsPrefix = originalNodeDef->hasNamespace ()
470
+ ? originalNodeDef->getNamespace () + mx::NAME_PREFIX_SEPARATOR
471
+ : std::string {};
472
+ auto optimizedNodeName = originalNodeDef->getNodeString () + " _" + flags;
473
+ if (!nsPrefix.empty () && optimizedNodeName.rfind (nsPrefix, 0 ) == 0 ) {
474
+ optimizedNodeName = optimizedNodeName.substr (nsPrefix.size ());
475
+ }
476
+ const auto optimizedNodeNameWithNS = nsPrefix + optimizedNodeName;
477
+ const std::string optimizedNodeDefName
478
+ = nsPrefix + ND_PREFIX + optimizedNodeName + " _surfaceshader" ;
479
+ if (const auto existingNd = _library->getNodeDef (optimizedNodeDefName)) {
381
480
// Already there
382
- return ;
481
+ return existingNd ;
383
482
}
384
483
484
+ _optimizedNodeIds.insert (PXR_NS::TfToken (optimizedNodeDefName));
485
+
385
486
auto optimizedNodeDef
386
487
= _library->addNodeDef (optimizedNodeDefName, " surfaceshader" , optimizedNodeName);
387
488
optimizedNodeDef->copyContentFrom (originalNodeDef);
388
489
optimizedNodeDef->setSourceUri (" " );
389
490
optimizedNodeDef->setNodeString (optimizedNodeName);
390
491
391
- auto optimizedNodeGraph = _library->addNodeGraph (" NG_" + optimizedNodeName + " _surfaceshader" );
492
+ auto optimizedNodeGraph
493
+ = _library->addNodeGraph (nsPrefix + " LPOPTING_" + optimizedNodeName + " _surfaceshader" );
392
494
optimizedNodeGraph->copyContentFrom (originalNodeGraph);
393
495
optimizedNodeGraph->setSourceUri (" " );
394
496
optimizedNodeGraph->setNodeDefString (optimizedNodeDefName);
@@ -414,6 +516,8 @@ void LobePrunerImpl::ensureLibraryHasOptimizedShader(
414
516
default : continue ;
415
517
}
416
518
}
519
+
520
+ return optimizedNodeDef;
417
521
}
418
522
419
523
void LobePrunerImpl::optimizeZeroValue (
@@ -560,9 +664,16 @@ LobePruner::Ptr LobePruner::create() { return std::make_shared<LobePruner>(); }
560
664
LobePruner::~LobePruner () = default ;
561
665
LobePruner::LobePruner () = default ;
562
666
563
- bool LobePruner::getOptimizedNodeCategory (const mx::Node& node, std::string& nodeCategory)
667
+ void LobePruner::optimizeLibrary (const MaterialX::DocumentPtr& library)
668
+ {
669
+ if (_impl) {
670
+ _impl->optimizeLibrary (library);
671
+ }
672
+ }
673
+
674
+ bool LobePruner::getOptimizedNodeDef (const mx::Node& node, mx::NodeDefPtr& nodeDef)
564
675
{
565
- return _impl ? _impl->getOptimizedNodeCategory (node, nodeCategory ) : false ;
676
+ return _impl ? _impl->getOptimizedNodeDef (node, nodeDef ) : false ;
566
677
}
567
678
568
679
mx::StringVec LobePruner::getOptimizedAttributeNames (const mx::NodeDefPtr& nodeDef) const
@@ -582,7 +693,7 @@ void LobePruner::setLibrary(const mx::DocumentPtr& library)
582
693
583
694
bool LobePruner::isOptimizedNodeId (const PXR_NS::TfToken& nodeId)
584
695
{
585
- return nodeId. GetString (). rfind (LobePrunerImpl::ND_PREFIX, 0 ) == 0 ;
696
+ return _impl ? _impl-> isOptimizedNodeId (nodeId) : false ;
586
697
}
587
698
588
699
const std::string& LobePruner::getOptimizedNodeDefPrefix () { return LobePrunerImpl::ND_PREFIX; }
0 commit comments