I’ve discovered a bug which may be related to NVCC. It seems that the compiler will incorrecly assume that two variables are equal after it may have been modified by rtTrace?
Cut out snippet:
float3 attenSaved = radiancePrd.attenuation;
//OPTIX_DEBUG_PRINT(0, "attenSaved: %.2f %.2f %.2f\n", attenSaved.x, attenSaved.y, attenSaved.z);
Ray newRay(hitPoint, ray.direction, RayType::RADIANCE_IN_PARTICIPATING_MEDIUM, 0.01);
rtTrace(sceneRootObject, newRay, radiancePrd);
// attenSaved is NOT saved at this point
If i use the debug print statement (a printf macro) then the correct result is achieved. This is kind of painful since I do use this pattern quite a bit. Otherwise, after the rtTrace, attenSaved is the same as radiancePrd.attenuation (not correct).
This is the entire closest hit program if it helps you. I introduced a hack which prevented this problem. I can experiment to get a minimal not-working example, but I would have to get back to that.
RT_PROGRAM void closestHitRadiance()
{
#if ENABLE_PARTICIPATING_MEDIA
const float sigma_t = sigma_a + sigma_s;
float3 worldShadingNormal = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shadingNormal));
float3 hitPoint = ray.origin + tHit*ray.direction;
bool isHitFromOutside = hitFromOutside(ray.direction, worldShadingNormal);
double tHitStack = tHit + 0.1 - 0.1; // Important, prevents compiler optimization on variable
OPTIX_DEBUG_PRINT(0, "Hit media: %s (attn: %.2f %.2f %.2f)\n", isHitFromOutside ? "outside" : "inside",
radiancePrd.attenuation.x, radiancePrd.attenuation.y, radiancePrd.attenuation.z);
if(isHitFromOutside)
{
float3 attenSaved = radiancePrd.attenuation + 0.1 - 0.1; // Important, prevents compiler optimization on variable
// Send ray through the medium
Ray newRay(hitPoint, ray.direction, RayType::RADIANCE_IN_PARTICIPATING_MEDIUM, 0.01);
rtTrace(sceneRootObject, newRay, radiancePrd);
float distance = radiancePrd.lastTHit;
float transmittance = exp(-distance*sigma_t);
VolumetricRadiancePRD volRadiancePrd;
volRadiancePrd.radiance = make_float3(0);
volRadiancePrd.numHits = 0;
volRadiancePrd.sigma_t = sigma_t;
volRadiancePrd.sigma_s = sigma_s;
// Get volumetric radiance
Ray ray(hitPoint, ray.direction, RayType::VOLUMETRIC_RADIANCE, 0.0000001, distance);
rtTrace(volumetricPhotonsRoot, ray, volRadiancePrd);
// Multiply existing volumetric transmittance with current transmittance, and add gathered volumetric radiance
// from this path
radiancePrd.volumetricRadiance *= transmittance;
radiancePrd.volumetricRadiance += attenSaved*volRadiancePrd.radiance;
OPTIX_DEBUG_PRINT(0, "Add radiance with attenSaved: %.2f %.2f %.2f\n", attenSaved.x, attenSaved.y, attenSaved.z);
radiancePrd.attenuation *= transmittance;
}
else
{
// We are escaping the boundary of the participating medium, so we'll compute the attenuation and volumetric radiance for the remaining path
// and deliver it to a parent stack frame.
Ray newRay = Ray(hitPoint, ray.direction, RayType::RADIANCE, 0.01);
rtTrace(sceneRootObject, newRay, radiancePrd);
}
radiancePrd.lastTHit = tHitStack;
#endif
}
Yes, a more complete reproducer would improve the likelihood I can reproduce it and fix it. You can either provide sample code (from either an SDK sample or your own code), or you can contact us on our mailing list (see the release notes for the address) and we can arrange for you to send us a trace of the optix API we can use to reproduce your problem here.