// commercial license or contractual agreement.
#include <BVH_Triangulation.hxx>
-
-#ifdef HAVE_TBB
- // On Windows, function TryEnterCriticalSection has appeared in Windows NT
- // and is surrounded by #ifdef in MS VC++ 7.1 headers.
- // Thus to use it we need to define appropriate macro saying that we will
- // run on Windows NT 4.0 at least
- #if defined(_WIN32) && !defined(_WIN32_WINNT)
- #define _WIN32_WINNT 0x0501
- #endif
-
- #include <tbb/tbb.h>
-#endif
+#include <OSD_Parallel.hxx>
// =======================================================================
// function : BVH_DistanceField
#undef BVH_DOT3
-#ifdef HAVE_TBB
-
//! Tool object for parallel construction of distance field (uses Intel TBB).
template<class T, int N>
class BVH_ParallelDistanceFieldBuilder
//
}
- void operator() (const tbb::blocked_range<Standard_Integer>& theRange) const
+ void operator() (const Standard_Integer theIndex) const
{
- myOutField->BuildSlices (*myGeometry, theRange.begin(), theRange.end());
+ myOutField->BuildSlices (*myGeometry, theIndex, theIndex + 1);
}
};
-#endif
-
// =======================================================================
// function : BuildSlices
// purpose : Performs building of distance field for the given Z slices
myVoxelSize.y() = (myCornerMax.y() - myCornerMin.y()) / myDimensionY;
myVoxelSize.z() = (myCornerMax.z() - myCornerMin.z()) / myDimensionZ;
-#ifdef HAVE_TBB
-
- tbb::parallel_for (tbb::blocked_range<Standard_Integer> (0, myDimensionZ),
- BVH_ParallelDistanceFieldBuilder<T, N> (this, &theGeometry));
-
-#else
-
- BuildSlices (theGeometry, 0, myDimensionZ);
-
-#endif
+ OSD_Parallel::For (0, myDimensionZ, BVH_ParallelDistanceFieldBuilder<T, N> (this, &theGeometry));
return Standard_True;
}
return 0;
}
-#ifdef HAVE_TBB
-
- //! TBB task for parallel bounds updating.
template<class T, int N>
- class UpdateBoundTask: public tbb::task
+ struct BoundData
{
-
- BVH_Set<T, N>* mySet; //!< Set of geometric objects
+ BVH_Set <T, N>* mySet; //!< Set of geometric objects
BVH_Tree<T, N>* myBVH; //!< BVH tree built over the set
Standard_Integer myNode; //!< BVH node to update bounding box
Standard_Integer myLevel; //!< Level of the processed BVH node
Standard_Integer* myHeight; //!< Height of the processed BVH node
+ };
+ //! Task for parallel bounds updating.
+ template<class T, int N>
+ class UpdateBoundTask
+ {
public:
- //! Creates new TBB parallel bound update task.
- UpdateBoundTask (BVH_Set<T, N>* theSet,
- BVH_Tree<T, N>* theBVH,
- Standard_Integer theNode,
- Standard_Integer theLevel,
- Standard_Integer* theHeight)
- : mySet (theSet), myBVH (theBVH), myNode (theNode), myLevel (theLevel), myHeight (theHeight) {}
-
//! Executes the task.
- tbb::task* execute()
+ void operator()(const BoundData<T, N>& theData) const
{
- if (myBVH->IsOuter (myNode) || myLevel > 2)
+ if (theData.myBVH->IsOuter (theData.myNode) || theData.myLevel > 2)
{
- *myHeight = BVH::UpdateBounds (mySet, myBVH, myNode);
+ *theData.myHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, theData.myNode);
}
else
{
Standard_Integer aLftHeight = 0;
Standard_Integer aRghHeight = 0;
- const Standard_Integer aLftChild = myBVH->NodeInfoBuffer()[myNode].y();
- const Standard_Integer aRghChild = myBVH->NodeInfoBuffer()[myNode].z();
+ const Standard_Integer aLftChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].y();
+ const Standard_Integer aRghChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].z();
- Standard_Integer aCount = 1;
- tbb::task_list aList;
- if (!myBVH->IsOuter (aLftChild))
+ std::vector<BoundData<T, N> > aList;
+ aList.reserve (2);
+ if (!theData.myBVH->IsOuter (aLftChild))
{
- ++aCount;
- aList.push_back (*new ( allocate_child() )
- UpdateBoundTask (mySet, myBVH, aLftChild, myLevel + 1, &aLftHeight));
+ BoundData<T, N> aBoundData = {theData.mySet, theData.myBVH, aLftChild, theData.myLevel + 1, &aLftHeight};
+ aList.push_back (aBoundData);
}
else
{
- aLftHeight = BVH::UpdateBounds (mySet, myBVH, aLftChild);
+ aLftHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, aLftChild);
}
- if (!myBVH->IsOuter (aRghChild))
+ if (!theData.myBVH->IsOuter (aRghChild))
{
- ++aCount;
- aList.push_back (*new( allocate_child() )
- UpdateBoundTask (mySet, myBVH, aRghChild, myLevel + 1, &aRghHeight));
+ BoundData<T, N> aBoundData = {theData.mySet, theData.myBVH, aRghChild, theData.myLevel + 1, &aRghHeight};
+ aList.push_back (aBoundData);
}
else
{
- aRghHeight = BVH::UpdateBounds (mySet, myBVH, aRghChild);
+ aRghHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, aRghChild);
}
- if (aCount > 1)
+ if (!aList.empty())
{
- set_ref_count (aCount);
- spawn_and_wait_for_all (aList);
+ OSD_Parallel::ForEach (aList.begin (), aList.end (), UpdateBoundTask<T, N> ());
}
- typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = myBVH->MinPointBuffer()[aLftChild];
- typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = myBVH->MaxPointBuffer()[aLftChild];
- typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = myBVH->MinPointBuffer()[aRghChild];
- typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = myBVH->MaxPointBuffer()[aRghChild];
+ typename BVH_Box<T, N>::BVH_VecNt aLftMinPoint = theData.myBVH->MinPointBuffer()[aLftChild];
+ typename BVH_Box<T, N>::BVH_VecNt aLftMaxPoint = theData.myBVH->MaxPointBuffer()[aLftChild];
+ typename BVH_Box<T, N>::BVH_VecNt aRghMinPoint = theData.myBVH->MinPointBuffer()[aRghChild];
+ typename BVH_Box<T, N>::BVH_VecNt aRghMaxPoint = theData.myBVH->MaxPointBuffer()[aRghChild];
BVH::BoxMinMax<T, N>::CwiseMin (aLftMinPoint, aRghMinPoint);
BVH::BoxMinMax<T, N>::CwiseMax (aLftMaxPoint, aRghMaxPoint);
- myBVH->MinPointBuffer()[myNode] = aLftMinPoint;
- myBVH->MaxPointBuffer()[myNode] = aLftMaxPoint;
+ theData.myBVH->MinPointBuffer()[theData.myNode] = aLftMinPoint;
+ theData.myBVH->MaxPointBuffer()[theData.myNode] = aLftMaxPoint;
- *myHeight = Max (aLftHeight, aRghHeight) + 1;
+ *theData.myHeight = Max (aLftHeight, aRghHeight) + 1;
}
- return NULL;
}
};
-
-#endif
}
// =======================================================================
theBVH->MaxPointBuffer().resize (theBVH->NodeInfoBuffer().size());
Standard_Integer aHeight = 0;
-
-#ifdef HAVE_TBB
-
- // Note: Although TBB tasks are allocated using placement
- // new, we do not need to delete them explicitly
- BVH::UpdateBoundTask<T, N>& aRootTask = *new ( tbb::task::allocate_root() )
- BVH::UpdateBoundTask<T, N> (theSet, theBVH, 0, 0, &aHeight);
-
- tbb::task::spawn_root_and_wait (aRootTask);
-
-#else
-
- aHeight = BVH::UpdateBounds (theSet, theBVH, 0);
-
-#endif
+ BVH::BoundData<T, N> aBoundData = { theSet, theBVH, 0, 0, &aHeight };
+ BVH::UpdateBoundTask<T, N> aBoundTask;
+ aBoundTask (aBoundData);
BVH_Builder<T, N>::updateDepth (theBVH, aHeight);
}
#include <BVH_Builder.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Shared.hxx>
+#include <OSD_Parallel.hxx>
#include <algorithm>
-#ifdef HAVE_TBB
- // On Windows, function TryEnterCriticalSection has appeared in Windows NT
- // and is surrounded by #ifdef in MS VC++ 7.1 headers.
- // Thus to use it we need to define appropriate macro saying that we will
- // run on Windows NT 4.0 at least
- #if defined(_WIN32) && !defined(_WIN32_WINNT)
- #define _WIN32_WINNT 0x0501
- #endif
-
- #include <tbb/parallel_invoke.h>
-#endif
-
//! Pair of Morton code and primitive ID.
typedef std::pair<Standard_Integer, Standard_Integer> BVH_EncodedLink;
private:
- //! TBB functor class to run sorting.
- struct Functor
+ //! Structure defining sorting range.
+ struct SortRange
{
LinkIterator myStart; //!< Start element of exclusive sorting range
LinkIterator myFinal; //!< Final element of exclusive sorting range
Standard_Integer myDigit; //!< Bit number used for partition operation
+ };
- //! Creates new sorting functor.
- Functor (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit)
- : myStart (theStart), myFinal (theFinal), myDigit (theDigit) {}
-
+ //! Functor class to run sorting in parallel.
+ struct Functor
+ {
//! Runs sorting function for the given range.
- void operator() () const
+ void operator()(const SortRange& theRange) const
{
- RadixSorter::Sort (myStart, myFinal, myDigit);
+ RadixSorter::Sort (theRange.myStart, theRange.myFinal, theRange.myDigit);
}
};
static void Sort (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit)
{
- #ifdef HAVE_TBB
if (theDigit < 24)
{
BVH::RadixSorter::perform (theStart, theFinal, theDigit);
else
{
LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit));
- tbb::parallel_invoke (Functor (theStart, anOffset, theDigit - 1),
- Functor (anOffset, theFinal, theDigit - 1));
+ SortRange aSplits[2] = {
+ {theStart, anOffset, theDigit - 1},
+ {anOffset, theFinal, theDigit - 1}
+ };
+
+ OSD_Parallel::ForEach (std::begin (aSplits), std::end (aSplits), Functor ());
}
- #else
- BVH::RadixSorter::perform (theStart, theFinal, theDigit);
- #endif
}
protected: