DirectX Meshlet Vertex and Primitive Limits
In DirectX 12's mesh shading pipeline, geometry is partitioned into small sub-meshes known as meshlets to optimize GPU memory bandwidth and enable granular culling. This article examines the typical number of vertices and primitives processed within a single DirectX meshlet, contrasting the architectural hardware ceilings with real-world, vendor-recommended implementation sizes.
Architectural Hardware Ceilings
The DirectX 12 specification allows a mesh shader threadgroup to output a hardware maximum of:
- Maximum Vertices: 256
- Maximum Primitives: 256
These figures represent hard limits set by the Direct3D 12 runtime. While a meshlet can theoretically allocate up to these caps, doing so often degrades performance due to increased register pressure and reduced hardware thread occupancy.
Typical Recommended Values
In production environments, graphics developers and hardware vendors (such as NVIDIA and AMD) recommend considerably smaller configurations to maximize GPU cache utilization and parallel execution:
- Typical Vertices: 64 (rarely exceeding 128)
- Typical Primitives (Triangles): 126 to 128
The most common default configuration used across modern game engines and geometry utilities (such as DirectXMesh) is 64 vertices and 126 primitives.
Reasons for These Targets
- GPU Occupancy and Shared Memory: Mesh shaders allocate output vertex and primitive attribute storage in high-speed, on-chip shared memory. Sizing meshlets to 64 vertices and 126 primitives leaves sufficient local memory for multiple threadgroups to execute concurrently across individual Streaming Multiprocessors (SMs) or Compute Units (CUs).
- Thread Mapping and Wavefront Alignment: GPUs process work in warps (32 threads on NVIDIA) or wavefronts (32 or 64 threads on AMD). Aligning output allocations closely with multiples of these execution sizes avoids idle execution lanes and ensures uniform workload distribution.
- Primitive Index Alignment: The specific choice of 126 triangles instead of 128 often stems from index buffer packing. Triangles require three 8-bit or 16-bit indices; using 126 primitives maintains optimal alignment within 4-byte boundaries, simplifying hardware memory access patterns.
- Culling Granularity: Keeping meshlets within these ranges ensures bounding volumes remain compact. This increases the efficiency of early frustum, backface, and cone-based occlusion culling at the meshlet level before any vertices are forwarded to the rasterizer.