OptiX 6.5 modulo operator producing incorrect result

Update
Here’s a simple reproducible example of the modulo (%) operator bug in OptiX. You can add this line to any ray generation program, and it will throw an exception even though mathematically the if statement is always false:

if ((int)(launch_index.x / 12.f) % 30 < 0) rtThrow(RT_EXCEPTION_USER);

My environment: Windows 10, OptiX 6.6.0, display driver 440.70, CUDA driver 10.2.0, Quadro RTX 8000

Original post
In my callable programs, the modulo (%) function is no longer producing the correct results. Everything worked with display driver 431.36, but stopped working in display driver 436.15 and later. Errors only seem to occur when taking the modulo relative to a fairly large number, and the results are consistent from one run to the next.

Here is my callable program with some comments where it is not working (edited down from here). When executed correctly, it produces a test pattern to be shown on the sky in my scene.

#include <optix_world.h>
using namespace optix;

RT_CALLABLE_PROGRAM float3 gencumsky(const float3 direction, const float3 ignore)
{
	float alt = asinf(direction.z) * 180 * M_1_PIf;
	if (alt < 0.0f) return make_float3(0.0f);
	float az = atan2f(direction.x, direction.y) * 180 * M_1_PIf;
	if (az < 0.0f) az += 360.0f;
	
	int x = 0;
	if (alt < 12.0f)
		x = (int)(0.5f + az / 12.0f) % 30; // <==== This does not produce the correct result
		//x = (int)(0.5f + az / 12.0f); // <==== It does work without the modulo, except that when az=359degrees, I want x to be 0, not 30
	else if (alt < 24.0f)
		x = (int)(0.5f + az / 12.0f) % 30 + 30; // <==== This also does not produce the correct result
	else if (alt < 36.0f)
		x = (int)(0.5f + az / 15.0f) % 24 + 60; // <==== Everything from here on works correctly
	else if (alt < 48.0f)
		x = (int)(0.5f + az / 15.0f) % 24 + 84;
	else if (alt < 60.0f)
		x = (int)(0.5f + az / 20.0f) % 18 + 108;
	else if (alt < 72.0f)
		x = (int)(0.5f + az / 30.0f) % 12 + 126;
	else if (alt < 84.0f)
		x = (int)(0.5f + az / 60.0f) % 6 + 138;
	else
		x = 144;

	return make_float3(x);
}

It seems like a basic math error. I’m actually not sure if this is an OptiX issue or a general CUDA issue.

Hey nljones, you’re totally right, there’s a bug in modulo operator compilation somewhere. I can reproduce it. I’ve filed it for a fix ASAP. Thank you for the report.

Here’s a temporary workaround:

float im;
if (int(modff(idx.x / 12.f / 30.f, &im) * 30.f) < 0) rtThrow(RT_EXCEPTION_USER);


David.

Just a status update, the fix for this is on the way in the next driver update. Thanks again for letting us know, we’re surprised that none of our regression tests caught this one.


David.