Callable program buffer: Assertion failed

I’m trying to create a buffer of callable programs. When I run my application, I get this error:

OptiX Error: Unknown error (Details: Function "_rtContextCompile" caught exception: Assertion failed: "insn->isMove() || insn->isLoad() || insn->isAdd()", [5639172])

I’m not sure what this means or how to debug it. I’m assuming because this happens during rtContextCompile that the problem must be in my shader, which looks like this:

#define RT_USE_TEMPLATED_RTCALLABLEPROGRAM //not sure I need this
#include <optix_world.h>

/* Context variables */
rtBuffer<rtCallableProgramId<float(optix::Ray*)> > functions;
...
RT_PROGRAM void miss()
{
	...
	float3 color = light.color;
	if (light.function > -1)
		color *= functions[light.function]( &ray );
	...
}

Everything works fine if I remove the references to the callable programs. Any ideas how to fix the error?

OptiX 3.6.0, CUDA 6.0, Windows 7, VS2010, using SM_20, Quadro K4000

Could you provide a more information on how you setup the functions buffer values and how the functions’ code looks like?
The variable “ray” is the rtCurrentRay?

A complete minimal reproducer in failing state would be needed to investigate this.
(The forum allows attachments to your submitted posts with the small paper clip icon in the top right corner you’ll see when hovering the mouse over the post.)

We have posted a new OptiX version to the FTP. It’s 3.6.0 final. It has one bug fix since the 3.6.0 beta and some documentation enhancements. The OptiX Prime Trbvh chunking performance improvements that the release notes promise should come in OptiX 3.6.1, around the end of June.

For you and everyone experiencing bugs in 3.6.0 beta, please try 3.6.0 final and let us know whether or not it is fixed.

I have tried to strip down the program as much as possible. The error persists even when light.function == -1 and goes away only when the line “color *= functionslight.function;” is commented out from the shader. (Am I right to assume that the compiler then optimizes out the declaration of “fuctions” in the shader?)

The setup for the stripped-down version now looks like this:

RTbuffer   function_buffer;
//int*       function_buffer_data;
RTvariable var;
int function_count = 0;

/* Create Buffer */
RT_CHECK_ERROR( rtBufferCreate( context, RT_BUFFER_INPUT, &function_buffer ) );
RT_CHECK_ERROR( rtBufferSetFormat( function_buffer, RT_FORMAT_PROGRAM_ID ) );
RT_CHECK_ERROR( rtBufferSetSize1D( function_buffer, function_count ) );
//RT_CHECK_ERROR( rtBufferMap( function_buffer, (void**)&function_buffer_data ) );
...
/* Populate buffer (commented out) */
//RT_CHECK_ERROR( rtProgramCreateFromPTXFile( context, path_to_ptx, "myfunc", &program ) );
//RT_CHECK_ERROR( rtProgramGetId( program, &program_id ) );
//light.function = fi;
//function_buffer_data[fi++] = program_id;
...
//RT_CHECK_ERROR( rtBufferUnmap( function_buffer ) );
RT_CHECK_ERROR( rtContextDeclareVariable( context, "functions", &var ) );
RT_CHECK_ERROR( rtVariableSetObject( var, function_buffer ) );

At this point, OptiX shouldn’t even be aware of the existance of any callable programs. It seems to me that the only place left that could cause the problem is in the shader.

Yes.

This is with the new 3.6.0. I never downloaded the beta.

The error I reported above seems to only happens when I pass a pointer to the callable program such as:

rtBuffer<rtCallableProgramId<float(optix::Ray*)> > functions;

or:

rtBuffer<rtCallableProgramId<float(float3*)> > functions;

If I pass the argument directly (which I understand is not recommended), like this:

rtBuffer<rtCallableProgramId<float(optix::Ray)> > functions;

or:

rtBuffer<rtCallableProgramId<float(float3)> > functions;

then I get a different error:

OptiX Error: Invalid value (Details: Function "_rtContextCompile" caught exception: Function call %r38 rejected due to the semantic type (2) of caller _Z4missv_0, [5640347])

The callable program is called from a miss program, but it is bindless, so am I correct that it should not care about the caller’s semantic type?

There are two separate problems here. First, you are correct that the first problem is passing rtCurrentRay by ptr. A current limitation of optix is that you can and should not take the address of a semantic variable. So pass the ray by value – there will not be a perf cost.

The second issue is not as clear – optix is claiming that you are calling a function in an illegal manner. This usually happens when you call rtTrace from a miss program or something similar. Could you paste the entirety of you miss program function body and your callable program function body (if it is different from that posted above)?

Thanks

I thought I would try to make this as simple as possible. I still get the “Function call rejected” error.

Miss program:

#define RT_USE_TEMPLATED_RTCALLABLEPROGRAM
#include <optix_world.h>
#include <curand_kernel.h>

struct PerRayData_radiance
{
	float3 result;
	float weight;
	float distance;
	int depth;
	int ambient_depth;
	curandState_t* state;
};

/* Context variables */
rtBuffer<rtCallableProgramId<float()> > functions;
rtDeclareVariable(PerRayData_radiance, prd_radiance, rtPayload, );

RT_PROGRAM void miss()
{
	prd_radiance.result = make_float3( functions[0]() );
}

Callable program:

