In a main function, I want to do a second ray tracing, but the code logic is different from the first ray tracing.My idea is to recreate a module to import a different .cu file and create a new acceleration structure.
I wonder if there is a more convenient way?
Let’s address this from the required OptiX API functions from bottom to top.
If you want to call OptiX with two different ray tracing algorithms from your main host function, then you need to call optixLaunch
twice.
https://raytracing-docs.nvidia.com/optix8/guide/index.html#ray_generation_launches#ray-generation-launches
The individual function arguments to the optixLaunch call define what of your OptiX device code runs on what data structures.
The pipeline contains all device programs which are used inside the Shader Binding Table (SBT).
The programs inside the pipeline are defined by an array of OptixProgramGroupDesc
which define the OptixModule
, program domain type, and program name.
The OptixModule are created from input PTX or OptiX-IR code containing your OptiX device programs.
You can have as many OptixModules as you like, or you can put all device programs in one module, but since that is bigger, the optixModuleCreate
can get slower.
I’m usually splitting modules by domain type:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/MDL_renderer/src/Device.cpp#L344
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/MDL_renderer/src/Device.cpp#L713
The SBT defines which of the pipeline programs are called when during the optixLaunch
.
While you can have multiple ray generation programs in one module and in one pipeline, you can only use one of them inside an optixLaunch
because there is only one ray generation program inside an SBT! That defines the entry point of the launch.
The pipelineParams
and pipelineParamsSize
define which data get copied to your constant launch parameter structure which name you gave to OptiX in OptixPipelineCompileOptions::pipelineLaunchParamsVariableName
Which acceleration structures are used, is defined by the OptixTraversableHandle
argument inside the optixTrace call.
The OptixTraversableHandle(s) to use is usually stored inside the OptiX launch parameter structure.
These handles are generated usually by building instance or geometry acceleration structures with optixAccelBuild
or a following optixAccelCompact
.
Let’s look at the two extreme cases:
1.) If you want to implement two completely different ray tracing algorithms running on different geometry, you need two pipelines, two SBTs, two launch parameter structures, and two top-level OptixTraversableHandles.
You could share some modules if you wanted, but basically everything is different.
2.) If you only want to implement two different cameras (e.g. perspective, orthographic) which otherwise work on the same scene data and ray tracing algorithm (light transport), then you only need two different ray generation programs and either two different SBTs or you need to exchange the ray generation program inside the SBT between optixLaunch calls.
The better alternative would be to implement both camera models inside a single ray generation program and switch between them with a value inside the launch parameters.
Related thread: https://forums.developer.nvidia.com/t/multiple-raygen-functions-within-same-pipeline-in-optix-7/122305/2
Now depending on what you really need, there are multiple different implementation options in between these two which can reuse some amount of data.
I get it.Thank you very much for your advice