Visibility Buffer (Experimental)
Visibility Buffer is off by default.
In the latest recorded TROPICS benchmark, async mode 2 slightly outperformed legacy rendering. VRCS and compute shadows increased frame time. Results depend on the scene, hardware and configuration.
Unreal Engine X adds a hybrid visibility buffer for non-Nanite foliage. Foliage tool and landscape grass instances write visible triangle identities into a visibility texture. Compute shaders reconstruct their surface attributes, evaluate materials and write the GBuffer.
Other geometry uses the normal depth prepass and BasePass. Standard deferred lighting remains available, with optional VRCS lighting consumers.
Enable
For an initial comparison, use:
r.RDG.AsyncCompute 1
x.RDG.AsyncComputeSplitFence 1
x.VisibilityBuffer.AsyncCompute 2
x.VisibilityBuffer.VRCS 0
x.VisibilityBuffer.ComputeShadows 0
x.Experimental.VisibilityBuffer 1
Compare against x.Experimental.VisibilityBuffer 0, keeping the camera and other
settings unchanged. Allow shader compilation and PSO preparation to settle before
measuring.
Changing between disabled and enabled rebuilds component render state.
Run x.VisibilityBuffer.DumpStats after the scene settles to inspect routing
and material eligibility.
Main settings
Defaults were checked against source on 22 October 2026.
| Console variable | Default | Purpose |
|---|---|---|
x.Experimental.VisibilityBuffer | 0 | 0 disables VB, 1 enables it, 2–6 select debug views |
x.VisibilityBuffer.AsyncCompute | 2 | Selects classification, vertex and material queue placement |
x.VisibilityBuffer.WPOPixelCoverage | 4 | Coverage limit for packed WPO pixel shading |
x.VisibilityBuffer.MinLOD | 0 | Lowest mesh LOD eligible for VB |
x.VisibilityBuffer.PrecachePSOs | 1 | Prepares eligible foliage raster and compute material PSOs during loading |
x.VisibilityBuffer.VRCS | 0 | Optional variable-rate compute texturing and lighting |
x.VisibilityBuffer.ComputeShadows | 0 | Optional compute projection of directional PCSS cascades |
x.VisibilityBuffer.DumpStats | command | Logs routing, material eligibility, quad utilization and vertex statistics |
PrecachePSOs is a read-only startup setting. Changing MinLOD rebuilds render
state.
The old x.VisibilityBuffer.TransientResources setting is absent from the current
implementation.
Geometry and material support
Requirements:
- D3D SM6 with GPUScene.
- Single-sample legacy deferred rendering.
- Compute-writable scene color and GBuffer targets.
- Eligible non-Nanite foliage geometry.
| Geometry | Rendering path |
|---|---|
| Foliage tool instances and landscape grass | VB when material, geometry and LOD checks pass |
| Static mesh actors, ordinary ISM/HISM and Landscape | Normal depth prepass and BasePass |
| Nanite geometry | Nanite's own rendering path |
Routing follows component type. A rock painted using the Foliage tool can qualify, while the same rock placed as a static mesh actor stays on the normal path.
Opaque and masked foliage materials are supported, including WPO. Supported shading models are Default Lit, Unlit, Two Sided Foliage, Cloth and Subsurface.
Cloth here means the material shading model. It does not enable skeletal meshes or simulated cloth geometry in the foliage VB.
The following remain on the normal path:
- Pixel Depth Offset and anisotropic materials.
- First-person output and motion-vector world-offset materials.
- Custom HLSL pixel discard.
- Baked or cached lighting policies.
- Unsupported vertex factories or geometry bindings.
Forward rendering and Substrate are rejected.
Pipeline
| Stage | What it does |
|---|---|
| Visibility raster | Writes foliage depth and visibility tokens identifying the visible geometry. WPO is evaluated during rasterization |
| Two-pass occlusion | Re-tests instances rejected against the previous HZB using the current frame's HZB |
| Classification | Groups visible work by material and shading mode, builds indirect work lists and identifies required WPO vertex chunks |
| Vertex processing | Transforms required WPO vertex chunks once into a cache. Previous-frame vertex history supplies positions for velocity |
| Material resolve | Reconstructs surface attributes, evaluates materials and writes the GBuffer |
| Deferred lighting | Uses the resolved GBuffer through standard lighting or eligible optional VRCS consumers |
Packed pixels and cooperative quads
Materials verified as derivative-free can shade one covered pixel per lane, using analytic derivatives for reconstruction and texture sampling. This avoids helper-lane work on small foliage triangles.
Materials requiring derivative operations use cooperative 2×2 quad shading.
x.VisibilityBuffer.WPOPixelCoverage controls the coverage limit for packed WPO
shading. Its default of 4 permits packed shading for every covered pixel when
the material supports it.
Depth ownership
Some non-VB meshes can write depth during BasePass after the visibility raster. In that configuration, the VB raster also records its depth and material resolve checks that a nearer BasePass surface has not replaced the pixel.
With a full masked prepass and depth-read-only BasePass, the extra ownership target and test are unnecessary.
Async compute
| Mode | Classification | Vertex processing and material resolve |
|---|---|---|
0 | Graphics | Graphics |
1 | Graphics | Async after BasePass |
2, default | Async, allowing overlap with BasePass | Async after BasePass |
3 | Async after BasePass | Async after BasePass |
Async modes require r.RDG.AsyncCompute 1. Otherwise all VB compute work runs
on graphics.
Mode 2 allows classification to overlap BasePass and later work to overlap HZB and shadow depths. These passes still compete for GPU resources. Judge the resulting frame time rather than adding individual pass durations.
Mode 3 explicitly waits for BasePass before starting the async chain.
Latest measured performance
Trace 20261020_120621, TROPICS map, RTX 3060, 1920×1080, Reflex enabled.
Numbers are per-frame GPU medians from the saved trace analysis.
| Configuration | GPU frame | Approximate difference from legacy |
|---|---|---|
| Legacy, three segments | 9.12–9.20 ms | Baseline |
| VB, async mode 0 | 9.61–9.66 ms | +0.5 ms |
| VB, async mode 2 | 9.02–9.05 ms | −0.10 to −0.15 ms |
| VB, async mode 2 + VRCS | 9.36–9.40 ms | +0.2 ms |
| VB, async mode 2 + VRCS + compute shadows | 9.72–9.75 ms | +0.55 ms |
Async mode 2 improved frame time by about 0.6 ms over mode 0, despite increasing ShadowDepths by approximately 0.26 ms through queue contention.
Use mode 2 with VRCS and compute shadows disabled as the starting configuration.
Earlier results
Earlier builds and views produced mixed results. Foliage-only routing improved some occluder-heavy views, while dense jungle views could remain slower.
The corrected 13 October Showcase retest measured mode 2 at approximately 0.25 ms slower than the best legacy configuration. The later TROPICS result does not establish a gain in every scene.
Reading async timings
Use the GPU0-Compute0 Work/Wait tracks to distinguish execution from waiting.
An async scope's wall time can include a fence wait and overstate shader cost.
Render-thread setup also has measurable overhead. The later EarlyClassify experiment did not improve frame time or materially reduce its setup wait and was removed.
Variable-rate compute shading
x.VisibilityBuffer.VRCS 1 enables optional variable-rate compute texturing
and lighting.
The implementation includes:
- A rate image informed by luminance and depth.
- Primary/copy selection for compatible surface pixels.
- Coarse material evaluation with copied GBuffer outputs.
- Lighting work construction.
- Optional directional-light, clustered-light and reflection/sky consumers.
- Deblocking of copied lighting pixels.
Each consumer has separate eligibility checks and can fall back to the normal path.
VRCS controls
These sub-switch defaults apply only while their parent features are enabled.
| Console variable | Default | Purpose |
|---|---|---|
x.VisibilityBuffer.VRCS.Texturing | 1 | Coarse material resolve |
x.VisibilityBuffer.VRCS.Lighting | 1 | Lighting work construction and lighting consumers |
x.VisibilityBuffer.VRCS.Shadows | 1 | Coarse compute shadow projection, also requiring ComputeShadows |
x.VisibilityBuffer.VRCS.ClusteredLights | 1 | Eligible clustered local lights |
x.VisibilityBuffer.VRCS.Reflections | 1 | Eligible reflection and sky composition |
x.VisibilityBuffer.VRCS.Deblock | 1 | Interpolates copied lighting pixels |
x.VisibilityBuffer.VRCS.EdgeThreshold | 0.2 | Luminance-gradient threshold |
x.VisibilityBuffer.VRCS.DepthThreshold | 0.005 | Relative depth threshold |
x.VisibilityBuffer.VRCS.NormalThreshold | 0.9 | Minimum normal cosine for shared lighting |
x.VisibilityBuffer.VRCS.MotionScale | 0 | Optional motion-based rate adjustment |
x.VisibilityBuffer.VRCS.Debug | 0 | 1 displays rates, 2 displays lighting primary/copy pixels |
Current performance
VRCS added approximately 0.34 ms over VB mode 2 in the latest capture.
Classification work increased from approximately 0.31 to 0.66 ms, while material shading decreased from approximately 1.33 to 1.23 ms. Rate generation, lighting work construction and deblocking added further work.
Enabling VRCS currently disables hardware VRS for the entire frame. This also increases the cost of non-VB raster passes.
The TROPICS capture contained no clustered local lights, and its VRCS reflection consumer fell back. Their performance is therefore unmeasured in this comparison.
Compute shadows
x.VisibilityBuffer.ComputeShadows 1 optionally projects directional PCSS
cascade shadows using compute shaders.
It projects existing shadow maps and does not replace shadow-depth rasterization.
The path requires compatible directional cascades, a UAV-capable shadow mask and
r.Shadow.FilterMethod 1 or 3. Substrate and instanced stereo are rejected.
x.VisibilityBuffer.ComputeShadows.MinMax defaults to 1 and enables a min/max
hierarchy to skip eligible PCSS work.
Compute shadows added approximately 0.36 ms on top of the VRCS configuration in the latest capture. The feature remains disabled by default.
Debugging
x.Experimental.VisibilityBuffer provides these views:
| Value | View |
|---|---|
2 | Material IDs |
3 | Triangle IDs |
4 | Draw IDs |
5 | GPUScene instance IDs |
6 | Quad utilization |
In quad utilization, green indicates packed pixels, blue indicates full quads, and yellow through red indicates helper-lane work.
Pixels outside VB routing are dimmed. A fully dimmed view can indicate that no visible geometry qualifies.
Use x.VisibilityBuffer.DumpStats after settling following an enable or routing
change. Compare routing, rejected materials, vertex work and quad utilization.
References
- Guerrilla Games, “Adventures with Deferred Texturing in Horizon Forbidden West”, GDC 2022.
- id Software, “Variable-Rate Compute Shaders in DOOM: The Dark Ages”.
- id Software, “The devil is in the details: idTech 666”, SIGGRAPH 2016.
- Burns and Hunt, “The Visibility Buffer: A Cache-Friendly Approach to Deferred Shading”, JCGT 2013.
- The Forge visibility buffer samples.
- Wicked Engine visibility buffer implementation.
- Unreal Engine Nanite shading bins and two-pass occlusion.