Skip to content

Commit 8c28c16

Browse files
authored
Reduced dirty notifications for isolate select. (#239)
* Reduced dirty notifications for isolate select. * Fixed 2025 build.
1 parent 1068d23 commit 8c28c16

File tree

4 files changed

+107
-8
lines changed

4 files changed

+107
-8
lines changed

lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::DisableIsolateSel
174174
)
175175
{
176176
_isolateSelection[viewportId] = nullptr;
177+
_isolateSelectSceneIndex->SetViewport(viewportId, nullptr);
177178
}
178179

179180
SelectionPtr

lib/flowViewport/sceneIndex/fvpIsolateSelectSceneIndex.cpp

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ bool isGeomSubset(const HdSceneIndexPrim& prim) {
108108
#endif
109109
}
110110

111+
HdContainerDataSourceHandle setInstancerMaskDataSource(
112+
const HdSceneIndexPrim& inputPrim,
113+
const VtArray<bool>& instanceMask
114+
)
115+
{
116+
auto maskDs = HdRetainedTypedSampledDataSource<VtArray<bool>>::New(instanceMask);
117+
118+
return HdContainerDataSourceEditor(inputPrim.dataSource)
119+
.Set(instancerMaskLocator, maskDs)
120+
.Finish();
121+
}
122+
111123
}
112124

