Video summary

Erik Jansson - GPU driven Rendering with Mesh Shaders in Alan Wake 2

Main summary

Key takeaways

Technology

Summary (technological concepts, features, analysis)

Speaker / background

  • Edik (Erik) Jansson, Senior Graphics Programmer at Remedy Entertainment, presents GPU-driven rendering as used in Alan Wake 2.
  • Focus areas:
    • GPU-driven pipeline architecture
    • Meshlets
    • Mesh shaders
  • Talk context: primarily console rendering with performance numbers shown for Xbox Series X.

Why GPU-driven rendering was needed (from Control → Alan Wake 2)

Limitations in Control (earlier Remedy game)

  • The pipeline relied on a largely non–GPU-driven approach, with significant CPU-side work:
    • CPU-side culling remained expensive (example: ~3 million triangles still present after CPU-side culling in an indoor, flat-geometric scenario).
    • Command list recording on previous-gen consoles used multiple CPU cores, but it wasn’t efficient enough for next-gen scaling.

Increased complexity in Alan Wake 2 (Pacific Northwest scene)

  • Scene complexity grows sharply:
    • ~200M triangles before culling
    • Dense vegetation + widespread photogrammetry
  • Additional factors:
    • Fewer “main occluders” (less wall-like structure)
    • Heavy reliance on alpha testing

Resulting motivation

  • GPU-driven rendering reduces:
    • CPU overhead
    • command submission
  • This enables the render thread to be ~single-core, freeing CPU time for other systems.
  • After GPU-side culling, triangle counts become manageable (~10.6M triangles), making real-time console rendering feasible.

GPU-driven pipeline architecture (high-level)

CPU-to-GPU population model

  • Even GPU-driven rendering begins with CPU-side setup:
    • CPU streams/updates persistent objects into draw sets
    • Objects are organized into buckets based on material properties, e.g.:
      • Vegetation with alpha-tested depth-pass bucket
      • Rocks / single-sided non-alpha bucket

Per-view visibility construction

  • Visible draw sets are created per view, including:
    • Camera view
    • Shadow map views (e.g., spotlight views)

Incremental GPU updates

  • CPU updates the GPU incrementally (only differences), avoiding full rebuilds every frame.

Core geometry passes mentioned

  • Skinning pass
  • Depth pre-pass
  • Shadow maps
  • G-buffer pass

Alpha handling strategy

  • The G-buffer pass avoids alpha testing because depth pre-pass already handled it.
  • The “hard” alpha-tested steps remain:
    • Depth pre-pass
    • Shadow depth passes

Occlusion culling challenge and “last-frame occluders”

The chicken-and-egg problem

  • Occlusion culling needs hierarchical depth structure (e.g., Hi-Z/HZB), but building it normally requires rendering—creating a dependency loop.

Approach: reuse last frame

  • Render the previous frame’s occluders
  • Build a Hi-Z / HZB-like structure
  • Perform occlusion culling using it

Handling correctness gaps

  • This introduces gaps, so the fix is:
    • Render the missing remainder after the culling decision

Temporal continuity / correctness

  • The culling result is carried to the next frame.
  • Correctness is maintained by re-drawing previously culled geometry using new-frame meshlet references, which keeps animated/skinned geometry consistent.

Bindless rendering considerations

Why bindless helps

  • Uses bindless resources (indexing descriptor heaps rather than binding slots):
    • reduces CPU overhead
    • increases flexibility

Pitfall: divergent resource access

  • Divergent indexing can trigger DXE/driver/compiler issues.
  • Mitigation:
    • nonuniform resource index
  • Warning:
    • May hurt performance on AMD due to added control flow.

Alternative: uniform indexing

  • Another option is trying to make indices uniform (e.g., wave-lane techniques),
  • but only works if truly uniform—otherwise artifacts can occur.

Extending beyond textures

  • For Alan Wake 2, the approach expands to:
    • Bindless geometry for the meshlets/mesh shader path

Meshlets: generation and bounds

Meshlets as the primitive

  • Meshlets are treated as the unit of work for mesh shaders.

Generation process

  • They use an open-source meshlet library (described as “excellent”) that largely works out-of-the-box.
  • Meshlet generation uses a greedy algorithm, with rare edge cases where bounds may be slightly worse.

Meshlet sizing choice (Alan Wake 2)

  • Chosen size: 64 triangles + 64 vertices per meshlet.
  • Trade-off noted:
    • Larger meshlets can improve performance on some architectures.
    • Smaller meshlets can improve culling efficiency.
  • Advice: tune for real production scenarios, not only synthetic tests.

Bounds required for culling

  • Bounding spheres
  • Normal cones:
    • cone axis + spread
    • spread stored quantized; dequantize in shaders

Dynamic / skinned geometry bounds

  • Compute shader updates bounds for skinned instances:
    • Sphere update: bounding sphere via wave reductions (min/max/mean) over skinned vertex positions
    • Normal cone update: reductions over transformed normals to compute cone axis/spread
  • Reported performance on Xbox Series X:
    • ~<2ms for sphere updates
    • ~+0.1ms for normal cone updates
    • (happening over a large meshlet-rich area)

