2
$\begingroup$

I am writing a renderer that uses a deferred clustered shading technique. On the CPU I group lights, decals, and environment maps into 3 seperate clustered structures (functionally, arrays of unsigned integers), and on the GPU at various stages in the shading pipeline I read from the clustered structure to decide which lights/decals/cubemaps to shade a pixel with. The shading stages are fullscreen passes.

To move the cluster data from the CPU ot the GPU, I use a memcpy into a persistent mapped buffer (triple buffered, and using GL_MAP_COHERENT_BIT). The copy is to a Uniform Buffer Object.

I see three possible ways I could order the CPU/GPU commands.

Option A:

DecalClusterCPU();//Do the CPU stuff for Frame N
memcpy(...);//Copy the Data for Frame N
LightClusterCPU();
memcpy(...);
CubemapClusterCPU();
memcpy(...);
RenderGeometryGPU();
DecalPassGPU();//a compute shader, uses Decal Cluster data
ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data
DenoiserPassGPU();//a compute shader
FinalShadingPassGPU();//a compute shader, uses Light Cluster Data
SwapBuffers();

Option B:

DecalClusterCPU();
memcpy(...);

RenderGeometryGPU();
DecalPassGPU();//a compute shader, uses Decal Cluster data

CubemapClusterCPU();
memcpy(...);

ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data
DenoiserPassGPU();//a compute shader

LightClusterCPU();
memcpy(...);
FinalShadingPassGPU();//a compute shader, uses Light Cluster Data
SwapBuffers();

Option C:

memcpy(...);//Copy the data for frame N

memcpy(...);

memcpy(...);
RenderGeometryGPU();
DecalPassGPU();//a compute shader, uses Decal Cluster data
ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data
DenoiserPassGPU();//a compute shader
FinalShadingPassGPU();//a compute shader, uses Light Cluster Data
SwapBuffers();
CubemapClusterCPU();//do the CPU stuff for frame N + 1
LightClusterCPU();
DecalClusterCPU();

My essence of my question is: Is it a bad/good idea to perform CPU operations in the middle of performing OpenGL commands? How can rendering commands and CPU operations be ordered such to maximize concurrency (Avoid the GPU waiting for the CPU to add commands to the Queue).

I have profiled the operations using CPU timings and Nvidia-Nsight and noted that on my machine: Decal CPU binning is about 2-3ms Light binning is about 0-1ms Cubemap binning is about 1ms

Geometry Rendering is about 1.5ms Decal Pass is about 1.5ms Reflections (ray marched) is about 6ms Denoising is about 2ms

The total frame time is about 15ms (including a shadow mapping section, particles, and the final shading pass). So performing the binning(GPU) in parallel with the GPU makes a lot of sense. For example, the Light binning could be done in parallel with the reflection pass, as the GPU doesnt need it until the final shading stage.

$\endgroup$
1
  • $\begingroup$ A good GPU profiling tool is probably the best way to find the answer to type of question. For example gpuopen.com/rgp which is specific to AMD. Then you can rearrange commands and see how it effects GPU utilization. $\endgroup$
    – pmw1234
    Commented Apr 3, 2023 at 22:31

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.