RT sun shadows: static stipple / dither pattern in penumbras that the denoiser never resolves (regression?) #841

Closed
opened 2026-10-18 06:10:33 +00:00 by sky_line · 2 comments
Owner

RT sun shadow penumbras show a fine, regular stipple / dither pattern that the denoiser never resolves. With a static sun and camera the pattern is completely static (doesn't crawl or settle). The test was with FSR off; the owner's normal setup is FSR native AA.

Setup: RenderVKSunShadows 2 (RT sun), shadow mask at half resolution (also at full, similar); RenderVKRTShadowSoftness 0.01. Every denoiser setting is on and at default (RenderVKRTShadowDenoise, …Svgf, …Atrous 3, …TemporalAlways, history 32, anti-lag, reactive, zoom-aware). The owner doesn't remember this grain surviving after the denoiser work, so it looks like a regression.

A static pattern means the per-frame noise / sample sequence isn't changing (a frozen seed or frame index), so temporal accumulation averages identical samples, AND the spatial filter isn't smoothing the penumbra either.

Suspects

  • #814 (beta 13) moved per-frame constants (frame info, light info, the deferred main view) into uniform buffers. If the RT shadow trace / denoiser reads its frame index / noise seed / jitter from a field that is no longer updated (the old SSBO copy, or a UBO block not refreshed for that pass), the noise freezes.
  • The noise is deliberately fixed when no temporal resolve follows (TAA / FSR off): the motion blur does that, and the RT shadow sampling may too. That stops temporal accumulation from converging, and the denoiser must then rely on its spatial (a-trous) passes. Check whether those passes actually smooth penumbra pixels or skip them (edge-stopping weights, the RenderVKRTShadowCertainBypass "certain" pixels, history-length gates).
  • Other beta 13 changes near the mask: the #831 fused shadow + classify kernel (the shadow pass now runs inside the tile-classify kernel with a different group shape), #827 split lighting consuming the mask.

Expected

Soft, noise-free penumbras with RT sun shadows, with and without TAA / FSR, as after the denoiser work (#666 and related).

penumbra stipple

RT sun shadow penumbras show a fine, regular **stipple / dither pattern** that the denoiser never resolves. With a static sun and camera the pattern is **completely static** (doesn't crawl or settle). The test was with FSR off; the owner's normal setup is FSR native AA. Setup: `RenderVKSunShadows` 2 (RT sun), shadow mask at half resolution (also at full, similar); `RenderVKRTShadowSoftness` 0.01. Every denoiser setting is on and at default (`RenderVKRTShadowDenoise`, `…Svgf`, `…Atrous` 3, `…TemporalAlways`, history 32, anti-lag, reactive, zoom-aware). The owner doesn't remember this grain surviving after the denoiser work, so it looks like a **regression**. A static pattern means the per-frame noise / sample sequence isn't changing (a frozen seed or frame index), so temporal accumulation averages identical samples, AND the spatial filter isn't smoothing the penumbra either. ### Suspects - **#814** (beta 13) moved per-frame constants (frame info, light info, the deferred main view) into **uniform buffers**. If the RT shadow trace / denoiser reads its frame index / noise seed / jitter from a field that is no longer updated (the old SSBO copy, or a UBO block not refreshed for that pass), the noise freezes. - The noise is deliberately **fixed when no temporal resolve follows** (TAA / FSR off): the motion blur does that, and the RT shadow sampling may too. That stops temporal accumulation from converging, and the denoiser must then rely on its spatial (a-trous) passes. Check whether those passes actually smooth penumbra pixels or skip them (edge-stopping weights, the `RenderVKRTShadowCertainBypass` "certain" pixels, history-length gates). - Other beta 13 changes near the mask: the #831 fused shadow + classify kernel (the shadow pass now runs inside the tile-classify kernel with a different group shape), #827 split lighting consuming the mask. ### Expected Soft, noise-free penumbras with RT sun shadows, with and without TAA / FSR, as after the denoiser work (#666 and related). ![penumbra stipple](https://git.slipstreamviewer.org/attachments/fe69dae3-3841-49d9-bf47-bd5b71089af1)
sky_line added this to the Slipstream project 2026-10-18 06:10:33 +00:00
Author
Owner

Root cause (7434f07789): the mask push packs its mode bits into a float (p0.y). Bits 22-23 (slope bias, default 2, added in da32667379, shipped in beta 13) push that value into [2^23, 2^24), where floats are spaced 1 apart. The shader decoded it as uint(x + 0.5), which rounds every odd value up to the next even one. That clears bit 0 (the denoiser) and the carry flips bit 1 (history valid). So on default settings every frame ran the legacy mask path: no history, and noise phase 0, giving a frozen stipple.

Evidence: RenderVKRTMaskDiag showed history len 0 and meta 0 on 64/64 surface samples, with the host's denoise flag on. Fix: decode with round(), which is exact for representable integers. p0.z gets the same decoder.

This affects release/1.3, so it's a hotfix candidate.

Root cause (7434f07789): the mask push packs its mode bits into a float (p0.y). Bits 22-23 (slope bias, default 2, added in da32667379, shipped in beta 13) push that value into [2^23, 2^24), where floats are spaced 1 apart. The shader decoded it as uint(x + 0.5), which rounds every odd value up to the next even one. That clears bit 0 (the denoiser) and the carry flips bit 1 (history valid). So on default settings every frame ran the legacy mask path: no history, and noise phase 0, giving a frozen stipple. Evidence: RenderVKRTMaskDiag showed history len 0 and meta 0 on 64/64 surface samples, with the host's denoise flag on. Fix: decode with round(), which is exact for representable integers. p0.z gets the same decoder. This affects release/1.3, so it's a hotfix candidate.
Author
Owner

Fixed in Slipstream 1.3.0 (stable): https://git.slipstreamviewer.org/sky_line/Slipstream/releases/tag/v1.3.0

If you still see this on 1.3.0, reply here and we'll reopen it.

Fixed in **Slipstream 1.3.0** (stable): https://git.slipstreamviewer.org/sky_line/Slipstream/releases/tag/v1.3.0 If you still see this on 1.3.0, reply here and we'll reopen it.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#841
No description provided.