Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
24dccf8
Add cuBQL submodule and CMake setup
Waqar-ukaea Jun 18, 2026
dfba5d7
Added CuBQLRayTracer backend support
Waqar-ukaea Jun 18, 2026
32bbd86
Updated vk_device_probe to also probe for available openmp device
Waqar-ukaea Jun 18, 2026
fde3538
Add CMakePresets.json for openmp target offload flags
Waqar-ukaea Jun 18, 2026
0b9ee4b
Added tests for cuBQL backend
Waqar-ukaea Jun 18, 2026
b28c9dd
Added tools setup for cuBQL + updated ray_fire tool
Waqar-ukaea Jun 18, 2026
da5ffed
Updated particle sim tool to work with cuBQL backend
Waqar-ukaea Jun 18, 2026
4f71cdc
Updated ray_benchmark tool to work with cuBQL backend
Waqar-ukaea Jun 18, 2026
88b78a6
Update to latest cuBQL version in submodule
Waqar-ukaea Jun 18, 2026
cff9b88
Reverting back to working cuBQL commit as latest seems to break ray q…
Waqar-ukaea Jun 22, 2026
3b5ccab
Added a public facing ray hit buffer object for downstream applicatio…
Waqar-ukaea Jun 25, 2026
3f8735b
Minor optimizations and code clarity changes to cuBQL traversal kernel
Waqar-ukaea Jun 25, 2026
f7909f6
Updated ray payload for ray_fire_batch to include surface crossing me…
Waqar-ukaea Jul 14, 2026
d0228d7
Switch cuBQL to flattened per-volume BVHs
Waqar-ukaea Jul 17, 2026
1544225
Track maximum parent-volume bump on shared cuBQL surface meshes
Waqar-ukaea Jul 20, 2026
84cd932
Added test for batch ray fire
Waqar-ukaea Jul 31, 2026
f895344
Extended batch api tests to include a mult-volume test with full payl…
Waqar-ukaea Jul 31, 2026
e0a4bdf
Updated output on test failiure for batch ray fire
Waqar-ukaea Jul 31, 2026
de86dbd
Fix header file include of mesh_mocks after quad+hex rebase
Waqar-ukaea Aug 3, 2026
4703dae
Determine expected normals in batch_ray_fire_test via mesh_manager
Waqar-ukaea Aug 3, 2026
b857939
Update test_files submodule
Waqar-ukaea Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
[submodule "vendor/GPRT"]
path = vendor/GPRT
url = https://github.com/gprt-org/GPRT.git
[submodule "vendor/cuBQL"]
path = vendor/cuBQL
url = https://github.com/NVIDIA/cuBQL
57 changes: 54 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ option(XDG_ENABLE_LIBMESH "Enable support for the libMesh mesh library" OFF
option(XDG_LINK_MPI "Link with MPI (for dependency compatibility)" OFF)
option(XDG_ENABLE_EMBREE "Enable support for the Embree ray tracing library" ON)
option(XDG_ENABLE_GPRT "Enable support for the GPRT ray tracing library" OFF)
option(XDG_ENABLE_CUBQL "Enable support for the cuBQL ray tracing library" OFF)
option(XDG_BUILD_TESTS "Enable C++ unit testing" ON)
option(XDG_BUILD_TOOLS "Enable tools and miniapps" ON)

Expand All @@ -20,6 +21,10 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose build type" FORCE)
endif()

if(DEFINED XDG_CMAKE_PRESET)
message(STATUS "XDG CMake preset: ${XDG_CMAKE_PRESET}")
endif()

# Compiler options (things in this section may not be platform-portable)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

Expand Down Expand Up @@ -111,6 +116,12 @@ if(XDG_ENABLE_GPRT)
)
endif()

if(XDG_ENABLE_CUBQL)
list(APPEND VENDOR_PATHS
vendor/cuBQL
)
endif()

if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
option(XDG_GIT_SUBMODULE "Check submodules during build" ON)
if(XDG_GIT_SUBMODULE)
Expand Down Expand Up @@ -175,11 +186,12 @@ if (NOT XDG_ENABLE_MOAB AND NOT XDG_ENABLE_LIBMESH)
endif()

# Ensure at least one ray tracing backend is enabled
if (NOT XDG_ENABLE_EMBREE AND NOT XDG_ENABLE_GPRT)
if (NOT XDG_ENABLE_EMBREE AND NOT XDG_ENABLE_GPRT AND NOT XDG_ENABLE_CUBQL)
message(FATAL_ERROR
"No ray tracing backend enabled. Enable at least one of:\n"
" -DXDG_ENABLE_EMBREE=ON\n"
" -DXDG_ENABLE_GPRT=ON")
" -DXDG_ENABLE_GPRT=ON\n"
" -DXDG_ENABLE_CUBQL=ON")
endif()

# GPRT
Expand All @@ -188,6 +200,11 @@ if (XDG_ENABLE_GPRT)
add_subdirectory(vendor/GPRT)
endif()

if (XDG_ENABLE_CUBQL)
set(CUBQL_OMP ON CACHE BOOL "Build cuBQL with OpenMP target offload" FORCE)
add_subdirectory(vendor/cuBQL)
endif()

