Feed the sets passed to render(); returns the current version, bumped when the content changed since the previous call. An EMPTY hidden set is equivalent to no hidden filter; an EMPTY isolated set is NOT equivalent to null (it isolates nothing, i.e. hides everything). Cost is O(|hidden| + |isolated|) membership checks per call — strictly below the O(scene elements) per-batch scan this version key lets the renderer skip.
Content-based change tracking for the per-frame hide/isolate sets.
The renderer caches per-batch visibility keyed by the version this tracker produces, so correctness demands the version bumps EXACTLY when the effective filter changes: