DirectCompute Frustum Culling to Reduce Vertex Work

DirectCompute frustum culling moves visibility determination from the CPU to the GPU, filtering out non-visible geometry before it reaches the traditional rendering pipeline. By evaluating bounding volumes inside a compute shader and emitting draw arguments directly on the GPU, the system prevents culled geometry from ever being submitted to the Input Assembler and Vertex Shader. This overview examines how this GPU-driven architecture operates, why it bypasses early pipeline bottlenecks, and how it drastically reduces downstream vertex processing in DirectX applications.

The Problem with Traditional Culling

In a standard graphics pipeline, the CPU performs coarse frustum culling on scene objects and submits draw calls for those that intersect the camera frustum. However, CPU-side culling often operates at a coarse granularity due to performance constraints, resulting in many partially occluded or out-of-view objects being submitted.

When these draw calls reach the DirectX graphics pipeline, every vertex belonging to the submitted geometry must pass through the Input Assembler (IA) and Vertex Shader (VS). The hardware only discards off-screen geometry at the clipping and primitive setup stages, which occur after vertex shading has already consumed memory bandwidth and compute cycles.

The DirectCompute Frustum Culling Workflow

DirectCompute solves this inefficiency by shifting visibility testing to a compute pass executed immediately before the main rasterization passes. The process operates in four discrete stages:

  1. Bounding Volume Evaluation: The compute shader reads per-object or per-instance bounding data (such as Axis-Aligned Bounding Boxes or bounding spheres) stored in a structured buffer. Each thread or threadgroup evaluates whether a bounding volume intersects the camera's six frustum planes.
  2. Buffer Compaction: Surviving instances that pass the frustum intersection test write their identifiers to a visible instance buffer (an append or structured buffer). Threads use atomic operations or parallel prefix sums (stream compaction) to place visible instances sequentially in memory.
  3. Indirect Argument Generation: Instead of sending instance counts back to the CPU, the compute shader writes the final draw counts and offsets directly into an indirect arguments buffer conforming to DirectX's D3D12_DRAW_INDEXED_ARGUMENTS or D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS structure.
  4. Indirect Rendering: The graphics pipeline executes the render pass using DrawIndexedInstancedIndirect (or ExecuteIndirect in DirectX 12).

How Vertex Work Is Eliminated

Executing this culling pass via DirectCompute reduces vertex work in the subsequent graphics passes through specific hardware mechanisms:

  • Bypassing the Input Assembler: Because non-visible objects are excluded from the indirect draw arguments, the Input Assembler never fetches index or vertex data for those objects from VRAM. This saves significant memory bandwidth, especially for dense, high-polygon meshes.
  • Skipping Vertex Shader Invocations: Vertices that are completely outside the view frustum are never shaded. In conventional rendering, the vertex shader must run on all vertices to project them into clip space before the fixed-function clipper can discard them. DirectCompute culling discards these meshes prior to the graphics pipeline, reducing total vertex shader invocations to only what is within the view.
  • Finer-Grained Cluster and Meshlet Culling: Beyond whole-object culling, DirectCompute can cull geometry at the cluster or meshlet level (small groups of 64–128 vertices). By evaluating bounds for individual sub-mesh chunks, large objects that partially intersect the frustum have their non-visible sections stripped out before the vertex pipeline runs, eliminating unnecessary transformations on partially visible geometry.
  • Elimination of CPU-GPU Synchronization Latency: Because the compute shader directly populates the argument buffer on the GPU, the CPU does not need to read back visibility results. The graphics pass can execute immediately after the compute pass using resource barriers, ensuring the pipeline remains fully saturated while processing a significantly reduced vertex payload.