app: unload stream-probe cells before map transitions tear them down
This commit is contained in:
parent
87b27dc2a9
commit
70a7c55183
3 changed files with 56 additions and 6 deletions
|
|
@ -416,6 +416,26 @@ extern "C" REX_FUNC(sub_8247B3A0) {
|
||||||
(list_mode != 0 && list_count != 0) || cell_size > 4096) {
|
(list_mode != 0 && list_count != 0) || cell_size > 4096) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Loading screens and the frontend stream one world set out and another
|
||||||
|
// in, then destroy the departing collection objects. Any probe record
|
||||||
|
// kept in the gather output here stays loaded past that teardown and its
|
||||||
|
// content leaks into the arriving map (the differ cannot unload a record
|
||||||
|
// whose collection object is already gone - the ProcessEntries sanitizer
|
||||||
|
// below drops such descriptors without an unload). Leave the output
|
||||||
|
// untouched so probe cells unload through the same differ passes as the
|
||||||
|
// departing vanilla set while their collections are still live, and drop
|
||||||
|
// the caches: their neighbourhood is the departing map's. The in-game
|
||||||
|
// pause menu keeps the world resident and reports false; it merges the
|
||||||
|
// cache below instead.
|
||||||
|
if (skate3::native_scene::LoadingOrFrontendActive()) {
|
||||||
|
if (debug && (g_probe_cache[0].count > 0 || g_probe_cache[1].count > 0)) {
|
||||||
|
REXLOG_INFO(
|
||||||
|
"draw_distance: stream probe caches dropped (loading/frontend)");
|
||||||
|
}
|
||||||
|
g_probe_cache[0] = {};
|
||||||
|
g_probe_cache[1] = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ProbeRecord records[192];
|
ProbeRecord records[192];
|
||||||
size_t record_count = 0;
|
size_t record_count = 0;
|
||||||
|
|
@ -499,8 +519,12 @@ extern "C" REX_FUNC(sub_8247B3A0) {
|
||||||
const bool set_resident = desc_total > 0 && desc_loaded >= desc_total;
|
const bool set_resident = desc_total > 0 && desc_loaded >= desc_total;
|
||||||
const bool in_gameplay =
|
const bool in_gameplay =
|
||||||
rex::kernel::guest_presence::GameplayContextValue() == 1;
|
rex::kernel::guest_presence::GameplayContextValue() == 1;
|
||||||
if (cache_valid || (cache_usable && cache.count > 0 &&
|
// An empty vanilla gather is the game clearing this focus (teardown or a
|
||||||
(!set_resident || !in_gameplay))) {
|
// transient); never inject on top of it - the differ is about to unload
|
||||||
|
// everything the focus held.
|
||||||
|
if (vanilla_count > 0 &&
|
||||||
|
(cache_valid || (cache_usable && cache.count > 0 &&
|
||||||
|
(!set_resident || !in_gameplay)))) {
|
||||||
// The neighbourhood cannot have changed (cell membership is quantized
|
// The neighbourhood cannot have changed (cell membership is quantized
|
||||||
// to the grid): merge the cached probe results instead of re-running
|
// to the grid): merge the cached probe results instead of re-running
|
||||||
// the gather fan. Cached distances are slightly stale; they are only
|
// the gather fan. Cached distances are slightly stale; they are only
|
||||||
|
|
@ -525,10 +549,10 @@ extern "C" REX_FUNC(sub_8247B3A0) {
|
||||||
++record_count;
|
++record_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!set_resident || !in_gameplay) {
|
} else if (vanilla_count == 0 || !set_resident || !in_gameplay) {
|
||||||
// Initial load, a fresh focus, or outside gameplay (loading screen /
|
// Initial load, a fresh focus, an emptied focus, or outside gameplay:
|
||||||
// frontend): let the vanilla set finish streaming first; the fan
|
// let the vanilla set finish streaming first; the fan starts on a
|
||||||
// starts on a later cycle.
|
// later cycle.
|
||||||
} else {
|
} else {
|
||||||
// Full probe fan: every grid cell within the probe radius, stepped in
|
// Full probe fan: every grid cell within the probe radius, stepped in
|
||||||
// cell multiples. The 7x7 cap bounds the fan at 48 gather calls; the
|
// cell multiples. The 7x7 cap bounds the fan at 48 gather calls; the
|
||||||
|
|
|
||||||
|
|
@ -6092,6 +6092,23 @@ bool FreecamGuestPose(float out_pos[3]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LoadingOrFrontendActive() {
|
||||||
|
if (rex::kernel::guest_presence::GameplayContextValue() != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Same publish-staleness window as YieldForMenus: the pause menu keeps
|
||||||
|
// the world resubmitting perspective scenes behind it, loading screens
|
||||||
|
// and the frontend stop publishing.
|
||||||
|
const int64_t last_ns = g_last_publish_ns.load(std::memory_order_relaxed);
|
||||||
|
if (last_ns < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const int64_t now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
return now_ns - last_ns >= 300'000'000;
|
||||||
|
}
|
||||||
|
|
||||||
// Guest render thread only. Returns true when vp_out/cam_out hold a
|
// Guest render thread only. Returns true when vp_out/cam_out hold a
|
||||||
// re-timed pose for `now`; false = keep the raw guest pose (no history yet,
|
// re-timed pose for `now`; false = keep the raw guest pose (no history yet,
|
||||||
// or a cut/teleport snapped).
|
// or a cut/teleport snapped).
|
||||||
|
|
|
||||||
|
|
@ -500,6 +500,15 @@ void GetCapturedSunDir(float out[3]);
|
||||||
// SetViewMatrix override in skate3_native_scene.cpp.
|
// SetViewMatrix override in skate3_native_scene.cpp.
|
||||||
bool FreecamGuestPose(float out_pos[3]);
|
bool FreecamGuestPose(float out_pos[3]);
|
||||||
|
|
||||||
|
// True while the guest sits on a loading screen or in the frontend: the
|
||||||
|
// presence context is out of gameplay AND the world has stopped publishing
|
||||||
|
// perspective scenes. The in-game pause menu keeps publishing behind the
|
||||||
|
// menu and reports false. Mirrors the pause-vs-loading distinction in
|
||||||
|
// YieldForMenus (same 300 ms publish-staleness window). With scene capture
|
||||||
|
// disabled entirely, publishes never arrive and every out-of-gameplay
|
||||||
|
// context reports true (the conservative side).
|
||||||
|
bool LoadingOrFrontendActive();
|
||||||
|
|
||||||
// The game's per-entity spawn/streaming fade as carried by the item's
|
// The game's per-entity spawn/streaming fade as carried by the item's
|
||||||
// validated character-lighting capture (peds c21.x, defaultcharacter c13.x,
|
// validated character-lighting capture (peds c21.x, defaultcharacter c13.x,
|
||||||
// cacstamp c22.x, vehicle body c20.x, hair strand scale). 1.0 for items
|
// cacstamp c22.x, vehicle body c20.x, hair strand scale). 1.0 for items
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue