Skip to content

llf/scm: root-cause the stale sceneLights pass family (guards treat the symptom) #235

Description

@alandtse

Umbrella for the #92 / #233 family. The hook-site guards
(IsSafeLightRange + SEH) are symptom treatment — this issue tracks
whether the cause is reachable.

The actual cause

The engine caches/pools BSRenderPass objects whose sceneLights[]
is a raw BSLight**. A cached pass can outlive its lights; the
engine then derefs freed memory (GeometrySetupConstantDirectionalLight
reads sceneLights[0]->light->fade with zero checks). This is an
engine-native lifetime hazard — but vanilla rarely trips it because
vanilla light lifetime is stable. Shadow Light Fix / SCM
deliberately churns BSLights
(promoting NiLights to shadow-casting
lights and back), multiplying free/alloc cycles and widening the
stale window. That is why this family arrived with SLF.

Root-fix options assessed

  1. BSLight graveyard (deferred destruction) — tractable.
    Intercept BSLight release at SCM's conversion/free points, park in
    a bounded N-frame list, free after rendering. Kills within-frame
    and short-window staleness (the BookMenu case is likely this
    class). Cannot cover long-lived cached passes (cross-cell) without
    unbounded retention, so guards remain as backstop — but the warn
    lines should become rare, which is itself the measurement.
  2. Scrub engine pass pools on light free — the true fix, heavy
    RE. Requires reversing the BSRenderPass allocator/pool layout and
    patching sceneLights entries on destruction; enumeration is racy
    against the render thread. Prior art says caution: SCM ref-holding
    was already tried and was insufficient for cross-cell staleness.
  3. Ref-holding in sceneLights — not possible; engine struct is a
    raw pointer array written engine-side.

Proposal: implement (1) behind SCM, keep the (now-unified) guards as
defense-in-depth, and treat guard warn-line frequency in logs as the
regression metric. If warns persist for long-lived passes, that is
the evidence needed to justify the RE cost of (2).

Related: #92, #233, PR #234 (unified guards + per-frame probe cache).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions