optixProgramGroupCreate() seems always create same raygen program

Hello everyone. I met a problem when trying to build multiple pipelines to control the render process.

So I wrote two __raygen __ kernels, and I tried to bind each of the kernel into a different pipeline, here is the code:

raygenPGs.resize(RENDERER_TYPE_COUNT);

  char log[2048];

  size_t sizeof_log = sizeof(log);

  OptixProgramGroupOptions pgOptions = {};

  OptixProgramGroupDesc pgDesc = {};

  pgDesc.kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;

  pgDesc.raygen.module = module["rayLaunch"];

  // Fast renderer;

  pgDesc.raygen.entryFunctionName = "__raygen__fastRenderer";

  OPTIX_CHECK(optixProgramGroupCreate(optixContext,

                                      &pgDesc,

                                      1,

                                      &pgOptions,

                                      log, &sizeof_log,

                                      &raygenPGs[FAST]));

  if (sizeof_log > 1)

    PRINT(log);

  // Classic renderer;

  pgDesc.raygen.entryFunctionName = "__raygen__classicRenderer";

  OPTIX_CHECK(optixProgramGroupCreate(optixContext,

                                      &pgDesc,

                                      1,

                                      &pgOptions,

                                      log, &sizeof_log,

                                      &raygenPGs[CLASSIC]));

  if (sizeof_log > 1)

    PRINT(log);

And finally create two piplelines like this:

for (int i = 0; i < RENDERER_TYPE_COUNT; i++)

  {

    std::vector<OptixProgramGroup> programGroups;

    programGroups.push_back(raygenPGs[i]);

    for (auto pg : missPGs)

      programGroups.push_back(pg);

    for (auto pg : hitgroupPGs)

      programGroups.push_back(pg);

    for (auto pg : callablePGs)

      programGroups.push_back(pg);

    char log[2048];

    size_t sizeof_log = sizeof(log);

    PING;

    PRINT(programGroups.size());

    OPTIX_CHECK(optixPipelineCreate(optixContext,

                                    &pipelineCompileOptions,

                                    &pipelineLinkOptions,

                                    programGroups.data(),

                                    (int)programGroups.size(),

                                    log, &sizeof_log,

                                    &pipelines[i]));

    if (sizeof_log > 1)

      PRINT(log);

However, wired things happened that, both pipelines behaved exactly the same. More specifically, both optixLaunch(pipelines[FAST],... and optixLaunch(pipelines[CLASSIC],... triggered
__raygen__fastRenderer kernel, but __raygen__classicRenderer was never triggered.

And if I exchange the program position inside of raygenPGs, this time only __raygen__classicRenderer is triggered.

I checked many times and can’t solve the problem. Now I switch to continuation callables to do similar things however, may impact the performance a little. I would be glad if anyone can find where the problem is, thanks.

Code excerpts without the shader binding table setup don’t show the whole picture here.
With that setup you would need to change the shader binding table (SBT) ray generation record between each launch of a different pipeline as well.
From the outcome of your launches it sounds as if you’re not doing that.

Mind that you can have multiple ray generation programs in one pipeline and switch between them this way or by using different SBTs. Latter would be recommended if the rest of the programs is different as well.

Please see this threads for more information:
https://forums.developer.nvidia.com/t/multiple-raygen-functions-within-same-pipeline-in-optix-7/122305
https://forums.developer.nvidia.com/t/how-to-handle-multiple-ray-generators/83446

Now I switch to continuation callables to do similar things however, may impact the performance a little.

For performance reasons I would recommend avoiding continuation callable programs if you can. It’s faster to use optixTrace() inline than inside continuation callable programs.
If at all, I’m normally using direct callables to calculate state dynamically and use the results to control optixTrace() calls inside the main program domains.

Wow, thanks a lot for the reply, you saved my day!

I totally forgot about the SBTs stuff. After add code to change the SBT bind pointer, it totally works as expect. Infect I even didn’t need multiple pipelines, just pack or raygen program into one pipeline and change the entry pointer of SBTs would do it.

I used to suppose that when multiple raygen programs exist, Optix will trigger all raygen programs at the same time. Well I was wrong about that, only one entry points a time I guess~

You’re welcome.
Please read the linked posts which describe other options, benefits, and caveats of the different ways to architect renderers with multiple ray generation programs.