From 4346939c44242dda82b9d475471e5fb5b2b507ce Mon Sep 17 00:00:00 2001 From: krickw Date: Wed, 3 Jun 2020 09:06:37 -0400 Subject: [PATCH 1/4] Handle rprim purpose changing to a hidden purpose correctly. --- .../vp2RenderDelegate/proxyRenderDelegate.cpp | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp index 8897c96bc0..d931b3f368 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp @@ -390,6 +390,17 @@ void ProxyRenderDelegate::_InitRenderDelegate(MSubSceneContainer& container) { break; } } + + // Set the render tags to be all the tags. Vp2RenderDelegate implements + // render tags as a per-render item setting, so we always need to visit + // all the rprims to handle cases when an rprim changes from a displayed + // tag to a hidden tag. + TfTokenVector renderTags + = { HdRenderTagTokens->geometry, + HdRenderTagTokens->render, + HdRenderTagTokens->proxy, + HdRenderTagTokens->guide }; + _taskController->SetRenderTags(renderTags); } } @@ -776,20 +787,21 @@ void ProxyRenderDelegate::_UpdateRenderTags() // are being hidden, because the render pass level filtering will prevent // them from drawing. // The Vp2RenderDelegate implements render tags using MRenderItem::Enable(), - // which means we do need to update individual MRenderItems when the render - // tags change. + // which means we do need to update individual MRenderItems when the displayed + // render tags change, or when the render tag on an rprim changes. + // + // To handle an rprim's render tag value changing we need to be sure that + // the dummy render task we use to draw includes all render tags. If we + // leave any tags out then when an rprim changes from a visible tag to + // a hidden one that rprim will get marked dirty, but Sync will not be + // called because the rprim doesn't match the current render tags. + // // When we change the desired render tags on the proxyShape we'll be adding // and/or removing some tags, so we can have existing MRenderItems that need - // to be hidden, or hidden items that need to be shown. - // This function needs to do three things: - // 1: Make sure every rprim with a render tag whose visibility changed gets - // marked dirty. This will ensure the upcoming execute call will update - // the visibility of the MRenderItems in MPxSubSceneOverride. - // 2: Make a special call to Execute() with only the render tags which have - // been removed. We need this extra call to hide the previously shown - // items. - // 3: Update the render tags with the new final render tags so that the next - // real call to execute will update all the now visible items. + // to be hidden, or hidden items that need to be shown. To do that we need + // to make sure every rprim with a render tag whose visibility changed gets + // marked dirty. This will ensure the upcoming execute call will update + // the visibility of the MRenderItems in MPxSubSceneOverride. bool renderPurposeChanged = false; bool proxyPurposeChanged = false; bool guidePurposeChanged = false; @@ -826,26 +838,6 @@ void ProxyRenderDelegate::_UpdateRenderTags() for (auto& id : rprimsToDirty) { changeTracker.MarkRprimDirty(id, HdChangeTracker::DirtyRenderTag); } - - // Make a special pass over the removed render tags so that the objects - // can hide themselves. - _taskController->SetRenderTags(removedRenderTags); - _engine.Execute(_renderIndex.get(), &_dummyTasks); - - // Set the new render tags correctly.The regular execute will cause - // any newly visible rprims will update and mark themselves visible. - TfTokenVector renderTags - = { HdRenderTagTokens->geometry }; // always draw geometry render tag purpose. - if (_proxyShapeData->DrawRenderPurpose()) { - renderTags.push_back(HdRenderTagTokens->render); - } - if (_proxyShapeData->DrawProxyPurpose()) { - renderTags.push_back(HdRenderTagTokens->proxy); - } - if (_proxyShapeData->DrawGuidePurpose()) { - renderTags.push_back(HdRenderTagTokens->guide); - } - _taskController->SetRenderTags(renderTags); } } From 0a07070955255b5811c42a0191dd3e67f770866b Mon Sep 17 00:00:00 2001 From: krickw Date: Wed, 3 Jun 2020 11:09:09 -0400 Subject: [PATCH 2/4] Selection hi-lite items respect purpose. --- lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index 7a31751364..6d8f67ae69 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -1332,16 +1332,19 @@ void HdVP2Mesh::_UpdateDrawItem( } } + auto drawItemVisible = [&]() { + return drawItem->GetVisible() && drawScene.DrawRenderTag(renderIndex.GetRenderTag(GetId())); + }; + if (itemDirtyBits & (HdChangeTracker::DirtyVisibility | HdChangeTracker::DirtyRenderTag)) { - drawItemData._enabled - = drawItem->GetVisible() && drawScene.DrawRenderTag(renderIndex.GetRenderTag(GetId())); + drawItemData._enabled = drawItemVisible(); stateToCommit._enabled = &drawItemData._enabled; } if (isDedicatedSelectionHighlightItem) { if (itemDirtyBits & DirtySelectionHighlight) { const bool enable = - (_selectionState != kUnselected) && drawItem->GetVisible(); + (_selectionState != kUnselected) && drawItemVisible(); if (drawItemData._enabled != enable) { drawItemData._enabled = enable; stateToCommit._enabled = &drawItemData._enabled; @@ -1350,7 +1353,7 @@ void HdVP2Mesh::_UpdateDrawItem( } else if (isBBoxItem) { if (itemDirtyBits & HdChangeTracker::DirtyExtent) { - const bool enable = !range.IsEmpty() && drawItem->GetVisible(); + const bool enable = !range.IsEmpty() && drawItemVisible(); if (drawItemData._enabled != enable) { drawItemData._enabled = enable; stateToCommit._enabled = &drawItemData._enabled; From 51e6b1bc154be27abaf5fdaf27c9377e5466b4bb Mon Sep 17 00:00:00 2001 From: krickw Date: Wed, 3 Jun 2020 13:20:53 -0400 Subject: [PATCH 3/4] Revert "Selection hi-lite items respect purpose." This reverts commit 0a07070955255b5811c42a0191dd3e67f770866b. --- lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index 6d8f67ae69..7a31751364 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -1332,19 +1332,16 @@ void HdVP2Mesh::_UpdateDrawItem( } } - auto drawItemVisible = [&]() { - return drawItem->GetVisible() && drawScene.DrawRenderTag(renderIndex.GetRenderTag(GetId())); - }; - if (itemDirtyBits & (HdChangeTracker::DirtyVisibility | HdChangeTracker::DirtyRenderTag)) { - drawItemData._enabled = drawItemVisible(); + drawItemData._enabled + = drawItem->GetVisible() && drawScene.DrawRenderTag(renderIndex.GetRenderTag(GetId())); stateToCommit._enabled = &drawItemData._enabled; } if (isDedicatedSelectionHighlightItem) { if (itemDirtyBits & DirtySelectionHighlight) { const bool enable = - (_selectionState != kUnselected) && drawItemVisible(); + (_selectionState != kUnselected) && drawItem->GetVisible(); if (drawItemData._enabled != enable) { drawItemData._enabled = enable; stateToCommit._enabled = &drawItemData._enabled; @@ -1353,7 +1350,7 @@ void HdVP2Mesh::_UpdateDrawItem( } else if (isBBoxItem) { if (itemDirtyBits & HdChangeTracker::DirtyExtent) { - const bool enable = !range.IsEmpty() && drawItemVisible(); + const bool enable = !range.IsEmpty() && drawItem->GetVisible(); if (drawItemData._enabled != enable) { drawItemData._enabled = enable; stateToCommit._enabled = &drawItemData._enabled; From 7665260456571a1a057c719686a734ba25db9295 Mon Sep 17 00:00:00 2001 From: krickw Date: Thu, 4 Jun 2020 15:48:06 -0400 Subject: [PATCH 4/4] Don't update mesh rprims that are hidden by render tags (purpose). Keep the set of render tags on our dummy render task small. --- lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp | 43 ++++++++++++++ lib/mayaUsd/render/vp2RenderDelegate/mesh.h | 2 + .../vp2RenderDelegate/proxyRenderDelegate.cpp | 58 +++++++++++++------ .../vp2RenderDelegate/proxyRenderDelegate.h | 5 ++ 4 files changed, 89 insertions(+), 19 deletions(-) diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index 7a31751364..623415fad5 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -365,6 +365,20 @@ void HdVP2Mesh::Sync( return; } + // We don't update the repr if it is hidden by the render tags (purpose) + // of the ProxyRenderDelegate. In additional, we need to hide any already + // existing render items because they should not be drawn. + auto* const param = static_cast(_delegate->GetRenderParam()); + ProxyRenderDelegate& drawScene = param->GetDrawScene(); + if (!drawScene.DrawRenderTag(delegate->GetRenderIndex().GetRenderTag(GetId()))) { + _HideAllDrawItems(reprToken); + // clearing visibility here is wrong. It is a work around to handle purpose changing + // marking visibility dirty instead of render tag. See UsdImagingGprimAdapter::ProcessPropertyChange + // for where this happens. + *dirtyBits &= ~( HdChangeTracker::DirtyRenderTag | HdChangeTracker::DirtyVisibility ); + return; + } + MProfilingScope profilingScope(HdVP2RenderDelegate::sProfilerCategory, MProfiler::kColorC_L2, _rprimId.asChar(), "HdVP2Mesh::Sync"); @@ -1520,6 +1534,35 @@ void HdVP2Mesh::_UpdateDrawItem( }); } +void HdVP2Mesh::_HideAllDrawItems(const TfToken& reprToken) { + HdReprSharedPtr const& curRepr = _GetRepr(reprToken); + if (!curRepr) { + return; + } + + _MeshReprConfig::DescArray reprDescs = _GetReprDesc(reprToken); + + // For each relevant draw item, update dirty buffer sources. + int drawItemIndex = 0; + for (size_t descIdx = 0; descIdx < reprDescs.size(); ++descIdx) { + const HdMeshReprDesc& desc = reprDescs[descIdx]; + if (desc.geomStyle == HdMeshGeomStyleInvalid) { + continue; + } + + auto* drawItem = static_cast(curRepr->GetDrawItem(drawItemIndex++)); + if (!drawItem) + continue; + MHWRender::MRenderItem* renderItem = drawItem->GetRenderItem(); + if (!renderItem) + continue; + + _delegate->GetVP2ResourceRegistry().EnqueueCommit([renderItem]() { + renderItem->enable(false); + }); + } +} + /*! \brief Update _primvarSourceMap, our local cache of raw primvar data. This function pulls data from the scene delegate, but defers processing. diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.h b/lib/mayaUsd/render/vp2RenderDelegate/mesh.h index 697234f3c7..c08d7d8ba6 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.h @@ -102,6 +102,8 @@ class HdVP2Mesh final : public HdMesh { const HdMeshReprDesc& desc, bool requireSmoothNormals, bool requireFlatNormals); + void _HideAllDrawItems(const TfToken& reprToken); + void _UpdatePrimvarSources( HdSceneDelegate* sceneDelegate, HdDirtyBits dirtyBits, diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp index d931b3f368..e4e914de02 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp @@ -390,17 +390,6 @@ void ProxyRenderDelegate::_InitRenderDelegate(MSubSceneContainer& container) { break; } } - - // Set the render tags to be all the tags. Vp2RenderDelegate implements - // render tags as a per-render item setting, so we always need to visit - // all the rprims to handle cases when an rprim changes from a displayed - // tag to a hidden tag. - TfTokenVector renderTags - = { HdRenderTagTokens->geometry, - HdRenderTagTokens->render, - HdRenderTagTokens->proxy, - HdRenderTagTokens->guide }; - _taskController->SetRenderTags(renderTags); } } @@ -802,6 +791,7 @@ void ProxyRenderDelegate::_UpdateRenderTags() // to make sure every rprim with a render tag whose visibility changed gets // marked dirty. This will ensure the upcoming execute call will update // the visibility of the MRenderItems in MPxSubSceneOverride. + HdChangeTracker& changeTracker = _renderIndex->GetChangeTracker(); bool renderPurposeChanged = false; bool proxyPurposeChanged = false; bool guidePurposeChanged = false; @@ -815,30 +805,60 @@ void ProxyRenderDelegate::_UpdateRenderTags() // Build the list of render tags which were added or removed (changed) // and the list of render tags which were removed. TfTokenVector changedRenderTags; - TfTokenVector removedRenderTags; if (renderPurposeChanged) { changedRenderTags.push_back(HdRenderTagTokens->render); - if (!_proxyShapeData->DrawRenderPurpose()) - removedRenderTags.push_back(HdRenderTagTokens->render); } if (proxyPurposeChanged) { changedRenderTags.push_back(HdRenderTagTokens->proxy); - if (!_proxyShapeData->DrawProxyPurpose()) - removedRenderTags.push_back(HdRenderTagTokens->proxy); } if (guidePurposeChanged) { changedRenderTags.push_back(HdRenderTagTokens->guide); - if (!_proxyShapeData->DrawGuidePurpose()) - removedRenderTags.push_back(HdRenderTagTokens->guide); } // Mark all the rprims which have a render tag which changed dirty SdfPathVector rprimsToDirty = _GetFilteredRprims(*_defaultCollection, changedRenderTags); - HdChangeTracker& changeTracker = _renderIndex->GetChangeTracker(); + for (auto& id : rprimsToDirty) { changeTracker.MarkRprimDirty(id, HdChangeTracker::DirtyRenderTag); } } + + // When the render tag on an rprim changes we do a pass over all rprims to update + // their visibility. The frame after we do the pass over all the tags, set the tags back to + // the minimum set of tags. + if (!_taskRenderTagsValid) { + TfTokenVector renderTags + = { HdRenderTagTokens->geometry }; // always draw geometry render tag purpose. + if (_proxyShapeData->DrawRenderPurpose()) { + renderTags.push_back(HdRenderTagTokens->render); + } + if (_proxyShapeData->DrawProxyPurpose()) { + renderTags.push_back(HdRenderTagTokens->proxy); + } + if (_proxyShapeData->DrawGuidePurpose()) { + renderTags.push_back(HdRenderTagTokens->guide); + } + _taskController->SetRenderTags(renderTags); + _taskRenderTagsValid = true; + } + + // Vp2RenderDelegate implements render tags as a per-render item setting. + // To handle cases when an rprim changes from a displayed tag to a hidden tag + // we need to visit all the rprims and set the enable flag correctly on + // all their render items. Do visit all the rprims we need to set the + // render tags to be all the tags. + // When an rprim has it's renderTag changed the global render tag version + // id will change. + const int renderTagVersion = changeTracker.GetRenderTagVersion(); + if (renderTagVersion != _renderTagVersion) { + TfTokenVector renderTags = { HdRenderTagTokens->geometry, + HdRenderTagTokens->render, + HdRenderTagTokens->proxy, + HdRenderTagTokens->guide }; + _taskController->SetRenderTags(renderTags); + _taskRenderTagsValid = false; + _renderTagVersion = renderTagVersion; + } } //! \brief List the rprims in collection that match renderTags diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h index 561a617282..b6018375cb 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h @@ -193,6 +193,11 @@ class ProxyRenderDelegate : public MHWRender::MPxSubSceneOverride //! A collection of Rprims to prepare render data for specified reprs std::unique_ptr _defaultCollection; + //! The render tag version used the last time render tags were updated + int _renderTagVersion { 0 }; // initialized to 1 in HdChangeTracker, so we'll always have an + // invalid version the first update. + bool _taskRenderTagsValid { false }; //!< If false the render tags on the dummy render task are not the minimum set of tags. + //! A collection of Rprims being selected HdSelectionSharedPtr _selection;