mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-19 13:40:49 +03:00
0031757: Visualization - Prebuild BVH for Select3D_SensitiveEntity in separate threads
(cherry picked from commit bb598fe0216163889af6aa054ec8081eb1cfd384)
This commit is contained in:
@@ -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
|
||||
|
157
src/SelectMgr/SelectMgr_BVHThreadPool.cxx
Normal file
157
src/SelectMgr/SelectMgr_BVHThreadPool.cxx
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <SelectMgr_BVHThreadPool.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
|
||||
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<OSD_Thread>(1, aBVHThreadsNum);
|
||||
myBVHBuildData = NCollection_Array1<BVHBuild_Data>(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<BVHBuild_Data*> (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();
|
||||
}
|
||||
}
|
||||
|
60
src/SelectMgr/SelectMgr_BVHThreadPool.hxx
Normal file
60
src/SelectMgr/SelectMgr_BVHThreadPool.hxx
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef _SelectMgr_BVHThreadPool_HeaderFile
|
||||
#define _SelectMgr_BVHThreadPool_HeaderFile
|
||||
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <Select3D_SensitiveEntity.hxx>
|
||||
#include <Standard_Condition.hxx>
|
||||
|
||||
//! 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<Handle(Select3D_SensitiveEntity)> myBVHToBuildList; //!< list of queued sensitive entities
|
||||
NCollection_Array1<OSD_Thread> myBVHThreads; //!< threads to build BVH
|
||||
Standard_Boolean myToStopBVHThread; //!< flag to stop BVH threads
|
||||
Standard_Mutex myBVHListMutex; //!< mutex for interaction with myBVHToBuildList
|
||||
NCollection_Array1<BVHBuild_Data> 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
|
@@ -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<Handle(SelectMgr_SensitiveEntity)>::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<Handle(SelectMgr_SensitiveEntity)>::Iterator anIter(aNewSel->Entities());
|
||||
for (; anIter.More(); anIter.Next())
|
||||
{
|
||||
const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value()->BaseSensitive();
|
||||
mySelector->QueueBVHBuild(anEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -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<Standard_Real, 3, 4> (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);
|
||||
}
|
||||
}
|
@@ -31,6 +31,7 @@
|
||||
#include <SelectMgr_StateOfSelection.hxx>
|
||||
#include <SelectMgr_ToleranceMap.hxx>
|
||||
#include <Standard_OStream.hxx>
|
||||
#include <SelectMgr_BVHThreadPool.hxx>
|
||||
|
||||
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;
|
||||
|
Reference in New Issue
Block a user