113125
namespace FVP_NS_DEF {
@@ -159,11 +171,8 @@ HdSceneIndexPrim IsolateSelectSceneIndex::GetPrim(const SdfPath& primPath) const
159171

160172
auto instancerMask = _instancerMasks.find(primPath);
161173
if (instancerMask != _instancerMasks.end()) {
162-
auto maskDs = HdRetainedTypedSampledDataSource<VtArray<bool>>::New(instancerMask->second);
163-
164-
inputPrim.dataSource = HdContainerDataSourceEditor(inputPrim.dataSource)
165-
.Set(instancerMaskLocator, maskDs)
166-
.Finish();
174+
inputPrim.dataSource =
175+
setInstancerMaskDataSource(inputPrim, instancerMask->second);
167176

168177
return inputPrim;
169178
}
@@ -179,6 +188,20 @@ HdSceneIndexPrim IsolateSelectSceneIndex::GetPrim(const SdfPath& primPath) const
179188
// HYDRA-1242: setting visibility on GeomSubset prim causes hang in Hydra
180189
// Storm.
181190
if (!included && !isGeomSubset(inputPrim)) {
191+
// If an instancer is not included, none of its instances are, so set
192+
// an instance mask that is entirely false.
193+
if (inputPrim.primType == HdPrimTypeTokens->instancer) {
194+
auto instancerTopologySchema = HdInstancerTopologySchema::GetFromParent(inputPrim.dataSource);
195+
const auto nbInstances = getNbInstances(instancerTopologySchema);
196+
VtArray<bool> instanceMask(nbInstances, false);
197+
198+
inputPrim.dataSource = setInstancerMaskDataSource(inputPrim, instanceMask);
199+
}
200+
201+
// Unclear whether instancers need their visibility off. As of OpenUSD
202+
// 0.24.11, Hydra Storm seems to ignore visibility for instancers, but
203+
// there seems to be no harm in setting it false.
204+
182205
inputPrim.dataSource = HdContainerDataSourceEditor(inputPrim.dataSource)
183206
.Set(HdVisibilitySchema::GetDefaultLocator(), visOff)
184207
.Finish();
@@ -437,21 +460,45 @@ void IsolateSelectSceneIndex::_DirtyVisibilityRecursive(
437460
HdSceneIndexObserver::DirtiedPrimEntries* dirtiedEntries
438461
) const
439462
{
440-
TF_DEBUG(FVP_ISOLATE_SELECT_SCENE_INDEX)
441-
.Msg(" %s: marking %s visibility locator dirty.\n", _viewportId.c_str(), primPath.GetText());
442-
463+
// If the prim is a material, early out: visibility is not
464+
// relevant for materials
443465
auto prim = GetInputSceneIndex()->GetPrim(primPath);
466+
if (prim.primType == HdPrimTypeTokens->material) {
467+
return;
468+
}
444469

445470
// GeomSubset visibility must not be set (see GetPrim()), so no need to
446471
// dirty it.
447472
if (isGeomSubset(prim)) {
448473
return;
449474
}
450475

476+
TF_DEBUG(FVP_ISOLATE_SELECT_SCENE_INDEX)
477+
.Msg(" %s: marking %s visibility locator dirty.\n", _viewportId.c_str(), primPath.GetText());
478+
479+
// Unclear whether instancers need their visibility off. As of OpenUSD
480+
// 0.24.11, Hydra Storm seems to ignore visibility for instancers, but
481+
// there seems to be no harm in setting it false.
482+
451483
dirtiedEntries->emplace_back(
452484
primPath, HdVisibilitySchema::GetDefaultLocator());
453485

486+
// If the prim is an instancer, set its mask dirty, but don't recurse, as
487+
// the hierarchy beneath an instancer is its prototypes, whose visibility
488+
// is managed by the instancer mask data source.
489+
if (prim.primType == HdPrimTypeTokens->instancer) {
490+
_AddDirtyInstancerMaskEntry(primPath, dirtiedEntries);
491+
return;
492+
}
493+
454494
for (const auto& childPath : GetChildPrimPaths(primPath)) {
495+
#if PXR_VERSION >= 2403
496+
// Recursing down to set visibility on a geomSubset child is wasteful.
497+
auto childPrim = GetInputSceneIndex()->GetPrim(childPath);
498+
if (childPrim.primType == HdPrimTypeTokens->geomSubset) {
499+
continue;
500+
}
501+
#endif
455502
_DirtyVisibilityRecursive(childPath, dirtiedEntries);
456503
}
457504
}

lib/mayaHydra/mayaPlugin/renderOverride.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,15 +1831,50 @@ void MtohRenderOverride::_ViewSelectedChangedCb(
18311831
return;
18321832
}
18331833

1834+
auto found = instance->_isolateSelectState.find(viewName.asChar());
1835+
if (found == instance->_isolateSelectState.end()) {
1836+
found = instance->_isolateSelectState.insert(found, VpIsolateSelectStates::value_type(viewName.asChar(), IsolateSelectState::IsolateSelectOff));
1837+
}
1838+
18341839
// The M3dView returns the list of view selected objects as strings.
18351840
// If isolate select is turned off, we want to disable isolate selection.
18361841
// Otherwise, replace with what is in the M3dView.
18371842
auto& vpDataMgr = Fvp::ViewportDataMgr::Get();
18381843
if (!view.viewSelected()) {
18391844
vpDataMgr.DisableIsolateSelection(viewName.asChar());
1845+
found->second = IsolateSelectState::IsolateSelectOff;
18401846
return;
18411847
}
18421848

1849+
// Deal with IsolateSelectState changes. The messages we receive are
1850+
// viewSelectedObjectsChanged true or false.
1851+
//
1852+
// State transitions:
1853+
//
1854+
// off: message false --> go to pendingObjects, do not notify.
1855+
// off: message true --> illegal, warn, do not notify.
1856+
//
1857+
// pendingObjects: message false --> illegal, warn, do not notify.
1858+
// pendingObjects: message true --> notify, go to on.
1859+
//
1860+
// on: message false --> go to off, notify.
1861+
// on: message true --> stay on, notify.
1862+
1863+
if (found->second == IsolateSelectState::IsolateSelectOff) {
1864+
if (TF_VERIFY(!viewSelectedObjectsChanged)) {
1865+
found->second = IsolateSelectState::IsolateSelectPendingObjects;
1866+
}
1867+
return;
1868+
}
1869+
else if (found->second == IsolateSelectState::IsolateSelectPendingObjects) {
1870+
if (!TF_VERIFY(viewSelectedObjectsChanged)) {
1871+
return;
1872+
}
1873+
found->second = IsolateSelectState::IsolateSelectOn;
1874+
}
1875+
1876+
TF_VERIFY(found->second == IsolateSelectState::IsolateSelectOn);
1877+
18431878
// The M3dView returns the list of view selected objects as strings.
18441879
// Loop over the view selected objects and try to create UFE paths from
18451880
// them. If there is more than one element to the MStringArray, this

lib/mayaHydra/mayaPlugin/renderOverride.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include <memory>
7575
#include <mutex>
7676
#include <vector>
77+
#include <map>
7778

7879
#include <ufe/ufe.h>
7980
UFE_NS_DEF {
@@ -338,6 +339,21 @@ class MtohRenderOverride : public MHWRender::MRenderOverride,
338339
#ifdef MAYA_HAS_VIEW_SELECTED_OBJECT_API
339340
long int _nbViewSelectedChangedCalls{0};
340341
#endif
342+
343+
// Maya has an awkward notification mechanism for isolate select,
344+
// with a view selected objects changed boolean that indicates
345+
// whether the state has changed (false), or the isolate selected
346+
// objects have changed (true). When changing a viewport from
347+
// isolate select off to on, two notifications are therefore sent,
348+
// first false (state change), then true (objects set). To avoid
349+
// double dirtying in Hydra, we track the following isolate select
350+
// states per viewport:
351+
//
352+
enum class IsolateSelectState {IsolateSelectOff, IsolateSelectPendingObjects,
353+
IsolateSelectOn};
354+
355+
using VpIsolateSelectStates = std::map<std::string, IsolateSelectState>;
356+
VpIsolateSelectStates _isolateSelectState;
341357
};
342358

343359
PXR_NAMESPACE_CLOSE_SCOPE

0 commit comments

Comments
 (0)