1
0
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:
age
2020-09-08 14:44:21 +03:00
committed by nds
parent 76413cb11c
commit ffdf673ef3
6 changed files with 298 additions and 1 deletions

View File

@@ -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

View 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();
}
}

View 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

View File

@@ -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);
}
}
}
//=======================================================================

View File

@@ -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);
}
}

View File

@@ -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;