Skip to content

Commit

Permalink
Merge pull request #2059 from Autodesk/vlasovi/MAYA106075-perf
Browse files Browse the repository at this point in the history
MAYA106075 - Introducing color cache to improve performance
  • Loading branch information
Krystian Ligenza authored Feb 2, 2022
2 parents 68948d6 + e22e7cc commit 124b037
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 35 deletions.
104 changes: 69 additions & 35 deletions lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext)
MProfilingScope profilingScope(
HdVP2RenderDelegate::sProfilerCategory, MProfiler::kColorC_L1, "Execute");

++_frameCounter;
_UpdateRenderTags();

// If update for selection is enabled, the draw data for the "points" repr
Expand Down Expand Up @@ -1475,21 +1476,33 @@ const MColor& ProxyRenderDelegate::GetWireframeColor() const { return _wireframe

GfVec3f ProxyRenderDelegate::GetCurveDefaultColor()
{
MDoubleArray curveColorResult;
{
std::lock_guard<std::mutex> mutexGuard(_mayaCommandEngineMutex);
MGlobal::executeCommand(
"int $index = `displayColor -q -dormant \"curve\"`; colorIndex -q $index;",
curveColorResult);
// Check the cache. It is safe since _dormantCurveColorCache.second is atomic
if (_dormantCurveColorCache.second == _frameCounter) {
return _dormantCurveColorCache.first;
}

// Enter the mutex and check the cache again
std::lock_guard<std::mutex> mutexGuard(_mayaCommandEngineMutex);
if (_dormantCurveColorCache.second == _frameCounter) {
return _dormantCurveColorCache.first;
}

if (curveColorResult.length() == 3) {
return GfVec3f(curveColorResult[0], curveColorResult[1], curveColorResult[2]);
// Execute Maya command engine to fetch the color
MDoubleArray colorResult;
MGlobal::executeCommand(
"int $index = `displayColor -q -dormant \"curve\"`; colorIndex -q $index;", colorResult);

if (colorResult.length() == 3) {
_dormantCurveColorCache.first = GfVec3f(colorResult[0], colorResult[1], colorResult[2]);
} else {
TF_WARN("Failed to obtain curve default color");
// In case of an error, return the default navy-blue color
return GfVec3f(0.000f, 0.016f, 0.376f);
_dormantCurveColorCache.first = GfVec3f(0.000f, 0.016f, 0.376f);
}

// Update the cache and return
_dormantCurveColorCache.second = _frameCounter;
return _dormantCurveColorCache.first;
}

//! \brief
Expand All @@ -1499,16 +1512,36 @@ MColor ProxyRenderDelegate::GetSelectionHighlightColor(const TfToken& className)
static const MColor kDefaultActiveColor(1.0f, 1.0f, 1.0f, 1.0f);

// Prepare to construct the query command.
bool fromPalette = true;
const char* queryName = "unsupported";
bool fromPalette = true;
const char* queryName = "unsupported";
MColorCache* colorCache = nullptr;
if (className.IsEmpty()) {
colorCache = &_leadColorCache;
fromPalette = false;
queryName = "lead";
} else if (className == HdPrimTypeTokens->mesh) {
colorCache = &_activeMeshColorCache;
fromPalette = false;
queryName = "polymeshActive";
} else if (className == HdPrimTypeTokens->basisCurves) {
colorCache = &_activeCurveColorCache;
queryName = "curve";
} else {
TF_WARN(
"ProxyRenderDelegate::GetSelectionHighlightColor - unsupported class: '%s'",
className.GetString().c_str());
return kDefaultActiveColor;
}

// Check the cache. It is safe since colorCache->second is atomic
if (colorCache->second == _frameCounter) {
return colorCache->first;
}

// Enter the mutex and check the cache again
std::lock_guard<std::mutex> mutexGuard(_mayaCommandEngineMutex);
if (colorCache->second == _frameCounter) {
return colorCache->first;
}

// Construct the query command string.
Expand All @@ -1524,37 +1557,38 @@ MColor ProxyRenderDelegate::GetSelectionHighlightColor(const TfToken& className)
}

// Query and return the selection color.
{
MDoubleArray colorResult;
std::lock_guard<std::mutex> mutexGuard(_mayaCommandEngineMutex);
MGlobal::executeCommand(queryCommand, colorResult);

if (colorResult.length() == 3) {
MColor color(colorResult[0], colorResult[1], colorResult[2]);

if (className.IsEmpty()) {
// The 'lead' color is returned in display space, so we need to convert it to
// rendering space. However, function MColorPickerUtilities::applyViewTransform
// is supported only starting from Maya 2023, so in opposite case we just return
// the default lead color.
MDoubleArray colorResult;
MGlobal::executeCommand(queryCommand, colorResult);

if (colorResult.length() == 3) {
MColor color(colorResult[0], colorResult[1], colorResult[2]);

if (className.IsEmpty()) {
// The 'lead' color is returned in display space, so we need to convert it to
// rendering space. However, function MColorPickerUtilities::applyViewTransform
// is supported only starting from Maya 2023, so in opposite case we just return
// the default lead color.
#if MAYA_API_VERSION >= 20230000
return MColorPickerUtilities::applyViewTransform(
color, MColorPickerUtilities::kInverse);
colorCache->first
= MColorPickerUtilities::applyViewTransform(color, MColorPickerUtilities::kInverse);
#else
return kDefaultLeadColor;
colorCache->first = kDefaultLeadColor;
#endif
} else {
return color;
}
} else {
TF_WARN(
"Failed to obtain selection highlight color for '%s' objects",
className.IsEmpty() ? "lead" : className.GetString().c_str());
colorCache->first = color;
}
} else {
TF_WARN(
"Failed to obtain selection highlight color for '%s' objects",
className.IsEmpty() ? "lead" : className.GetString().c_str());

// In case of any failure, return the default color
colorCache->first = className.IsEmpty() ? kDefaultLeadColor : kDefaultActiveColor;
}

// In case of any failure, return the default color
return className.IsEmpty() ? kDefaultLeadColor : kDefaultActiveColor;
// Update the cache and return
colorCache->second = _frameCounter;
return colorCache->first;
}

bool ProxyRenderDelegate::DrawRenderTag(const TfToken& renderTag) const
Expand Down
9 changes: 9 additions & 0 deletions lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,15 @@ class ProxyRenderDelegate : public MHWRender::MPxSubSceneOverride
MColor _wireframeColor; //!< Wireframe color assigned to the proxy shape

std::mutex _mayaCommandEngineMutex;
uint64_t _frameCounter { 0 };

typedef std::pair<MColor, std::atomic<uint64_t>> MColorCache;
typedef std::pair<GfVec3f, std::atomic<uint64_t>> GfVec3fCache;

MColorCache _activeMeshColorCache { MColor(), 0 };
MColorCache _activeCurveColorCache { MColor(), 0 };
MColorCache _leadColorCache { MColor(), 0 };
GfVec3fCache _dormantCurveColorCache { GfVec3f(), 0 };

//! A collection of Rprims to prepare render data for specified reprs
std::unique_ptr<HdRprimCollection> _defaultCollection;
Expand Down

0 comments on commit 124b037

Please sign in to comment.