list(APPEND xdg_sources
src/geometry/measure.cpp
src/geometry/plucker.cpp
Expand Down Expand Up @@ -225,6 +242,23 @@ dbl_deviceCode

endif()

if (XDG_ENABLE_CUBQL)
list(APPEND xdg_sources
src/cuBQL/triangles.cpp
src/cuBQL/intersection.cpp
src/cuBQL/ray_tracer.cpp
)

# We need a precompile definition to switch to using the cuBQL math types in the shared
# plucker intersection code. The compile definition is used in dp__math.h
set_source_files_properties(
src/cuBQL/ray_tracer.cpp
src/cuBQL/intersection.cpp
PROPERTIES COMPILE_DEFINITIONS XDG_DP_MATH_CUBQL
)

endif()

if (XDG_ENABLE_LIBMESH)
list(APPEND xdg_sources
src/libmesh/mesh_manager.cpp
Expand Down Expand Up @@ -285,7 +319,12 @@ if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
endif()

# attempt to find OpenMP and include it if found
find_package(OpenMP)
if (XDG_ENABLE_CUBQL)
find_package(OpenMP REQUIRED)
else()
find_package(OpenMP)
endif()

if (OpenMP_CXX_FOUND)
target_link_libraries(xdg PRIVATE OpenMP::OpenMP_CXX)
target_compile_definitions(xdg PRIVATE XDG_HAVE_OPENMP)
Expand Down Expand Up @@ -323,6 +362,18 @@ if (XDG_ENABLE_GPRT)
target_link_options(xdg PRIVATE -Wl,--unresolved-symbols=ignore-in-shared-libs)
endif()

if (XDG_ENABLE_CUBQL)
target_compile_definitions(xdg PUBLIC XDG_ENABLE_CUBQL)
target_link_libraries(xdg PRIVATE $<BUILD_INTERFACE:cuBQL>)
# TODO: Stop relying on LD_LIBRARY_PATH for LLVM OpenMP offload runtimes.
# As a temporary measure whilst figuring out our way around cuBQL this is
# okay but in the long run we should aim for a more robust solutions here.
# Clang injects libomptarget when offload flags are supplied by presets, but
# CMake does not currently add that compiler runtime directory to RPATH.
# Add targeted BUILD_RPATH handling for libomptarget/libomp, and decide
# whether install RPATH should remain environment-module based or be opt-in.
endif()

target_link_libraries(xdg PRIVATE fmt::fmt)

# ==========================
Expand Down
68 changes: 68 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"version": 3,
"configurePresets": [
{
"name": "base",
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_FLAGS": "$env{PRESET_CXX_FLAGS} $env{LLVM_CXX_FLAGS} $env{COMMON_CXX_FLAGS}",
"XDG_CMAKE_PRESET": "${presetName}"
},
"environment": {
"COMMON_CXX_FLAGS": ""
}
},
{
"name": "llvm",
"inherits": ["base"],
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++"
},
"environment": {
"LLVM_CXX_FLAGS": "-fopenmp -fopenmp-cuda-mode"
}
},
{
"name": "cubql_llvm_ada",
"inherits": ["llvm"],
"displayName": "cuBQL LLVM OpenMP offload RTX 2000 Ada",
"cacheVariables": {
"XDG_ENABLE_CUBQL": "ON"
},
"environment": {
"PRESET_CXX_FLAGS": "-fopenmp-targets=nvptx64 -Xopenmp-target -march=sm_89"
}
},
{
"name": "nvhpc",
"inherits": ["base"],
"cacheVariables": {
"CMAKE_C_COMPILER": "nvc",
"CMAKE_CXX_COMPILER": "nvc++"
}
},
{
"name": "cubql_nvhpc_ada",
"inherits": ["nvhpc"],
"displayName": "cuBQL NVHPC OpenMP offload RTX 2000 Ada",
"cacheVariables": {
"XDG_ENABLE_CUBQL": "ON"
},
"environment": {
"PRESET_CXX_FLAGS": "-mp=gpu -Minfo=mp -gpu=cc89"
}
}
],
"buildPresets": [
{
"name": "cubql_llvm_ada",
"configurePreset": "cubql_llvm_ada"
},
{
"name": "cubql_nvhpc_ada",
"configurePreset": "cubql_nvhpc_ada"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#pragma once

#ifdef XDG_ENABLE_GPRT
#include "xdg/error.h"

// --------------------------------------------------------------------------------------
// Vulkan probe functions to check for ray tracing capable devices at runtime
// --------------------------------------------------------------------------------------
#ifdef XDG_ENABLE_GPRT

#include <cstring>
#include <string>
#include <vector>
Expand Down Expand Up @@ -90,5 +94,47 @@ inline bool system_has_vk_device()
missing);
return false;
}
#endif

// --------------------------------------------------------------------------------------
// OpenMP target probe functions to check for devices capable of running cuBQL at runtime
// --------------------------------------------------------------------------------------

#ifdef XDG_ENABLE_CUBQL

#include <omp.h>

