Skip to content

Commit

Permalink
BVH improvements (#1429)
Browse files Browse the repository at this point in the history
* Add constructor

* Eliminate extra copy of each bounding box

---------

Co-authored-by: format-robot <[email protected]>
  • Loading branch information
adayton1 and format-robot authored Oct 14, 2024
1 parent f596660 commit 3636238
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 43 deletions.
38 changes: 37 additions & 1 deletion src/axom/spin/BVH.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,43 @@ class BVH
BVH() : m_AllocatorID(axom::execution_space<ExecSpace>::allocatorID()) { }

/*!
* \brief Initializes a BVH instance, of specified dimension, over a given set
* \brief Constructs a BVH instance of specified dimension over a given set
* of geometric entities, each represented by its corresponding axis-aligned
* bounding box.
*
* \param [in] boxes buffer consisting of bounding boxes for each entity.
* \param [in] numItems the total number of items to store in the BVH.
* \param [in] allocatorID the ID of the allocator to use in BVH construction.
* \param [in] scaleFactor the scale factor for the given bounding boxes.
* \param [in] tolerance the tolerance to use when querying the BVH.
*
* \warning The supplied boxes array must point to a buffer in a memory space
* that is compatible with the execution space. For example, when using
* CUDA_EXEC, boxes must be in unified memory or GPU memory. The supplied
* allocator ID must also correspond to an umpire allocator and be compatible
* with the execution space. The code currently does not check for these
* conditions.
*
* \pre boxes != nullptr
* \pre numItems > 0
* \pre allocatorID must correspond to an Umpire allocator and be compatible
* with the execution space
*/
template <typename BoxIndexable>
BVH(const BoxIndexable boxes,
IndexType numItems,
int allocatorID = axom::execution_space<ExecSpace>::allocatorID(),
FloatType tolerance = DEFAULT_TOLERANCE,
FloatType scaleFactor = DEFAULT_SCALE_FACTOR)
: m_AllocatorID {allocatorID}
, m_tolerance {tolerance}
, m_scaleFactor {scaleFactor}
{
initialize(boxes, numItems);
}

/*!
* \brief Initializes a BVH instance of specified dimension over a given set
* of geometric entities, each represented by its corresponding axis-aligned
* bounding box.
*
Expand Down
7 changes: 2 additions & 5 deletions src/axom/spin/internal/linear_bvh/build_radix_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,8 @@ void transform_boxes(const BoxIndexable boxes,
for_all<ExecSpace>(
size,
AXOM_LAMBDA(std::int32_t i) {
primal::BoundingBox<FloatType, NDIMS> aabb = boxes[i];

aabb.scale(scale_factor);

aabbs[i] = aabb;
aabbs[i] = boxes[i];
aabbs[i].scale(scale_factor);
});
}

Expand Down
137 changes: 100 additions & 37 deletions src/axom/spin/tests/spin_bvh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,16 @@ void generate_aabbs_and_centroids(
//------------------------------------------------------------------------------

/*!
* \brief Tests the construction of the BVH in 2D by inserting two bounding
* boxes in the BVH and ensuring that the bounds of the BVH are as expected.
* \brief Tests building the BVH by inserting two bounding boxes
* in the BVH and ensuring that the bounds of the BVH are as expected.
*/
template <typename ExecSpace, typename FloatType>
void check_build_bvh2d()
template <int Dimension, typename ExecSpace, typename FloatType>
void check_build_bvh()
{
constexpr int NUM_BOXES = 2;
constexpr int NDIMS = 2;

using BoxType = typename primal::BoundingBox<FloatType, NDIMS>;
using PointType = typename primal::Point<FloatType, NDIMS>;
using BoxType = typename primal::BoundingBox<FloatType, Dimension>;
using PointType = typename primal::Point<FloatType, Dimension>;

const int hostAllocatorID =
axom::execution_space<axom::SEQ_EXEC>::allocatorID();
Expand All @@ -216,20 +215,18 @@ void check_build_bvh2d()
boxes[0] = BoxType {PointType(0.), PointType(1.)};
boxes[1] = BoxType {PointType(1.), PointType(2.)};

spin::BVH<NDIMS, ExecSpace, FloatType> bvh;

// Copy boxes to device
axom::Array<BoxType> boxesDevice(boxes, deviceAllocatorID);

spin::BVH<Dimension, ExecSpace, FloatType> bvh;
bvh.setScaleFactor(1.0); // i.e., no scaling
bvh.initialize(boxesDevice.view(), NUM_BOXES);

int allocatorID = bvh.getAllocatorID();
EXPECT_EQ(allocatorID, axom::execution_space<ExecSpace>::allocatorID());
EXPECT_EQ(bvh.getAllocatorID(), deviceAllocatorID);

BoxType bounds = bvh.getBounds();

for(int idim = 0; idim < NDIMS; ++idim)
for(int idim = 0; idim < Dimension; ++idim)
{
EXPECT_NEAR(bounds.getMin()[idim], 0.0, EPS);
EXPECT_NEAR(bounds.getMax()[idim], 2.0, EPS);
Expand All @@ -239,17 +236,16 @@ void check_build_bvh2d()
//------------------------------------------------------------------------------

/*!
* \brief Tests the construction of the BVH in 3D by inserting two bounding
* \brief Tests the constructor of the BVH by inserting two bounding
* boxes in the BVH and ensuring that the bounds of the BVH are as expected.
*/
template <typename ExecSpace, typename FloatType>
void check_build_bvh3d()
template <int Dimension, typename ExecSpace, typename FloatType>
void check_construct_bvh()
{
constexpr int NUM_BOXES = 2;
constexpr int NDIMS = 3;

using BoxType = typename primal::BoundingBox<FloatType, NDIMS>;
using PointType = typename primal::Point<FloatType, NDIMS>;
using BoxType = typename primal::BoundingBox<FloatType, Dimension>;
using PointType = typename primal::Point<FloatType, Dimension>;

const int hostAllocatorID =
axom::execution_space<axom::SEQ_EXEC>::allocatorID();
Expand All @@ -259,20 +255,25 @@ void check_build_bvh3d()
boxes[0] = BoxType {PointType(0.), PointType(1.)};
boxes[1] = BoxType {PointType(1.), PointType(2.)};

spin::BVH<NDIMS, ExecSpace, FloatType> bvh;

// Copy boxes to device
axom::Array<BoxType> boxesDevice(boxes, deviceAllocatorID);

bvh.setScaleFactor(1.0); // i.e., no scaling
bvh.initialize(boxesDevice.view(), NUM_BOXES);
FloatType tolerance = static_cast<FloatType>(0.0); // i.e., no tolerance
FloatType scaleFactor = static_cast<FloatType>(1.0); // i.e., no scaling

int allocatorID = bvh.getAllocatorID();
EXPECT_EQ(allocatorID, axom::execution_space<ExecSpace>::allocatorID());
spin::BVH<Dimension, ExecSpace, FloatType> bvh(boxesDevice.view(),
NUM_BOXES,
deviceAllocatorID,
tolerance,
scaleFactor);

EXPECT_EQ(bvh.getAllocatorID(), deviceAllocatorID);
EXPECT_EQ(bvh.getTolerance(), tolerance);
EXPECT_EQ(bvh.getScaleFactor(), scaleFactor);

BoxType bounds = bvh.getBounds();

for(int idim = 0; idim < NDIMS; ++idim)
for(int idim = 0; idim < Dimension; ++idim)
{
EXPECT_NEAR(bounds.getMin()[idim], 0.0, EPS);
EXPECT_NEAR(bounds.getMax()[idim], 2.0, EPS);
Expand Down Expand Up @@ -1644,18 +1645,32 @@ void check_0_or_1_bbox_2d()

//------------------------------------------------------------------------------
// UNIT TESTS
//------------------------------------------------------------------------------
TEST(spin_bvh, build2D_sequential)
{
check_build_bvh<2, axom::SEQ_EXEC, double>();
check_build_bvh<2, axom::SEQ_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, construct2D_sequential)
{
check_build_bvh2d<axom::SEQ_EXEC, double>();
check_build_bvh2d<axom::SEQ_EXEC, float>();
check_construct_bvh<2, axom::SEQ_EXEC, double>();
check_construct_bvh<2, axom::SEQ_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, build3D_sequential)
{
check_build_bvh<3, axom::SEQ_EXEC, double>();
check_build_bvh<3, axom::SEQ_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, construct3D_sequential)
{
check_build_bvh3d<axom::SEQ_EXEC, double>();
check_build_bvh3d<axom::SEQ_EXEC, float>();
check_construct_bvh<3, axom::SEQ_EXEC, double>();
check_construct_bvh<3, axom::SEQ_EXEC, float>();
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -1745,17 +1760,31 @@ TEST(spin_bvh, single_bbox_sequential)
//------------------------------------------------------------------------------
#if defined(AXOM_USE_OPENMP) && defined(AXOM_USE_RAJA)

TEST(spin_bvh, build2D_omp)
{
check_build_bvh<2, axom::OMP_EXEC, double>();
check_build_bvh<2, axom::OMP_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, construct2D_omp)
{
check_build_bvh2d<axom::OMP_EXEC, double>();
check_build_bvh2d<axom::OMP_EXEC, float>();
check_construct_bvh<2, axom::OMP_EXEC, double>();
check_construct_bvh<2, axom::OMP_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, build3D_omp)
{
check_build_bvh<3, axom::OMP_EXEC, double>();
check_build_bvh<3, axom::OMP_EXEC, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, construct3D_omp)
{
check_build_bvh3d<axom::OMP_EXEC, double>();
check_build_bvh3d<axom::OMP_EXEC, float>();
check_construct_bvh<3, axom::OMP_EXEC, double>();
check_construct_bvh<3, axom::OMP_EXEC, float>();
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -1825,6 +1854,23 @@ TEST(spin_bvh, single_bbox_omp)
//------------------------------------------------------------------------------
#if defined(AXOM_USE_GPU) && defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE)

TEST(spin_bvh, build2D_device)
{
constexpr int BLOCK_SIZE = 256;

#if defined(__CUDACC__)
using exec = axom::CUDA_EXEC<BLOCK_SIZE>;
#elif defined(__HIPCC__)
using exec = axom::HIP_EXEC<BLOCK_SIZE>;
#else
using exec = axom::SEQ_EXEC;
#endif

check_build_bvh<2, exec, double>();
check_build_bvh<2, exec, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, construct2D_device)
{
constexpr int BLOCK_SIZE = 256;
Expand All @@ -1837,8 +1883,25 @@ TEST(spin_bvh, construct2D_device)
using exec = axom::SEQ_EXEC;
#endif

check_build_bvh2d<exec, double>();
check_build_bvh2d<exec, float>();
check_construct_bvh<2, exec, double>();
check_construct_bvh<2, exec, float>();
}

//------------------------------------------------------------------------------
TEST(spin_bvh, build3D_device)
{
constexpr int BLOCK_SIZE = 256;

#if defined(__CUDACC__)
using exec = axom::CUDA_EXEC<BLOCK_SIZE>;
#elif defined(__HIPCC__)
using exec = axom::HIP_EXEC<BLOCK_SIZE>;
#else
using exec = axom::SEQ_EXEC;
#endif

check_build_bvh<3, exec, double>();
check_build_bvh<3, exec, float>();
}

//------------------------------------------------------------------------------
Expand All @@ -1854,8 +1917,8 @@ TEST(spin_bvh, construct3D_device)
using exec = axom::SEQ_EXEC;
#endif

check_build_bvh3d<exec, double>();
check_build_bvh3d<exec, float>();
check_construct_bvh<3, exec, double>();
check_construct_bvh<3, exec, float>();
}

//------------------------------------------------------------------------------
Expand Down

0 comments on commit 3636238

Please sign in to comment.