Which issues can lead to nop hit?

I have a closest hit shader, which when it is called always returns a (0, 0, 0) when calling optixHitObjectGetWorldRayDirection(). I have a different closest hit shader which works fine (both in their own file).
I have now reduced the erroneous shader to just calling the getter and printing out the value, but the behaviour doesn’t change. Compiling and module creation don’t show any issues and I am a bit at a loss as to what may cause this. Are there any common issues which can lead to the nop hit result?

In my scene I can see that the shader is called correctly btw (or rather: it is called in the correct locations), as every object using the shader is rendered black (due to the incorrect lighting calculations stemming from the incorrect ray dir).

Hi @lobner,

Normally a nop hit object will not invoke your closest-hit shader in the first place, and so you will only get a result of (0,0,0) from optixHitObjectGetWorldRayDirection() if you call it from raygen or some other place that is executed explicitly, and not as the result of a call to optixInvoke().

I can’t say for sure what the problem might be without a minimal reproducer or more info. This sounds a bit like the type of thing that happen when the SBT indexing is incorrect. But do you mean that you switch the code of one closest-hit shader for a different one without changing anything else, and it starts to work, with optixHitObjectGetWorldRayDirection() returning correct non-zero values? That might rule out certain SBT issues, perhaps as well as potential issues with any instance transforms you might be using.

Some things you can double-check quickly are whether printf is working correctly, and whether you’re using any OptiX structs that haven’t been zero-initialized. Aside from that, you could try disabling the code for each closest-hit program and adding one line at a time until the behavior of optixHitObjectGetWorldRayDirection() changes. Something must be different between the two shaders, so if you started with this ray dir call working correctly at the top in both versions, you could introduce the subsequent code until it fails, and then you’ll have some data on the potential culprit.

Is it possible to use your errant closest-hit shader to reproduce the problem with an OptiX SDK sample such as optixTrangle?


David.

I have several objects in the scene and two different closest hit shaders in the SBT. If an object instance with index 0 (of my old, working shader) is hit, it works correctly. If an object instance with index 1 (of my new faulty shader) is hit, then the output is (0, 0, 0). If I put only my faulty shader and only one object into the scene, such that it has index 0, then it doesn’t work either.

printf works fine, that is what I use to check the output of optixHitObjectGetWorldRayDirection().

I will try to reproduce it with the example or otherwise minimally.

Yeah, I can reproduce it with the optixTriangle example. For this, I have loaded the .optixir shader as I compiled it for my own project.

The code of that shader right now (excluding comments) is:

#pragma once

#include <optix.h>

extern "C" __global__ void __closesthit__main()
{
	float3 rayDir = optixHitObjectGetWorldRayDirection();
	printf("rayDir = (%f, %f, %f)\n", rayDir.x, rayDir.y, rayDir.z);
}

I’ll upload the resulting optixir file

ggx_chit.zip (4.4 KB)

I have also tried to copy my shader code into the optixTriangle cuda file and the result is the same, the output is “rayDir = (0, 0, 0)”.

Which OS, driver version, and OptiX version are you testing against?

Does the repro with optixTriangle require borrowing the .optixir file from your other project? If you paste the code above directly into __closesthit__ch() inside of optixTriangle.cu - does everything start functioning correctly?


David.

OS is Win 11, Driver version is 537.13 (on an RTX A1000 Laptop GPU) or 537.42 (on an RTX 3080ti). OptiX version is 8.0 on both machines, though testing the optixTriangle example is done only on the RTX 3080ti system.
Yes, the behaviour is the same if using my code in __closesthit_ch() (no matter if I comment out the previous code or not and no matter if my function is part of the .cu file or not).

I have not tried to compile my code with the optixTriangle example, since I could reproduce with the example’s .cu file.

Thanks I’ll try to repro with your file soon. It might be worth seeing if you can repro using the optixTriangle example code, to rule out compilation or environment issues with your own example.

So there are a couple of other things you could try in your own code. One would be to print the SBT data pointer from both of your closest hit programs, and verify that they are correct and match what they should be - I’m not sure whether a bad SBT index has been ruled out. Another would be to turn on OptiX validation mode and check that it doesn’t complain about anything. A third would be to reproduce the issue using a newer 545 driver, and see whether the behavior is the same or changes.


David.

I updated to 546.01 on both systems, it did not change the behaviour (neither in my project nor the optixTriangle example). I have also compiled the above posted minimal code via the optixTriangle example, the result is also the same.

The validation mode is turned already, but, as I said, it doesn’t complain about anything so far as I can see.

I am not sure how I can verify the data pointer from the closest hit shader is correct. I can print them out, but what would I check them against?

I am not sure how I can verify the data pointer from the closest hit shader is correct. I can print them out, but what would I check them against?

Oh I just meant check the data pointer against the SBT buffer device pointer that you allocated. For example, use the data pointer in the hit program, along with your SBT record size, to figure out exactly which SBT table entry it’s referring to, make sure it’s the same as the SBT entry you expect to be accessed.


David.

Wait! Scratch that, don’t bother checking. I finally just tried it and realized what’s going on.

I completely missed some details from your description, sorry! optixHitObjectGetWorldRayDirection() queries an outgoing hit object, which only exists in closest-hit after you call optixMakeHitObject(). When you want to just query the incoming hit object’s ray direction, you should be using optixGetWorldRayDirection() instead.

Here’s a little snippet from the Programming Guide that explains this in more detail:

“With the introduction of optixTraverse and optixInvoke, an application must be able to interact with the hit object that is produced by traversal and consumed by shading. For the purposes of this chapter, the hit object available during traversal and shading will be referred to as the incoming hit object while the one available outside of traversal and shading will be referred to as the outgoing hit object. Both the incoming and outgoing hit objects can be live at the same time, but there is only ever one of each at a time. Accessor functions for the outgoing hit object are distinguished from the incoming hit object with the inclusion of the string “HitObject” in the device side API functions. For example, optixGetRayTmin accesses the incoming hit object, while optixHitObjectGetRayTmin accesses the outgoing hit object.”

https://raytracing-docs.nvidia.com/optix8/guide/index.html#shader_execution_reordering#hit-objects


David.

Ah, darn! You are correct. I’m not quite sure why it worked in my first shader (or maybe it didn’t really work but the lighting just wasn’t obviously broken). But at least that solves the problem and my confusion, thank you very much.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.