inline bool system_has_omp_target_device()
{
const int device_count = omp_get_num_devices();
if (device_count <= 0) {
warning("No OpenMP target devices found; cuBQL ray tracer unavailable.");
return false;
}

const int host_id = omp_get_initial_device();
for (int device_id = 0; device_id < device_count; ++device_id) {
int value = 1;
void* d_value = omp_target_alloc(sizeof(int), device_id);
if (!d_value) continue;

const int copy_result = omp_target_memcpy(d_value,
&value,
sizeof(int),
0,
0,
device_id,
host_id);
omp_target_free(d_value, device_id);

if (copy_result == 0) {
write_message("Found OpenMP target device {}.", device_id);
return true;
}
}

warning("OpenMP target devices were found, but none accepted target allocation; cuBQL ray tracer unavailable.");
return false;
}

#endif
8 changes: 5 additions & 3 deletions include/xdg/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ enum class MeshLibrary {
// Ray Tracing library identifier
enum class RTLibrary {
EMBREE,
GPRT
GPRT,
CUBQL
};

static const std::map<MeshLibrary, std::string> MESH_LIB_TO_STR =
Expand All @@ -67,7 +68,8 @@ static const std::map<MeshLibrary, std::string> MESH_LIB_TO_STR =
static const std::map<RTLibrary, std::string> RT_LIB_TO_STR =
{
{RTLibrary::EMBREE, "EMBREE"},
{RTLibrary::GPRT, "GPRT"}
{RTLibrary::GPRT, "GPRT"},
{RTLibrary::CUBQL, "CUBQL"}
};

// Mesh identifer type
Expand Down Expand Up @@ -181,4 +183,4 @@ struct formatter<xdg::VolumeElementType> : fmt::formatter<std::string> {

}

#endif // include guard
#endif // include guard
30 changes: 30 additions & 0 deletions include/xdg/cuBQL/cuBQL_backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef _XDG_CUBQL_BACKEND_H
#define _XDG_CUBQL_BACKEND_H

#include <cstddef>
#include <type_traits>
#include <utility>
#include <vector>

#include <omp.h>

// Guards to prevent CUDA headers from being included in host code, which causes
// failed compilation with LLVM-clang.
#if defined(__CUDA_ARCH__) && !defined(__CUDACC__)
#undef __CUDA_ARCH__
#endif

#include "xdg/error.h"

namespace xdg::cubql {

struct Context {
int gpuID {0};
int hostID {omp_get_initial_device()};
};



} // namespace xdg::cubql

#endif // include guard
82 changes: 82 additions & 0 deletions include/xdg/cuBQL/intersection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef _XDG_CUBQL_INTERSECTION_H
#define _XDG_CUBQL_INTERSECTION_H

// Guards to prevent CUDA headers from being included in host code, which causes
// failed compilation with LLVM-clang.
#if defined(__CUDA_ARCH__) && !defined(__CUDACC__)
#undef __CUDA_ARCH__
#endif

#include <cstddef>
#include <vector>

#include "xdg/constants.h"
#include "xdg/device_ray.h"
#include "xdg/cuBQL/triangles.h"
#include "cuBQL/math/vec.h"

namespace xdg {

struct CuBQLRay {
cuBQL::vec3d origin;
cuBQL::vec3d direction;
double tMin {0.0};
double tMax {INFTY};
MeshID volume {ID_NONE}; // volume we are tracing ray against
};

// TODO - Consider whether this is useful/necessary as its own struct
// struct CuBQLExcludeList {
// const MeshID* primitives {nullptr};
// int count {0};
// };

struct CuBQLSurfaceHit {
double distance {INFTY};
MeshID surface {ID_NONE};
MeshID primitive {ID_NONE};
PointInVolume piv {OUTSIDE};
MeshID next_volume {ID_NONE};
SurfaceBoundaryCondition boundary_condition {SurfaceBoundaryCondition::UNSET};
cuBQL::vec3d normal {0.0};

bool hit_found() const { return primitive != ID_NONE; }
};

inline bool orientation_cull(double normal_dot_direction,
HitOrientation orientation)
{
if (orientation == HitOrientation::ANY) return false;

if (orientation == HitOrientation::EXITING && normal_dot_direction < 0.0) {
return true;
} else if (orientation == HitOrientation::ENTERING && normal_dot_direction >= 0.0) {
return true;
}

return false;
}

/*
Wrapper for launching a single ray intersection query against the surface tree, with Host<->Device staging of ray and hit data
Performs host side staging and transfer hit data back to host after device side traversal
*/
void
intersect_surface_tree_scalar(const cubql::Context& context,
const CuBQLVolumeGroup& volume_group,
const CuBQLRay& ray,
CuBQLSurfaceHit& hit,
HitOrientation hit_orientation,
const std::vector<MeshID>* exclude_primitives);


void
intersect_surface_tree_batch(const cubql::Context& context,
const CuBQLVolumeGroup::DD* d_volume_to_group,
XDGRayHit* d_ray_hits,
std::size_t num_rays,
HitOrientation hit_orientation);

} // namespace xdg

#endif // include guard
Loading
Loading