Skip to content

Commit

Permalink
Merge pull request #245 from AnimalLogic/AL20-improve_meta_data_perfo…
Browse files Browse the repository at this point in the history
…rmance

[al] Performance improvements when processing prim meta data
  • Loading branch information
Krystian Ligenza authored Feb 28, 2020
2 parents 2c906ef + b3a1059 commit 8b2ebb4
Show file tree
Hide file tree
Showing 22 changed files with 1,734 additions and 693 deletions.
2 changes: 1 addition & 1 deletion plugin/al/lib/AL_USDMaya/AL/usdmaya/Global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ static void postFileRead(void*)
auto stage = proxy->getUsdStage();
proxy->deserialiseTranslatorContext();
proxy->translatorManufacture().preparePythonTranslators(proxy->context());
proxy->findTaggedPrims();
proxy->findPrimsWithMetaData();
proxy->deserialiseTransformRefs();
}
unloadedProxies.clear();
Expand Down
81 changes: 55 additions & 26 deletions plugin/al/lib/AL_USDMaya/AL/usdmaya/SelectabilityDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,70 +21,89 @@ namespace usdmaya {
//----------------------------------------------------------------------------------------------------------------------
bool SelectabilityDB::isPathUnselectable(const SdfPath& path) const
{
for(SdfPath unselectablePath : m_unselectablePaths)
auto begin = m_unselectablePaths.begin();
auto end = m_unselectablePaths.end();
auto foundPathEntry = end;
auto root = SdfPath::AbsoluteRootPath();
auto temp(path);

while(temp != root)
{
if(path.HasPrefix(unselectablePath))
foundPathEntry = std::lower_bound(begin, foundPathEntry, temp);
if(foundPathEntry != end && temp == *foundPathEntry)
{
return true;
}
temp = temp.GetParentPath();
}

return false;
}

//----------------------------------------------------------------------------------------------------------------------
void SelectabilityDB::removePathsAsUnselectable(const SdfPathVector& paths)
{
bool needsSort = false;
for(SdfPath path : paths)
{
needsSort |= removeUnselectablePath(path);
removeUnselectablePath(path);
}

if(needsSort)
auto end = m_unselectablePaths.end();
auto start = m_unselectablePaths.begin();
for(SdfPath path : paths)
{
sort();
auto temp = std::lower_bound(start, end, path);
if(temp != end)
{
if(*temp == path)
{
temp = m_unselectablePaths.erase(temp);
}
start = temp;
}
}
}

//----------------------------------------------------------------------------------------------------------------------
void SelectabilityDB::removePathAsUnselectable(const SdfPath& path)
{
if(removeUnselectablePath(path))
{
sort();
}
removeUnselectablePath(path);
}

//----------------------------------------------------------------------------------------------------------------------
void SelectabilityDB::addPathsAsUnselectable(const SdfPathVector& paths)
{
bool needsSort = false;
for(SdfPath path : paths)
auto end = m_unselectablePaths.end();
auto start = m_unselectablePaths.begin();
for(auto iter = paths.begin(), last = paths.end(); iter != last; ++iter)
{
needsSort |= addUnselectablePath(path);
}
start = std::lower_bound(start, end, *iter);

if(needsSort)
{
sort();
// If we've hit the end, we can simply append the remaining elements in one go.
if(start == end)
{
m_unselectablePaths.insert(end, iter, last);
return;
}

if(*start != *iter)
{
m_unselectablePaths.insert(start, *iter);
}
}
}

//----------------------------------------------------------------------------------------------------------------------
void SelectabilityDB::addPathAsUnselectable(const SdfPath& path)
{
if(addUnselectablePath(path))
{
sort();
}
addUnselectablePath(path);
}

//----------------------------------------------------------------------------------------------------------------------
bool SelectabilityDB::removeUnselectablePath(const SdfPath& path)
{
auto foundPathEntry = std::find(m_unselectablePaths.begin(), m_unselectablePaths.end(), path);
if(foundPathEntry != m_unselectablePaths.end())
auto end = m_unselectablePaths.end();
auto foundPathEntry = std::lower_bound(m_unselectablePaths.begin(), end, path);
if(foundPathEntry != end && *foundPathEntry == path)
{
m_unselectablePaths.erase(foundPathEntry);
return true;
Expand All @@ -95,7 +114,17 @@ bool SelectabilityDB::removeUnselectablePath(const SdfPath& path)
//----------------------------------------------------------------------------------------------------------------------
bool SelectabilityDB::addUnselectablePath(const SdfPath& path)
{
if(!std::binary_search(m_unselectablePaths.begin(), m_unselectablePaths.end(), path))
auto end = m_unselectablePaths.end();
auto iter = std::lower_bound(m_unselectablePaths.begin(), end, path);
if(iter != end)
{
if(*iter != path)
{
m_unselectablePaths.insert(iter, path);
return true;
}
}
else
{
m_unselectablePaths.push_back(path);
return true;
Expand All @@ -106,4 +135,4 @@ bool SelectabilityDB::addUnselectablePath(const SdfPath& path)
//----------------------------------------------------------------------------------------------------------------------
} // usdmaya
} // AL
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
43 changes: 40 additions & 3 deletions plugin/al/lib/AL_USDMaya/AL/usdmaya/SelectabilityDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#pragma once

#include "AL/usdmaya/Api.h"
#include "AL/usdmaya/ForwardDeclares.h"

#include "pxr/pxr.h"
#include "pxr/usd/sdf/path.h"
Expand All @@ -28,23 +29,60 @@ namespace usdmaya {
///---------------------------------------------------------------------------------------------------------------------
/// \brief Logic that stores a sorted list of paths which represent Selectable points in the USD hierarchy
///---------------------------------------------------------------------------------------------------------------------
class SelectabilityDB {
class SelectabilityDB
{
// at little unpleasant design wise, however it means the proxy shape can directly modify the internal
// list of unselectable paths. I have looked at moving some of that logic into this class, however that would
// incur a performance penalty (lock & excluded prim processing can be done at the same time).
friend class nodes::ProxyShape;
public:

SelectabilityDB()
: m_unselectablePaths()
{
m_unselectablePaths.reserve(128);
}

///-------------------------------------------------------------------------------------------------------------------
/// \brief Determines this path is unselectable
/// \param path that you want to determine if it's unselectable
///-------------------------------------------------------------------------------------------------------------------
AL_USDMAYA_PUBLIC
bool isPathUnselectable(const SdfPath& path) const;

///-------------------------------------------------------------------------------------------------------------------
/// \brief Determines whether there is an internal entry for the path specified (and only this path!). If you wish
/// to determine selectability, call isPathUnselectable instead.
/// \param path the path to check to see if exists
/// \return true if the path is contained, false if not.
///-------------------------------------------------------------------------------------------------------------------
bool containsPath(const SdfPath& path) const
{
auto foundPathEntry = std::lower_bound(m_unselectablePaths.begin(), m_unselectablePaths.end(), path);
if(foundPathEntry != m_unselectablePaths.end() && path == *foundPathEntry)
{
return true;
}
return false;
}

///-------------------------------------------------------------------------------------------------------------------
/// \brief Adds a list of paths to the selectable list
/// \param paths which will be added as selectable. All children paths will be also unselectable
///-------------------------------------------------------------------------------------------------------------------
AL_USDMAYA_PUBLIC
void addPathsAsUnselectable(const SdfPathVector& paths);

///-------------------------------------------------------------------------------------------------------------------
/// \brief Sets a list of paths to the selectable list
/// \param paths which will be added as selectable. All children paths will be also unselectable
///-------------------------------------------------------------------------------------------------------------------
void setPathsAsUnselectable(const SdfPathVector& paths)
{
m_unselectablePaths = paths;
std::sort(m_unselectablePaths.begin(), m_unselectablePaths.end());
}

///-------------------------------------------------------------------------------------------------------------------
/// \brief Adds a path to the unselectable list
/// \param path which will be added as unselectable. All children paths will be also unselectable
Expand Down Expand Up @@ -73,7 +111,6 @@ class SelectabilityDB {
void removePathAsUnselectable(const SdfPath& path);

private:
inline void sort(){std::sort(m_unselectablePaths.begin(), m_unselectablePaths.end());}
bool addUnselectablePath(const SdfPath& path);
bool removeUnselectablePath(const SdfPath& path);

Expand All @@ -84,4 +121,4 @@ class SelectabilityDB {
//----------------------------------------------------------------------------------------------------------------------
} // usdmaya
} // AL
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,13 @@ MStatus TranslatePrim::redoIt()

TF_DEBUG(ALUSDMAYA_COMMANDS).Msg("TranslatePrim::redoIt\n");
m_proxy->translatePrimPathsIntoMaya(newImportPaths, m_teardownPaths, tp);


// construct locks and selectability for imported prims
if(m_proxy->isLockPrimFeatureActive())
{
m_proxy->removeMetaData(m_teardownPaths);
m_proxy->processChangedMetaData(SdfPathVector(), newImportPaths);
}

auto stage = m_proxy->usdStage();
auto manufacture = m_proxy->translatorManufacture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ void ProxyShapePostLoadProcess::createTranformChainsForSchemaPrims(
newpath = ptrNode->makeUsdTransformChain(usdPrim.GetParent(), modifier, nodes::ProxyShape::kRequired, &modifier2, 0, pushToPrim, readAnimatedValues);
}
}
objsToCreate.push_back(std::make_pair(newpath, usdPrim));
objsToCreate.emplace_back(newpath, usdPrim);
}
else
{
Expand Down
35 changes: 20 additions & 15 deletions plugin/al/lib/AL_USDMaya/AL/usdmaya/fileio/TransformIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ namespace fileio {


//----------------------------------------------------------------------------------------------------------------------
TransformIterator::TransformIterator(UsdStageRefPtr stage, const MDagPath& parentPath)
TransformIterator::TransformIterator(UsdStageRefPtr stage, const MDagPath& parentPath, bool stopOnInstance)
: m_primStack(),
m_stage(stage)
m_stage(stage),
m_stopOnInstance(stopOnInstance)
{
TF_DEBUG(ALUSDMAYA_TRANSLATORS).Msg("TransformIterator::TransformIterator parent path: %s\n", parentPath.fullPathName().asChar());

Expand All @@ -50,9 +51,10 @@ TransformIterator::TransformIterator(UsdStageRefPtr stage, const MDagPath& paren
}

//----------------------------------------------------------------------------------------------------------------------
TransformIterator::TransformIterator(const UsdPrim& usdStartPrim, const MDagPath& mayaStartPath)
: m_primStack()
, m_stage(usdStartPrim.GetStage())
TransformIterator::TransformIterator(const UsdPrim& usdStartPrim, const MDagPath& mayaStartPath, bool stopOnInstance)
: m_primStack(),
m_stage(usdStartPrim.GetStage()),
m_stopOnInstance(stopOnInstance)
{
m_primStack.reserve(128);
m_primStack.push_back(StackRef(usdStartPrim));
Expand Down Expand Up @@ -94,15 +96,18 @@ bool TransformIterator::next()
do
{
StackRef& r = *(m_primStack.end() - 1);
if(r.m_prim.IsInstance())
if(r.m_prim.IsInstance() && !m_stopOnInstance)
{
UsdPrim master = r.m_prim.GetMaster();
m_primStack.push_back(StackRef(master));
m_visitedMasterPrimPaths.insert(master.GetPath());
StackRef& p = *(m_primStack.end() - 2);
StackRef& c = *(m_primStack.end() - 1);
c.m_object = p.m_object;
next();
if(!m_stopOnInstance)
{
UsdPrim master = r.m_prim.GetMaster();
m_primStack.push_back(StackRef(master));
m_visitedMasterPrimPaths.insert(master.GetPath());
StackRef& p = *(m_primStack.end() - 2);
StackRef& c = *(m_primStack.end() - 1);
c.m_object = p.m_object;
next();
}
return !done();
}
else
Expand All @@ -116,7 +121,7 @@ bool TransformIterator::next()

{
StackRef& b = *(m_primStack.end() - 1);
if(b.m_prim.IsInstance())
if(b.m_prim.IsInstance() && !m_stopOnInstance)
{
m_primStack.pop_back();
}
Expand Down Expand Up @@ -203,4 +208,4 @@ UsdPrim TransformIterator::parentPrim() const
} // fileio
} // usdmaya
} // AL
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ class TransformIterator
/// \param stage the stage to iterate over
/// \param parentPath the DAG path of the proxy shape
AL_USDMAYA_PUBLIC
TransformIterator(UsdStageRefPtr stage, const MDagPath& parentPath = MDagPath());
TransformIterator(UsdStageRefPtr stage, const MDagPath& parentPath = MDagPath(), bool stopOnInstance = false);

/// \brief ctor. Initialises the iterator to the root of the stage
/// \param startPrim a prim in a stage where the iteration should start
/// \param startMayaPath the DAG path of the proxy shape
AL_USDMAYA_PUBLIC
TransformIterator(const UsdPrim& startPrim, const MDagPath& startMayaPath);
TransformIterator(const UsdPrim& startPrim, const MDagPath& startMayaPath, bool stopOnInstance = false);

/// \brief return true if the iteration is complete
/// \return true when the iteration is complete
Expand Down Expand Up @@ -129,13 +129,12 @@ class TransformIterator
std::vector<StackRef> m_primStack;
UsdStageRefPtr m_stage;
MDagPath m_parentPath;

TfHashSet<SdfPath, SdfPath::Hash> m_visitedMasterPrimPaths;
bool m_stopOnInstance;
};

//----------------------------------------------------------------------------------------------------------------------
} // fileio
} // usdmaya
} // AL
//----------------------------------------------------------------------------------------------------------------------

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class Scope;
/// AL_USDMaya transformation matrix implementantations
/// \ingroup nodes
//----------------------------------------------------------------------------------------------------------------------

class BasicTransformationMatrix
: public MPxTransformationMatrix
{
Expand Down Expand Up @@ -71,7 +70,7 @@ class BasicTransformationMatrix
/// \brief return the prim this transform matrix is attached to
/// \return the prim this transform matrix is controlling
inline const UsdPrim& prim() const
{ return m_prim; }
{ return m_prim; }

virtual void initialiseToPrim(bool readFromPrim = true, Scope* node = 0) {}

Expand Down
Loading

0 comments on commit 8b2ebb4

Please sign in to comment.