scene: startup-flow CAS editor renders (heartbeat exemptions on 3 gates)
This commit is contained in:
parent
700e1e2d82
commit
f2155aa7fb
1 changed files with 58 additions and 17 deletions
|
|
@ -3039,6 +3039,23 @@ void OnSetShader(bool pixel, uint32_t obj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The CAS editor is ON SCREEN now: its own "_nis" pixel shaders were set
|
||||||
|
// within the last 0.5 s (see IsCasEditorPs). Consumed by the portrait-pass
|
||||||
|
// publish gate and the takeover gates; the STARTUP-flow editor's scene is
|
||||||
|
// skater-only (the garage geometry only exists in-world, so pre-gameplay the
|
||||||
|
// scene is ~10 all-character items at cam (-3.8,200.9,-7.6)), which both looks exactly like a portrait pass and sits below
|
||||||
|
// warmup_min_items.
|
||||||
|
bool CasEditorHeartbeatFresh() {
|
||||||
|
const int64_t last_ns = g_cas_ps_last_ns.load(std::memory_order_relaxed);
|
||||||
|
if (last_ns < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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 < 500'000'000;
|
||||||
|
}
|
||||||
|
|
||||||
void OnRenderStateUpload(uint64_t mask, uint32_t bank, uint32_t ptr) {
|
void OnRenderStateUpload(uint64_t mask, uint32_t bank, uint32_t ptr) {
|
||||||
(void)mask;
|
(void)mask;
|
||||||
if (ptr == 0) {
|
if (ptr == 0) {
|
||||||
|
|
@ -8468,8 +8485,15 @@ void BuildFrameScene(uint8_t* base, const SubmitRecord* records, size_t count) {
|
||||||
// backdrops always carry world geometry (the pause plaza ~700 items, the
|
// backdrops always carry world geometry (the pause plaza ~700 items, the
|
||||||
// CAS editor room has env-family walls). Skipped publishes also skip the
|
// CAS editor room has env-family walls). Skipped publishes also skip the
|
||||||
// freshness stamp, so the mode never flips.
|
// freshness stamp, so the mode never flips.
|
||||||
|
// CAS-editor exemption: the STARTUP-flow editor's scene is skater-only
|
||||||
|
// (no garage world pre-gameplay: 10 all-char items, exactly a portrait
|
||||||
|
// pass's shape; without the exemption this gate ate it, 3D black
|
||||||
|
// behind a live menu). The editor's _nis shader heartbeat separates the
|
||||||
|
// two: editor draws stamp it every frame, portrait passes use the
|
||||||
|
// _default compiles and never do.
|
||||||
if (rex::graphics::ultrawide_debug::Skate3GameplayContextValue() == 0 &&
|
if (rex::graphics::ultrawide_debug::Skate3GameplayContextValue() == 0 &&
|
||||||
!scene.items.empty() && scene.items.size() <= 48) {
|
!scene.items.empty() && scene.items.size() <= 48 &&
|
||||||
|
!CasEditorHeartbeatFresh()) {
|
||||||
bool all_char = true;
|
bool all_char = true;
|
||||||
for (const DrawItem& it : scene.items) {
|
for (const DrawItem& it : scene.items) {
|
||||||
if (it.char_family == 0) {
|
if (it.char_family == 0) {
|
||||||
|
|
@ -14502,10 +14526,17 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
|
||||||
REXCVAR_GET(skate3_native_render_scene_warmup_budget_ms) > 0 &&
|
REXCVAR_GET(skate3_native_render_scene_warmup_budget_ms) > 0 &&
|
||||||
g_warmup_armed.load(std::memory_order_relaxed)) {
|
g_warmup_armed.load(std::memory_order_relaxed)) {
|
||||||
std::lock_guard<std::mutex> lock(g_scene_mutex);
|
std::lock_guard<std::mutex> lock(g_scene_mutex);
|
||||||
|
// A fresh CAS-editor scene qualifies at ANY size: the startup-flow
|
||||||
|
// editor is skater-only (~10 items, below warmup_min_items) but is a
|
||||||
|
// complete, deliberate scene; holding it rendered the 3D view black
|
||||||
|
// behind the live editor menu. It renders WITHOUT disarming the gate
|
||||||
|
// (see the takeover gate below); real gameplay still needs min_items.
|
||||||
|
const bool fresh =
|
||||||
|
g_scene && g_scene->generation >= g_warmup_fresh_generation;
|
||||||
const bool ready =
|
const bool ready =
|
||||||
g_scene && g_scene->generation >= g_warmup_fresh_generation &&
|
fresh && (g_scene->items.size() >=
|
||||||
g_scene->items.size() >=
|
size_t(REXCVAR_GET(skate3_native_render_scene_warmup_min_items)) ||
|
||||||
size_t(REXCVAR_GET(skate3_native_render_scene_warmup_min_items));
|
(!g_scene->items.empty() && CasEditorHeartbeatFresh()));
|
||||||
loading_native = !ready;
|
loading_native = !ready;
|
||||||
}
|
}
|
||||||
g_loading_hold = loading_native;
|
g_loading_hold = loading_native;
|
||||||
|
|
@ -14609,27 +14640,37 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
|
||||||
if (warmup_ms > 0 && !loading_native &&
|
if (warmup_ms > 0 && !loading_native &&
|
||||||
REXCVAR_GET(skate3_native_render_scene_debug) == 0) {
|
REXCVAR_GET(skate3_native_render_scene_debug) == 0) {
|
||||||
if (g_warmup_armed.load(std::memory_order_relaxed)) {
|
if (g_warmup_armed.load(std::memory_order_relaxed)) {
|
||||||
if (scene.generation < g_warmup_fresh_generation ||
|
const bool small_or_stale =
|
||||||
|
scene.generation < g_warmup_fresh_generation ||
|
||||||
scene.items.size() <
|
scene.items.size() <
|
||||||
size_t(REXCVAR_GET(skate3_native_render_scene_warmup_min_items))) {
|
size_t(REXCVAR_GET(skate3_native_render_scene_warmup_min_items));
|
||||||
|
// A fresh CAS-editor scene renders despite being under min_items (the
|
||||||
|
// startup-flow editor is skater-only, ~10 items), but does NOT count
|
||||||
|
// as the gameplay takeover; the gate stays armed for the real load
|
||||||
|
// that follows the editor.
|
||||||
|
const bool editor_scene = scene.generation >= g_warmup_fresh_generation &&
|
||||||
|
!scene.items.empty() && CasEditorHeartbeatFresh();
|
||||||
|
if (small_or_stale && !editor_scene) {
|
||||||
// Stale or fade-in scene: yield (brief, a few frames). Keep
|
// Stale or fade-in scene: yield (brief, a few frames). Keep
|
||||||
// committing worker results meanwhile; every pre-takeover frame
|
// committing worker results meanwhile; every pre-takeover frame
|
||||||
// counts on map changes.
|
// counts on map changes.
|
||||||
PrewarmCommit(context, frame_number);
|
PrewarmCommit(context, frame_number);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_warmup_armed.store(false, std::memory_order_relaxed);
|
if (!small_or_stale) {
|
||||||
g_settle_until_frame = frame_number + 120;
|
g_warmup_armed.store(false, std::memory_order_relaxed);
|
||||||
size_t queued = 0;
|
g_settle_until_frame = frame_number + 120;
|
||||||
{
|
size_t queued = 0;
|
||||||
std::lock_guard<std::mutex> lock(g_prewarm_mutex);
|
{
|
||||||
queued = g_prewarm_queue.size();
|
std::lock_guard<std::mutex> lock(g_prewarm_mutex);
|
||||||
|
queued = g_prewarm_queue.size();
|
||||||
|
}
|
||||||
|
REXLOG_INFO(
|
||||||
|
"native-scene: taking over natively ({} items; prewarm {} done / {} dropped "
|
||||||
|
"/ {} queued)",
|
||||||
|
scene.items.size(), g_prewarm_done.load(std::memory_order_relaxed),
|
||||||
|
g_prewarm_dropped.load(std::memory_order_relaxed), queued);
|
||||||
}
|
}
|
||||||
REXLOG_INFO(
|
|
||||||
"native-scene: taking over natively ({} items; prewarm {} done / {} dropped "
|
|
||||||
"/ {} queued)",
|
|
||||||
scene.items.size(), g_prewarm_done.load(std::memory_order_relaxed),
|
|
||||||
g_prewarm_dropped.load(std::memory_order_relaxed), queued);
|
|
||||||
}
|
}
|
||||||
settling = frame_number < g_settle_until_frame;
|
settling = frame_number < g_settle_until_frame;
|
||||||
if (settling) {
|
if (settling) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue