GPU culling

Hello,

There are techniques for view frustum culling on cpu and gpu. I wonder why one would want to do culling on gpu, since culling on cpu potentially saves memory bandwidth of uploading mesh, textures etc. to gpu device-local memory?

The question is not directly about Vulkan, but I think it would be more “interesting” to discuss it in Vulkan terms…

Redrawing the same model is less work than culling parts of it and drawing the changed model. It also takes a significant amount of time to download a mesh from the disk and upload it to the GPU so you may as well get ahead of the game there (literally and figuratively).

So you are going to need to upload the full mesh anyway because the camera may move at any time (FPS players like being able to 360 in half a second), when a model suddenly needs to be drawn you just don’t have time to upload it to the gpu especially if you still need to grab it of the disk.

Per model culling is something that is viable when building the command buffer each frame but if you want to reuse the command buffer you again can’t cull based on the frustum.

Can you elaborate on “per model culling”? I’m not sure what you mean by that.

What I’m trying to achieve is something like google earth/maps (with openstreetmaps actually). I think I won’t have enough vram for all the data, so I will need to stream textures and meshes
constantly to the gpu, subject to camera frustum (coarse-grained).

foreach(model in models){
   if(isVisible(model)){
       //upload model transform uniform
       vkCmdDraw(...);
   }
}

model being a decent-sized chunk of terrain

This test is separate from which models are uploaded to vram, which should be more coarse grained with some hysteresis

What I’m trying to achieve is something like google earth/maps (with openstreetmaps actually).

That is a very different matter. You’re talking about streaming, which has to deal with the dynamically loading pieces of model data. Such a system extends beyond the low-level renderer, into issues of disk access and the like.

But even in such a system, GPU-computed visibility can still be relevant. The CPU has to be involved in uploading mesh data, but the GPU can still decide which uploaded meshes are visible at which times. After all, just because the camera moves past something doesn’t mean you immediately unload it from memory. If the user turns around, it should be there and it should be visible in full detail.

The overall purpose of GPU-based culling is to limit the number of draw calls and state changes the CPU has to put into command buffers. This alleviates the CPU burden of building command buffers to a degree. Honestly, this matters a lot more for OpenGL than Vulkan. In OpenGL, state changes and rendering commands hurt the CPU a lot, and you can only send them from one thread. In Vulkan, command buffer building isn’t free, but it’s a lot cheaper than OpenGL. Plus, you can thread it.

That’s not to say that GPU culling is pointless in Vulkan. By putting it on the GPU, it means the CPU doesn’t have to do a bunch of memory reads and testing of values. It’s just not as huge of an improvement compared to what you get from OpenGL GPU culling.

Thanks all, got it!