Calling strategy: from “naive rendering” to staged GPU culling + mesh shader execution

Naive scale example

  • ~200k instances
  • ~4M meshlets
  • ~200M triangles

Multi-stage savings pipeline

Key stages:

  1. Frustum culling
  2. “Frostum?” / shadow-cascade fitting:
    • further-away shadow cascade fitting using frustum plane counts
    • mentions using more clipping planes to fit cascades to occluders
  3. Contribution culling (especially for shadow maps)
    • project meshlet bounding sphere into a screen-space rectangle (L-B-R-T concept)
    • compare against a minimum contribution threshold
    • reported savings: ~2ms in shadow map pass scenarios; tuning is difficult
  4. Normal cone calling (conceptually backface-ish for meshlets)
    • described as existing, but not used for Alan Wake 2 mainly because occlusion culling already rejects many backfacing meshlets
  5. Occlusion culling (the main “holy grail”)
    • Uses HZB
    • samples depth at UV corners across an appropriate mip level vs the sphere depth
    • requires conservative max-based downsampling (not average)
HZB construction details
  • Use max-downsample Hi-Z for conservativeness.
  • May pad to power-of-two/parity to avoid edge flicker.
Build method choice
  • They use a single-pass downsampler (vs AMD SPD-style reference).
  • Reported impact:
    • ~2.2ms less rendering time
    • improves triangle count down to ~12.3M before later steps

Overall results (core headline)

  • After the calling pipeline:
    • ~10.6M triangles from ~200M initial
  • Shadow + G-buffer times are included in the talk, but the triangle-count reduction is the main headline.

Mesh shader usage and performance characteristics

Execution model

  • Mesh shaders are the final draw mechanism after compute-driven culling/calling.

Pipeline simplification

  • They describe a mesh-shader-only approach:
    • no amplification shaders (mesh shaders only)

Mesh shader example behavior

  • Configured like a small compute-style program:
    • outputs up to 64 triangles / vertex attributes
    • starts from per-meshlet bounds
    • does bookkeeping, transforms vertices, outputs triangle indices

Benefit vs classic vertex shader pipeline

  • Reported benefit: mesh shader version can be ~2x faster in some cases.
  • Attribution: largely due to more precise culling
    • “call meshlets instead of full meshes” (not mesh shaders magically reducing all costs)

Per-primitive calling / filtering

  • Adds an extra step inside mesh shaders:
    • reject triangles that won’t cover required sample points (conceptually linked to SV_Coverage / per-primitive behavior)
  • Hardware dependence:
    • Some GPUs see benefit; others see wash or loss
    • Example outcomes mentioned:
      • RDNA2: large win (~1.8ms faster)
      • PC (Nvidia): a loss in this specific test
      • Console wins reported (e.g., Series X ~8ms, Series S ~1.67ms)

Conclusions / lessons learned

  • Alan Wake 2 shipped with mesh shaders, presented as an early production use.
  • Remedy’s Northlight engine moved toward a fully GPU-driven rendering engine, improving iteration:
    • artists previously experienced “slow” iteration
    • now graphics can reflect actual content performance constraints (“your content is slow”)
  • Mesh shaders are described as mature enough for flexibility and performance benefits.
  • Major takeaway:
    • meshlets + mesh shaders dramatically increase the amount of culling/calling possible.

What’s next (future directions)

  • Work graphs
    • could reduce worst-case allocation costs when using execute indirect
    • avoid buffer blow-up
  • Micropolygon-style software rasterization / Nanite-like approach
    • they already do contribution calling + per-triangle calling
    • but may still need rasterization for small triangles
    • a classified approach could choose between software rasterization and fixed-function GPU paths
  • Reduce alpha-testing overdraw
    • alpha testing is costly (especially vegetation)
    • propose a classification/draw strategy to reduce alpha-test overdraw
  • More seamless meshlet loading
    • reduce popping
  • Meshlet compression research
    • mentioned work reportedly down to ~5 bits per triangle
    • performance impact still needs evaluation

Main speakers / sources (as mentioned)

  • Primary speaker: Edik (Erik) Jansson, Senior Graphics Programmer, Remedy Entertainment
  • Mentioned contributors / teams
    • Northlight engine team at Remedy
    • T. Alto (lead; key contributor to the GPU-driven rendering pipeline)
  • Tools / libraries
    • Open-source meshlet generation library (credited to A. Kappulkin per the subtitle)
  • Referenced related material
    • Prior/related resources: earlier GDC presentation on skinned vegetation meshlets (not fully detailed in the subtitles)
    • AMD SPD / SPD-like reference for Hi-Z downsampling
    • A named alternative for Hi-Z/HZB downsampling (subtitle suggests a person/approach; partially unclear)

Rate this summary

Your feedback will help improve summaries.

Improve this summary

Reprocess with a stronger model when the summary feels incomplete or inaccurate.

Pro

Translate summary in another language

Pro

Ask questions to this video

Chat for follow-up questions, clarifications, and source-backed answers.

Coming soon

Share this summary

Original video