From: age Date: Tue, 8 Sep 2020 11:44:21 +0000 (+0300) Subject: 0031757: Visualization - Prebuild BVH for Select3D_SensitiveEntity in separate threads X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=ffdf673ef3b55afc9432a061a50c95787aa110ac;p=occt-copy.git 0031757: Visualization - Prebuild BVH for Select3D_SensitiveEntity in separate threads (cherry picked from commit bb598fe0216163889af6aa054ec8081eb1cfd384) --- diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES index 3c05be68b8..85b038af82 100755 --- a/src/SelectMgr/FILES +++ b/src/SelectMgr/FILES @@ -2,6 +2,8 @@ SelectMgr_AndFilter.cxx SelectMgr_AndFilter.hxx SelectMgr_BaseFrustum.cxx SelectMgr_BaseFrustum.hxx +SelectMgr_BVHThreadPool.cxx +SelectMgr_BVHThreadPool.hxx SelectMgr_CompositionFilter.cxx SelectMgr_CompositionFilter.hxx SelectMgr_CompositionFilter.lxx diff --git a/src/SelectMgr/SelectMgr_BVHThreadPool.cxx b/src/SelectMgr/SelectMgr_BVHThreadPool.cxx new file mode 100644 index 0000000000..9f4da57fd9 --- /dev/null +++ b/src/SelectMgr/SelectMgr_BVHThreadPool.cxx @@ -0,0 +1,157 @@ +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BVHThreadPool, Standard_Transient) + +//================================================== +// Function: SelectMgr_BVHThreadPool +// Purpose : +//================================================== +SelectMgr_BVHThreadPool::SelectMgr_BVHThreadPool (Standard_Integer theNbThreads) +: myToStopBVHThread(Standard_False), + myWakeEvent(Standard_False), + myIdleEvent(Standard_True), + myIsStarted(Standard_False) +{ + Standard_Integer aBVHThreadsNum = theNbThreads > 0 ? theNbThreads : OSD_Parallel::NbLogicalProcessors() > 1 ? OSD_Parallel::NbLogicalProcessors() - 1 : 1; + myBVHThreads = NCollection_Array1(1, aBVHThreadsNum); + myBVHBuildData = NCollection_Array1(1, aBVHThreadsNum); + + for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i) + { + myBVHThreads.ChangeValue(i).SetFunction (buildBVHThreadFunc); + myBVHThreads.ChangeValue(i).SetPriority (THREAD_PRIORITY_BELOW_NORMAL); + myBVHBuildData.ChangeValue(i).Pool = this; + } +} + +//================================================== +// Function: ~SelectMgr_BVHThreadPool +// Purpose : +//================================================== +SelectMgr_BVHThreadPool::~SelectMgr_BVHThreadPool() +{ + StopThreads(); +} + +//================================================== +// Function: StopThreads +// Purpose : +//================================================== +void SelectMgr_BVHThreadPool::StopThreads() +{ + if (!myIsStarted) + { + return; + } + myToStopBVHThread = Standard_True; + myWakeEvent.Set(); + for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i) + { + myBVHThreads.ChangeValue(i).Wait(); + } + myToStopBVHThread = Standard_False; + myIsStarted = Standard_False; +} + +//================================================== +// Function: WaitThreads +// Purpose : +//================================================== +void SelectMgr_BVHThreadPool::WaitThreads() +{ + myIdleEvent.Wait(); + + LockBVHBuildMutex(); + UnlockBVHBuildMutex(); +} + +//======================================================================= +//function : BuildBVH +//purpose : +//======================================================================= +void SelectMgr_BVHThreadPool::BuildBVH (const Handle(Select3D_SensitiveEntity)& theEntity) +{ + myBVHListMutex.Lock(); + myBVHToBuildList.Append (theEntity); + myWakeEvent.Set(); + myIdleEvent.Reset(); + myBVHListMutex.Unlock(); + + if (!myIsStarted) + { + myIsStarted = Standard_True; + for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i) + { + myBVHThreads.ChangeValue(i).Run((Standard_Address)(&myBVHBuildData.ChangeValue(i))); + } + } +} + +//======================================================================= +//function : buildBVHThreadFunc +//purpose : +//======================================================================= +Standard_Address SelectMgr_BVHThreadPool::buildBVHThreadFunc (Standard_Address data) +{ + BVHBuild_Data* aData = reinterpret_cast (data); + SelectMgr_BVHThreadPool* aPool = aData->Pool; + Standard_Mutex& aBVHBuildMutex = aData->Mutex; + + for (;;) + { + aPool->myWakeEvent.Wait(); + + if (aPool->myToStopBVHThread) + { + break; + } + + aPool->myBVHListMutex.Lock(); + if (aPool->myBVHToBuildList.IsEmpty()) + { + aPool->myWakeEvent.Reset(); + aPool->myIdleEvent.Set(); + aPool->myBVHListMutex.Unlock(); + continue; + } + Handle(Select3D_SensitiveEntity) anEntity = aPool->myBVHToBuildList.First(); + aPool->myBVHToBuildList.RemoveFirst(); + + aBVHBuildMutex.Lock(); + aPool->myBVHListMutex.Unlock(); + + if (!anEntity.IsNull()) + { + anEntity->BVH(); + } + aBVHBuildMutex.Unlock(); + } + + return (Standard_Address)(0); +} + +//======================================================================= +//function : LockBVHBuildMutex +//purpose : +//======================================================================= +void SelectMgr_BVHThreadPool::LockBVHBuildMutex() +{ + for (Standard_Integer i = myBVHBuildData.Lower(); i <= myBVHBuildData.Upper(); ++i) + { + myBVHBuildData.ChangeValue(i).Mutex.Lock(); + } +} + +//======================================================================= +//function : UnlockBVHBuildMutex +//purpose : +//======================================================================= +void SelectMgr_BVHThreadPool::UnlockBVHBuildMutex() +{ + for (Standard_Integer i = myBVHBuildData.Lower(); i <= myBVHBuildData.Upper(); ++i) + { + myBVHBuildData.ChangeValue(i).Mutex.Unlock(); + } +} + diff --git a/src/SelectMgr/SelectMgr_BVHThreadPool.hxx b/src/SelectMgr/SelectMgr_BVHThreadPool.hxx new file mode 100644 index 0000000000..c1d1ebd915 --- /dev/null +++ b/src/SelectMgr/SelectMgr_BVHThreadPool.hxx @@ -0,0 +1,60 @@ +#ifndef _SelectMgr_BVHThreadPool_HeaderFile +#define _SelectMgr_BVHThreadPool_HeaderFile + +#include +#include +#include +#include +#include + +//! Class defining a thread pool for building BVH for Select3D_SensitiveEntity in multi-threaded mode. +class SelectMgr_BVHThreadPool : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(SelectMgr_BVHThreadPool, Standard_Transient) +public: + //! Main constructor + Standard_EXPORT SelectMgr_BVHThreadPool (Standard_Integer theNbThreads); + + //! Destructor + Standard_EXPORT virtual ~SelectMgr_BVHThreadPool(); + +public: + //! Queue a sensitive entity to build its BVH + Standard_EXPORT void BuildBVH (const Handle(Select3D_SensitiveEntity)& theEntity); + + //! Lock mutexes for building BVH + Standard_EXPORT void LockBVHBuildMutex(); + + //! Unlock mutexes for building BVH + Standard_EXPORT void UnlockBVHBuildMutex(); + + //! Stops threads + Standard_EXPORT void StopThreads(); + + //! Waits for all threads finish their jobs + Standard_EXPORT void WaitThreads(); + +protected: + + //! Thread function, accept address of BVHBuild_Data struct as parameter + static Standard_Address buildBVHThreadFunc (Standard_Address data); + +protected: + + //! Structure that will be passed to a separate thread + struct BVHBuild_Data + { + SelectMgr_BVHThreadPool* Pool; + Standard_Mutex Mutex; + }; + NCollection_List myBVHToBuildList; //!< list of queued sensitive entities + NCollection_Array1 myBVHThreads; //!< threads to build BVH + Standard_Boolean myToStopBVHThread; //!< flag to stop BVH threads + Standard_Mutex myBVHListMutex; //!< mutex for interaction with myBVHToBuildList + NCollection_Array1 myBVHBuildData; //!< list of mutexes for building BVH + Standard_Condition myWakeEvent; //!< raises when any sensitive is added to the BVH list + Standard_Condition myIdleEvent; //!< raises when BVH list become empty + Standard_Boolean myIsStarted; //!< indicates that threads are running +}; + +#endif diff --git a/src/SelectMgr/SelectMgr_SelectionManager.cxx b/src/SelectMgr/SelectMgr_SelectionManager.cxx index 195ed54c75..99545fee22 100644 --- a/src/SelectMgr/SelectMgr_SelectionManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectionManager.cxx @@ -484,6 +484,16 @@ void SelectMgr_SelectionManager::loadMode (const Handle(SelectMgr_SelectableObje theObject->AddSelection (aNewSel, theMode); aNewSel->UpdateBVHStatus (SelectMgr_TBU_Remove); aNewSel->SetSelectionState (SelectMgr_SOS_Deactivated); + + if (mySelector->ToPrebuildBVH()) + { + NCollection_Vector::Iterator anIter(aNewSel->Entities()); + for (; anIter.More(); anIter.Next()) + { + const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value()->BaseSensitive(); + mySelector->QueueBVHBuild(anEntity); + } + } } } return; @@ -496,6 +506,16 @@ void SelectMgr_SelectionManager::loadMode (const Handle(SelectMgr_SelectableObje mySelector->AddSelectionToObject (theObject, aNewSel); aNewSel->UpdateBVHStatus (SelectMgr_TBU_None); } + + if (mySelector->ToPrebuildBVH()) + { + NCollection_Vector::Iterator anIter(aNewSel->Entities()); + for (; anIter.More(); anIter.Next()) + { + const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value()->BaseSensitive(); + mySelector->QueueBVHBuild(anEntity); + } + } } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 9e467d2df6..1ce25db8a9 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -125,7 +125,8 @@ myToUpdateTolerance (Standard_True), myCameraScale (1.0), myCurRank (0), myIsLeftChildQueuedFirst (Standard_False), -myEntityIdx (0) +myEntityIdx (0), +myToPrebuildBVH (Standard_False) { myEntitySetBuilder = new BVH_BinnedBuilder (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True); } @@ -543,6 +544,11 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable //======================================================================= void SelectMgr_ViewerSelector::TraverseSensitives() { + if (myToPrebuildBVH) + { + myBVHThreadPool->LockBVHBuildMutex(); + } + mystored.Clear(); Standard_Integer aWidth; @@ -679,6 +685,11 @@ void SelectMgr_ViewerSelector::TraverseSensitives() } SortResult(); + + if (myToPrebuildBVH) + { + myBVHThreadPool->UnlockBVHBuildMutex(); + } } //================================================== @@ -1046,3 +1057,32 @@ void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean the { mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow); } + +//======================================================================= +//function : SetToPrebuildBVH +//purpose : +//======================================================================= +void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum) +{ + if (!theToPrebuild && !myBVHThreadPool.IsNull()) + { + myBVHThreadPool->StopThreads(); + } + else if (theToPrebuild) + { + myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum); + } + myToPrebuildBVH = theToPrebuild; +} + +//======================================================================= +//function : QueueBVHBuild +//purpose : +//======================================================================= +void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity) +{ + if (myToPrebuildBVH) + { + myBVHThreadPool->BuildBVH (theEntity); + } +} \ No newline at end of file diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx index 70b032cd1c..9929ef79f2 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx @@ -31,6 +31,7 @@ #include #include #include +#include class SelectMgr_SelectionManager; class SelectMgr_SensitiveEntitySet; @@ -245,6 +246,20 @@ public: Standard_DEPRECATED("Deprecated method DetectedEntity() should be replaced by DetectedEntity(int)") Standard_EXPORT const Handle(Select3D_SensitiveEntity)& DetectedEntity() const; +public: + + //! Enables/disables building BVH for sensitives in separate threads + Standard_EXPORT void SetToPrebuildBVH(Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum = -1); + + //! Queue a sensitive entity to build its BVH + Standard_EXPORT void QueueBVHBuild(const Handle(Select3D_SensitiveEntity)& theEntity); + + //! Returns TRUE if building BVH for sensitives in separate threads is enabled + Standard_Boolean ToPrebuildBVH() + { + return myToPrebuildBVH; + } + protected: Standard_EXPORT SelectMgr_ViewerSelector(); @@ -336,6 +351,9 @@ protected: gp_Dir myCameraDir; Standard_Real myCameraScale; + Standard_Boolean myToPrebuildBVH; + Handle(SelectMgr_BVHThreadPool) myBVHThreadPool; + private: Handle(TColStd_HArray1OfInteger) myIndexes;