Skip to content
40 changes: 40 additions & 0 deletions include/xdg/gprt/ray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef _XDG_GPRT_RAY_H
#define _XDG_GPRT_RAY_H

#include "gprt.h"
#include "../shared_enums.h"

/*
* Double-precision ray and hit structures used by the GPRT backend.
*
* These types are not inherently GPRT-specific, but we keep them here for now
* since GPRT is the only GPU backend. If another GPU backend is added, these
* can be reused. Unifying them with the CPU/Embree types is possible, but may
* not be worth the added complexity at this stage.
*/

namespace xdg {

struct dblRay
{
double3 origin;
double3 direction;
int volume_mesh_id; // MeshID of the volume this ray will be traced against
uint enabled; // Flag to indicate if the ray is active
int32_t* exclude_primitives; // Optional for excluding primitives
int32_t exclude_count; // Number of excluded primitives
};


struct dblHit
{
double distance;
int surf_id;
int primitive_id;
PointInVolume piv; // Point in volume check result (0 for outside, 1 for inside)
};

}


#endif
98 changes: 82 additions & 16 deletions include/xdg/gprt/ray_tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@

#include "xdg/constants.h"
#include "xdg/mesh_manager_interface.h"
#include "xdg/primitive_ref.h"
#include "xdg/geometry_data.h"
#include "xdg/ray_tracing_interface.h"
#include "xdg/ray.h"
#include "xdg/error.h"
#include "gprt/gprt.h"

#include "shared_structs.h"

extern GPRTProgram dbl_deviceCode;
Expand All @@ -26,17 +23,16 @@ enum class RayGenType {
};

struct gprtRayHit {
size_t capacity = 1; // Max number of rays allocated
size_t size = 0; // Current number of active rays
DeviceRayHitBuffers view; // external facing POD for rayhit buffers
size_t size = 0; // Current number of active rays

GPRTBufferOf<dblRay> ray = nullptr;
GPRTBufferOf<dblHit> hit = nullptr;
dblRay* devRayAddr = nullptr;
dblHit* devHitAddr = nullptr;

bool is_valid() const { return capacity > 0 && ray && hit && devRayAddr && devHitAddr; }
bool is_valid() const {
return view.capacity > 0 && ray && hit && view.rayDevPtr && view.hitDevPtr;
}
};

class GPRTRayTracer : public RayTracer {
public:
GPRTRayTracer();
Expand Down Expand Up @@ -83,15 +79,40 @@ class GPRTRayTracer : public RayTracer {
const Direction* direction = nullptr,
const std::vector<MeshID>* exclude_primitives = nullptr) const override;

void point_in_volume(TreeID tree,
const Position* points,
const size_t num_points,
uint8_t* results,
const Direction* directions = nullptr,
std::vector<MeshID>* exclude_primitives = nullptr) override;

std::pair<double, MeshID> ray_fire(TreeID scene,
const Position& origin,
const Direction& direction,
const double dist_limit = INFTY,
HitOrientation orientation = HitOrientation::EXITING,
std::vector<MeshID>* const exclude_primitives = nullptr) override;
void ray_fire(TreeID tree,
const Position* origins,
const Direction* directions,
const size_t num_rays,
double* hitDistances,
MeshID* surfaceIDs,
const double dist_limit = INFTY,
HitOrientation orientation = HitOrientation::EXITING,
std::vector<MeshID>* const exclude_primitives = nullptr) override;

void ray_fire_prepared(const size_t num_rays,
const double dist_limit = INFTY,
HitOrientation orientation = HitOrientation::EXITING) override;

void point_in_volume_prepared(const size_t num_rays) override;

std::pair<double, MeshID> closest(TreeID scene,
const Position& origin) override {};
const Position& origin) override {
fatal_error("Closest queries are not currently supported with GPRT ray tracer");
return {INFTY, ID_NONE};
};

