Thanks for replying.
In my case, the getPRD()
is just copied from the SDK files:
static __forceinline__ __device__ DR::SamplePRD *getPRD()
{
const unsigned int u0 = optixGetPayload_0();
const unsigned int u1 = optixGetPayload_1();
return reinterpret_cast<DR::SamplePRD *>(unpackPointer(u0, u1));
}
and the full function definitioin is just a simple
extern "C" __global__ void __continuation_callable__solid_color_material(DR::SamplePRD *prd, int instance_id)
the hit program is:
extern "C" __global__ void __closesthit__triangle_mesh()
{
printf("%d %d\n", optixGetPayload_0(), optixGetPayload_1());
DR::SamplePRD *prd = getPRD();
if (prd->log)
{
printf("hit program launched\n");
}
// retrive trace data
DR::HitData *sbt_record = reinterpret_cast<DR::HitData *>(optixGetSbtDataPointer());
DR::TriangleMeshData *sbt_data =
reinterpret_cast<DR::TriangleMeshData *>(sbt_record->mesh_payload);
const int prim_idx = optixGetPrimitiveIndex();
const float3 ray_dir = optixGetWorldRayDirection();
const float3 hit_pos = optixGetWorldRayOrigin() + optixGetRayTmax() * ray_dir;
const int vert_idx_offset = prim_idx * 3;
const int mat_id = sbt_data->mat_id;
const int mat_instance_id = sbt_data->mat_instance_id;
const DR::Vertex v0 = sbt_data->vertexes[vert_idx_offset + 0];
const DR::Vertex v1 = sbt_data->vertexes[vert_idx_offset + 1];
const DR::Vertex v2 = sbt_data->vertexes[vert_idx_offset + 2];
// REVIEW: how to pass hit infomation into material shader ?
if (prd->log)
{
printf("hit data loaded\n");
printf("mat_id=%d, mat_instance_id=%d\n", mat_id, mat_instance_id);
printf("current prd: %u\n", prd);
}
prd->tracker_tail->hit = true;
prd->tracker_tail->hit_pos = hit_pos;
optixContinuationCall<void, DR::SamplePRD *, int>(mat_id, prd, mat_instance_id);
if (prd->log)
{
printf("hit program ended\n");
}
}
the continuation callable program is:
#include "SolidColorMaterial.cuh"
extern "C" __global__ void __continuation_callable__solid_color_material(DR::SamplePRD *prd,
int instance_id)
{
printf("mat program get prd: %u\n", prd);
if (prd->log) // this is when things go wrong
{
printf("material program launched\n");
}
DR::CallableData *sbt_record = reinterpret_cast<DR::CallableData *>(optixGetSbtDataPointer());
DR::SolidColorMaterialData *data =
reinterpret_cast<DR::SolidColorMaterialData *>(sbt_record->callable_payload);
data = data + instance_id;
}
the original PRD is allocated inside the sample loop of raygen program and passed to hit program like this:
for (size_t s = 0; s < params.samples_per_launch; s++)
{
// generate ray
float2 subpixel_jitter = make_float2(curand_uniform(&rng), curand_uniform(&rng)) - 0.5;
const float2 d = make_float2((static_cast<float>(launch_index.x) + subpixel_jitter.x) /
static_cast<float>(params.width),
(static_cast<float>(launch_index.y) + subpixel_jitter.y) /
static_cast<float>(params.height));
float3 ray_orig, ray_dir;
ray_dir = normalize(d.x * camera_data->U + d.y * camera_data->V + camera_data->W);
ray_orig = camera_data->orig;
/* ---------------------------------- DEBUG --------------------------------- */
ray_dir = make_float3(-1, 0, 0);
/* ---------------------------------- DEBUG --------------------------------- */
// init prd
DR::SamplePRD prd;
prd.log = log;
prd.handle = params.handle;
prd.ray_occlusion_test = false;
prd.curr_depth = 0;
prd.max_depth = params.max_depth;
prd.sample_idx = s;
prd.rdn_seed = &rng;
// init tracker
DR::TraceTrackerNode *tracker = initTrackerNode(params.num_fbos);
prd.tracker_head = tracker;
prd.tracker_tail = tracker;
tracker->ray_orig = ray_orig;
tracker->ray_dir = ray_dir;
// pack prd pointer
unsigned int u0, u1;
packPointer(&prd, u0, u1);
// trace
optixTrace(params.handle, // handle
ray_orig, ray_dir,
1e-5f, // T min
1e10f, // T max
0.0f, // T curr
OptixVisibilityMask(1),
OPTIX_RAY_FLAG_TERMINATE_ON_FIRST_HIT, // ray flag
0u, // SBT offset
1u, // SBT stride
0u, // miss SBT index
u0, u1);
}
I may try to refactor those code to use DC for better performance, but at this time I just want something runable 🤣