From effdbd8dc0178c5eebdabcf0eb803c5d04c95a11 Mon Sep 17 00:00:00 2001 From: chrg6 Date: Fri, 13 Nov 2026 19:13:23 -0500 Subject: [PATCH] Describe in docs/architecture.md how the game's submitting threads take turns, and bring nvn_call_note's comment, which said the front end relied on one thread at a time, up to date. The submit path no longer relies on one guest thread at a time: replays take turns on the submission lock, a frame's bookkeeping at its present runs between two replays (vk_frame_owed.h), a held present goes out once and in order (vk_present_held.h), a second submission of a recording in flight gets a clone (nvn_submit_guard.h), and held work is asked about from a published copy (vk_evo_peek.h). docs/architecture.md section 4 gets a bullet saying so, with the switch and the log lines; the comment above nvn_api_core.c nvn_call_note now says what holds and that an overlap line is a count, not a fault. Checks that passed: pass_cc_check of nvn_api_core.c. Co-Authored-By: Claude Opus 5.5 --- docs/architecture.md | 10 ++++++++++ runtime/nvn_api_core.c | 8 +++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index c3ce1c96..0b0a2e08 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -91,6 +91,16 @@ keeps per-core data without locks and relies on that, so the host models it (`ru queues"); a CPU signal counts for a submission only when it came before the copies above were taken, and a submission it comes too late for goes on at once in one of its own (`vk_exec_xfer.c`, "events the CPU signals"). `NX2NAVI_EVO_TRACE=1` logs the order every frame was replayed in. +- Several submitting threads. The game submits from several threads and presents from one of them. Their replays take + turns on the submission lock (`vk_sync.c`). The state a present closes for the frame (the DLSS state, the motion + tables, the frame count conditional draws go by) is reset between two replays: by the present when the lock is free, + else first thing in the next submission (`vk_frame_owed.h`, `NX2NAVI_PRESENT_ORDER`). A present held for + event-ordered work is put out once and in order by whichever thread's submission finds its work done + (`vk_present_held.h`); submitting threads only try its lock, and the presenting thread waits for it only while + another thread puts a held present out. A recording two threads submit at once gets a copy of its own for the + second, for its deferred binds (`nvn_submit_guard.h`). Held work is asked about without the lock from a published + copy (`vk_evo_peek.h`). The log counts the overlaps with `NX2NAVI_TRACE=perf` ("enters a submit ... while"), and at + exit what they cost ("frame bookkeeping: ..."). - Driver data. The NVN driver keeps a per-stage constant bank (c0). The back end fills it as the driver does: storage and uniform tables, push constants and, for NVN 2 compute, the dispatch's group counts in bytes 0-0xb. - Storage buffers the shaders reach through pointer tables in memory are bound at the address the table holds diff --git a/runtime/nvn_api_core.c b/runtime/nvn_api_core.c index d0ed2d92..fa85ccb9 100644 --- a/runtime/nvn_api_core.c +++ b/runtime/nvn_api_core.c @@ -710,9 +710,11 @@ static uint64_t lod_entered, lod_issued, lod_fence[LOD_RING]; // core given up (section 2.2), or queued for the replay thread (NX2NAVI_REPLAY_ASYNC, vk_backend.c); the newest fence // value is what QueueFenceSync records. With the queue the fence covers replay and GPU, so the LOD guard below waits // for both. -// NX2NAVI_TRACE=perf (nvn_api.h): which threads submit and present, and whether two of these calls run at once. The -// synchronous replay's front end (vk_backend.c submit_sync, vk_be_present's held present, nvn_submits_in_frame) takes -// no lock of its own, so it relies on one thread at a time; this tells a run whether that holds. +// NX2NAVI_TRACE=perf (nvn_api.h): which threads submit and present, and whether two of these calls run at once, which +// happens in play (at area changes). With the replay on the submitting threads they take turns where it matters: +// replays on the submission lock (vk_sync.c sub_lock), a frame's bookkeeping at its present between two replays +// (vk_frame_owed.h), a held present put out by one thread and in order (vk_present_held.h), and a second submission of +// a recording in flight on a clone of its own (nvn_submit_guard.h). An overlap line counts; it is not a fault. void nvn_call_note(int present, uintptr_t q, int enter) { if (!(rt_trace & RT_TRACE_PERF)) return; static volatile int32_t inside;