Multiple raygen functions within same pipeline in Optix 7?

Now in Optix 7, only a single “raygen” program can be specified per pipeline.

That’s actually not the case.
https://raytracing-docs.nvidia.com/optix7/guide/index.html#program_pipeline_creation#program-pipeline-creation

There can be as many ray generation programs inside an OptixPipeline as you need, but there can be only one inside the Shader Binding Table (SBT) CUdeviceptr raygenRecord.
https://raytracing-docs.nvidia.com/optix7/guide/index.html#shader_binding_table#sbt-layout

There are some things to consider when putting many raygen programs into one OptixPipeline.
https://forums.developer.nvidia.com/t/how-to-handle-multiple-ray-generators/83446

Above link effectively answers your question already. Just to formulate things again with pros and cons:

1.) Recommended because that works fully asynchronously:
Set up as many SBTs as you have ray generation entry points. Set the CUdeviceptr raygenRecord to the entry point you want. All other SBT records remains identical in all SBTs. Means since those are only pointers, there is no duplicated data on the device and all optixLaunch() use the same pipeline, same stream, but different SBTs.

2.) Synchronous, not fully recommended. (If you need to sync between launches anyway to grab the results etc. it’s not that bad.)
Instead of using different SBTs, use only one and exchange the CUdeviceptr raygenRecord between launches.
That would be slower because since optixLaunch() calls are asynchronous, you would need to synchronize with the CUDA stream before you can manipulate the SBT.
(Similar for any data in the constant launch parameter buffer, BTW.)

3.) If what changes in the ray generation program is only the projection, implement the projection as direct callable programs and simply select the necessary projection program with an index in the optixLaunch() constant parameter block. That would only require a single raygeneration program
This can even be updated asynchronously with a cuMemcpyHtoDAsync() if the indices are sourced from different host locations.
Example were I use that method:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/rtigo3/shaders/raygeneration.cu#L201
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/rtigo3/src/Device.cpp#L658