ReSTIR Integration in DirectX Raytracing (DXR)

Reservoir-based Spatio-Temporal Importance Resampling (ReSTIR) dramatically improves real-time ray tracing performance by enabling the sampling of millions of dynamic lights with minimal noise and overhead. Integrating ReSTIR into DirectX Raytracing (DXR) involves coupling compute-driven importance resampling passes with hardware-accelerated ray tracing to resolve visibility. By maintaining compact data structures called reservoirs across space and time, the pipeline limits expensive DXR shadow ray evaluations to only the most promising light candidates, making path tracing and complex direct illumination practical in modern real-time rendering.

The Reservoir Data Structure and Buffer Allocation

At the core of ReSTIR is the reservoir, a lightweight structure that tracks candidate samples using streaming importance sampling (RIS). In DirectX 12, each reservoir is represented as a structured data element containing:

  • The selected sample (such as a light index or radiance sample).
  • The sum of candidate weights (\(w_{sum}\)).
  • The number of processed candidates (\(M\)).
  • The final normalization weight (\(W\)).

These structures are stored in GPU memory using 2D or structured RWStructuredBuffer (Unordered Access Views / Shader Resource Views). Because temporal reuse requires reading the previous frame’s results and writing the current frame’s state, developers implement ping-pong double buffering for the reservoir data alongside standard G-buffer data (world normals, linear depth, and motion vectors).

The ReSTIR Execution Pipeline in DXR

A typical ReSTIR direct illumination (ReSTIR DI) integration divides the frame into distinct compute and raytracing stages:

  1. Initial Candidate Generation (Compute or RayGen Shader): The GPU generates an initial set of light candidates per pixel. This is typically implemented in a standard compute shader or a DXR Ray Generation shader. Light sources are sampled proportionally to their unshadowed contribution using light grids or bounding volume hierarchies (BVHs). A reservoir is filled for each pixel without performing visibility tests.

  2. Temporal Resampling: A compute shader reprojects the current pixel to the previous frame using motion vectors. If the history sample passes geometric validation tests (depth and normal thresholds), the previous frame's reservoir is combined with the current reservoir. This combines history weights without tracing rays, rapidly boosting sample counts (\(M\)).

  3. Spatial Resampling: To further reduce variance, neighboring screen-space reservoirs are gathered and combined. A compute shader iterates over a random set of neighboring pixels, checking depth and normal similarity to prevent light leaking across geometry boundaries. Reservoirs from valid neighbors are merged mathematically.

  4. Visibility Determination using DXR: Evaluating visibility is the most expensive operation in ray tracing. The key advantage of ReSTIR is that visibility (shadow rays) only needs to be evaluated for the final selected light sample after resampling, rather than for every initial candidate.

    Under DXR, visibility is resolved in one of two ways:

    • DXR 1.0 (DispatchRays): A Ray Generation shader calls TraceRay() with a simple payload and ray flags like RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER against the Top-Level Acceleration Structure (TLAS).
    • DXR 1.1 (Inline Raytracing via RayQuery): Modern implementations frequently utilize RayQuery directly within compute shaders. This avoids the overhead of separate Ray Generation pipelines and shader table dispatches, allowing candidate generation, spatial merging, and shadow testing to occur within a unified compute pass.
  5. Final Shading: Pixels that pass the visibility check calculate the final direct lighting contribution by multiplying the light's evaluated radiance, the material's Bidirectional Reflectance Distribution Function (BRDF), and the reservoir’s final weight (\(W\)).

Performance Considerations

Integrating ReSTIR into DXR requires careful management of ray tracing divergence and register pressure. Inline raytracing (RayQuery) minimizes pipeline state object (PSO) switching overhead and simplifies debugging in tools like PIX. Additionally, limiting spatial reuse sample counts and applying temporal clamping prevents historical bias, fireflies, and ghosting artifacts during rapid camera or light movements.