#include <optix_world.h>

RT_CALLABLE_PROGRAM float myfunc()
{
	return 0.0f;
}

I dont see anything wrong here. I will try to reproduce on my end.

I tried unsuccessfully to reproduce the error – here is what my code looks like:

rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
rtBuffer<rtCallableProgramId<float3(optix::Ray)> > shade_ray;

RT_PROGRAM void miss()
{
prd_radiance.result = shade_ray0;
}

RT_CALLABLE_PROGRAM float3 shade_from_ray( const optix::Ray ray )
{
return optix::normalize( ray.direction ) * 0.5f + 0.5f;
}

And this all worked fine. Are you sure that the buffer is populated correctly on the host side? If so, could you please send an optix api capture to optix-help@nvidia.com so I can try with your exact code?

To create an api trace, simply run your app after setting the OPTIX_API_CAPTURE environment variable to a directory path where you want to create the api trace.

For instance. Setting OPTIX_API_CAPTURE=./my_trace will create the my_trace directory, with all necessary data for me to replay your optix app. Zip this directory, rename the .zip extension to something that will pass our mail filters (eg, .piz) and email it in. I will let you know what I find.

Thanks

This turns out to be a bug with the 32-bit release of OptiX 3.6.0. When I recompiled as a 64-bit program using the latest version of CMake, no errors were displayed.

However, now I have a new issue. The callable program doesn’t return the value that it should. Here’s my callable program:

#include <optix_world.h>
RT_CALLABLE_PROGRAM float myfunc( const float3 direction )
{
	return 1.0f;
}

And here’s the call to it:

#define RT_USE_TEMPLATED_RTCALLABLEPROGRAM
#include <optix_world.h>
rtBuffer<rtCallableProgramId<float(float3)> > functions;
RT_PROGRAM void miss()
{
	...
	float3 color = light.color;
	if (light.function > -1) {
		float f = functions[light.function]( normalize( ray.direction ) );
		if (f == f) // Check for NaN
			color *= f;
		if (prd_radiance.depth == 0) // Only output for primary rays
			rtPrintf( "Function returned %f\n", f );
	}
	...
}

This looks like it should always print “Function returned 1.0”. However, instead, my output is almost always either:

Function returned -170141183460469230000000000000000000000.000000

or

Function returned -1.#QNAN0

And it changes between the two during successive runs of the same executable, which shouldn’t happen. What could be causing this?

I would change the following one by one:

  • Make sure light.function is a valid index. You’re not checking for the upper bounds. Something like
    if (0 <= light.function && light.function < (int) functions.size())
  • There is a mismatch in the parameter declarations of your ID buffer and the myfunc implementation. I don’t know if that const makes any difference, your code just doesn’t match.
  • ray.direction should be normalized, no need for the normalize() call.
  • There was a problem with calling rtCurrentRay with constant reference. For additional paranoia you could try
    const float3 dir = ray.direction;
    const float f = functionslight.function;
  • A more obvious check for NaN is isnan(f).

I went through Detlef’s suggestions, but didn’t see any improvements.

rtPrintf("%d", light.function); yields 0, and rtPrintf("%d", functions[light.function]); yields 1, which is the callable program’s ID.

Changing rtBuffer<rtCallableProgramId<float(float3)> > functions; to rtBuffer<rtCallableProgramId<float(const float3)> > functions; didn’t have any effect. Nor did changing RT_CALLABLE_PROGRAM float myfunc( const float3 direction ) to RT_CALLABLE_PROGRAM float myfunc( float3 direction ).

I also added const float3 dir and used rtPrintf to look at its value, which didn’t yield any surprises, not the the value is currently used anyway.

Turns out I miss-diagnosed the problem because I wasn’t calling the fuction I thought I was. Actually, the function does return the value it’s told to, but it does not receive the correct value.

My miss program contains:

rtBuffer<rtCallableProgramId<float(float3)> > functions;
...
float3 H = ray.direction;
rtPrintf( "Sending (%f, %f, %f)\n", H.x, H.y, H.z);
float f = functions[0]( H );

And here’s the callable program:

RT_CALLABLE_PROGRAM float myfunc( float3 direction )
{
	rtPrintf("Recieved (%f, %f, %f)\n", direction.x, direction.y, direction.z);
	return 1.0f;
}

My output looks like this:

Sending (-0.939043, -0.340344, 0.048621)
Sending (-0.966871, -0.250307, 0.050061)
Sending (-0.986859, -0.153289, 0.051096)

...
Recieved (0.000000, -246183425639011170000000000000000000000.000000, 0.000000)
Recieved (0.000000, -244864602519352930000000000000000000000.000000, 0.000000)
Recieved (0.000000, -246199043094405980000000000000000000000.000000, 0.000000)
...

Any idea why myfunc isn’t seeing the argument it’s given?

It seems I’m getting exact same issues. Cross linking the topic, my original question though was about different matter.

I just tested this again with OptiX 3.6.2 and the latest graphics drivers. The issue is still not resolved.

Now using OptiX 3.6.2, CUDA 6.0, Windows 7 64-bit
Quadro K4000 with driver 340.52
2x Tesla K40 with driver 333.11 (remote)

A possible solution is to disable RT_EXCEPTION_PROGRAM_ID_INVALID.