Isn't the bounce limited to 2 in optixPathTracing example?

Continuing the discussion from Ray tracing by Optix help and guide:

You have already provided a detailed explanation of the optixPathTracing example.

  • Just as an additional question, isn’t the depth value (aka, bounce) limited to 2 in this example?
// optixPathTracer.cpp
 pipeline_link_options.maxTraceDepth = 2; 
...
uint32_t max_trace_depth = 2; 

// optixPathTracer.cu
if( prd.done  || depth >= 3 ) // TODO RR, variable for depth
                break;

If the bounces are limited to 2, in

 OPTIX_CHECK( optixLaunch(
                state.pipeline,
                state.stream,
                reinterpret_cast<CUdeviceptr>( state.d_params ),
                sizeof( Params ),
                &state.sbt,
                state.params.width,   // launch width
                state.params.height,  // launch height
                1      //depth               
                ) );

Why is the depth value provided 1? Is it because of minimum 1 boune and Maximum 2?

  • In this example, I did not find any direct/continuation callable use. So why this depth has been defined?
    uint32_t max_cc_depth = 0;
    uint32_t max_dc_depth = 0;

The optixUtilComputeStackSizes() function does not have any effect on implementation.

Hey @_Bi2022,

The depth parameter to optixLauch is not in any way related to trace depth. The launch depth is a declaration of the 3D launch size. By this I mean when you launch a kernel, you get width * height * depth total threads. By setting the depth parameter to 1, this means we’re doing a 2D launch, and that we will have width * height total threads, which makes more sense for image rendering than a 3D launch. You might set the launch depth greater than 1 if you were doing some volume rendering, or if you were rendering multiple layers or something.

OptiX’ maxTraceDepth is referring to the maximum number of recursive trace calls you will ever make, and this matters because every recursive trace call needs a stack frame, so this uses a lot of precious register memory. Because of that, it’s common with GPU path tracing to simulate recursive calls using iteration instead of recursion. This is what the optixPathTracer sample is doing - it does not call optixTrace() from the closest hit program recursively. Instead, it simulates a recursive path in the raygen program, only extending the path with another optixTrace call after the first call to optixTrace has already returned. The maximum trace depth is set to 2 because there is still a recursive call to optixTrace being used for shadow rays (aka ‘next event estimation’). Because the “radiance” rays are flattened via iteration, the shadow rays only increase the stack by 1 frame at the maximum, thus optixPathTracer needs 2 stack frames. I’m explaining this in order to point out that the depth value in this code has a different meaning than pipeline_link_options.maxTraceDepth:

if( prd.done  || depth >= 3 ) // TODO RR, variable for depth

The depth variable here is referring to the maximum iteration count, and does not affect the stack size. This local depth variable can have any value you like, it will only affect the render time and accuracy of bounce lighting calculations.

So, there are 3 different kinds of “depth” in the code snippets you referred to: launch depth, maximum recursive trace depth, and maximum path length. Only the maximum recursive trace depth (pipeline_link_options.maxTraceDepth) is involved in the stack size calculations.


David.

1 Like

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