bool occluded(TreeID scene,
const Position& origin,
Expand All @@ -100,9 +121,31 @@ class GPRTRayTracer : public RayTracer {
fatal_error("Occlusion queries are not currently supported with GPRT ray tracer");
return false;
}


// Check to see if buffers large enough and resize if not
void check_rayhit_buffer_capacity(const size_t N) override;

// Method to expose device ray and hit buffers for external population
DeviceRayHitBuffers get_device_rayhit_buffers(const size_t N) override;

/**
* @brief Allocate device buffers and invoke a callback to populate them
*
* This method enables downstream applications to populate ray buffers using
* any compute API (GPRT, CUDA, HIP, etc.) without XDG needing to know the details.
*/
void populate_rays_external(size_t numRays,
const RayPopulationCallback& callback) override;

void transfer_hits_buffer_to_host(const size_t num_rays,
std::vector<dblHit>& hits) override;

GPRTContext context()
{
return context_;
}

private:
void check_ray_buffer_capacity(size_t N);

// GPRT objects
GPRTContext context_;
Expand Down Expand Up @@ -133,7 +176,31 @@ class GPRTRayTracer : public RayTracer {

// Internal GPRT Mappings
std::unordered_map<SurfaceTreeID, GPRTAccel> surface_volume_tree_to_accel_map; // Map from XDG::TreeID to GPRTAccel for volume TLAS
std::vector<GPRTAccel> blas_handles_; // Store BLAS handles so that they can be explicitly referenced in destructor
std::unordered_map<SurfaceTreeID, MeshID> surface_tree_to_volume_map_;
std::vector<SurfaceAccelerationStructure> tlas_handles_; // Host side storage of TLAS device addresses
GPRTBufferOf<SurfaceAccelerationStructure> tlas_handle_buffer_; // Device buffer for TLAS addresses
std::vector<int> meshid_to_sense_; // Host-side MeshID -> sense map
GPRTBufferOf<int> meshid_to_sense_buffer_ {nullptr}; // Device buffer for MeshID -> sense map
bool initialized_ {false}; // flag to indicate if init() has been called

void update_tlas_table_();
void update_meshid_to_sense_();

template <typename T>
void upload_device_buffer_(GPRTBufferOf<T>& buf, const std::vector<T>& host_data)
{
if (host_data.empty()) return;

if (!buf) {
buf = gprtDeviceBufferCreate<T>(context_, host_data.size(), host_data.data());
return;
}

gprtBufferResize<T>(context_, buf, host_data.size(), false);
gprtBufferMap(buf);
std::copy(host_data.begin(), host_data.end(), gprtBufferGetHostPointer(buf));
gprtBufferUnmap(buf);
}

// Global Tree IDs
GPRTAccel global_surface_accel_ {nullptr};
Expand All @@ -142,5 +209,4 @@ class GPRTRayTracer : public RayTracer {
};

} // namespace xdg

#endif // include guard
#endif // include guard
41 changes: 12 additions & 29 deletions include/xdg/gprt/shared_structs.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
#ifndef XDG_GPRT_SHARED_STRUCTS_H
#define XDG_GPRT_SHARED_STRUCTS_H

#include "gprt.h"
#include "../shared_enums.h"
#include "ray.h"

struct GPRTPrimitiveRef
{
int id; // ID of the primitive
int sense;
};

struct dblRay
{
double3 origin;
double3 direction;
double tMin; // Minimum distance for ray intersection
double tMax; // Maximum distance for ray intersection
int32_t* exclude_primitives; // Optional for excluding primitives
int32_t exclude_count; // Number of excluded primitives
xdg::HitOrientation hitOrientation;
int volume_tree; // TreeID of the volume being queried
SurfaceAccelerationStructure volume_accel; // The volume accel
};

struct dblHit
{
double distance;
int surf_id;
int primitive_id;
xdg::PointInVolume piv; // Point in volume check result (0 for outside, 1 for inside)
};

/* variables for double precision triangle mesh geometry */
struct DPTriangleGeomData {
Expand All @@ -35,20 +18,17 @@ struct DPTriangleGeomData {
uint3 *index; // index buffer
double3 *normals; // normals buffer
int surf_id;
int2 vols;
int forward_vol;
int reverse_vol;
dblRay *ray; // double precision rays
int* meshid_to_sense; // MeshID -> sense (+1 forward, -1 reverse)
xdg::dblRay *ray; // double precision rays
xdg::HitOrientation hitOrientation;
int forward_tree; // TreeID of the forward volume
int reverse_tree; // TreeID of the reverse volume
GPRTPrimitiveRef* primitive_refs;
int num_faces; // Number of faces in the geometry
};

struct dblRayGenData {
dblRay *ray;
dblHit *hit;
xdg::dblRay *ray;
xdg::dblHit *hit;
SurfaceAccelerationStructure* meshid_to_accel_address; // MeshID->TLAS address table to recover volume to trace against
};

/* A small structure of constants that can change every frame without rebuilding the
Expand All @@ -57,4 +37,7 @@ struct dblRayGenData {
struct dblRayFirePushConstants {
double tMax;
double tMin;
xdg::HitOrientation hitOrientation;
};

#endif
Loading
Loading