mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Set vk_sub_in_frame under the submission lock from the place the submitting thread noted, so a thread about to submit no longer changes it under another thread's replay.
vk_sub_in_frame says which of its frame's submissions the one being recorded is; vk_memory.c sub_place files the mirror pre-snapshot's statistics by it during the replay, on the replaying thread and its workers. vk_be_submit wrote it on every submitting thread before submit_sync, outside sub_lock, so with the replay on the submitting threads another thread entering a submit changed it under a replay in progress, and the replay filed its work at the other submission's place. Each thread now notes the place in a thread-local (vk_be_submit, and replay_main for the asynchronous replay), and vk_sync.c submit publishes it right after taking the lock for a submission with commands (vk_sub_in_frame_publish, a weak no-op without the back end). Submissions without commands of their own (held work, the present thread's blit) leave it as it was, as before. Performance heuristics only; no timing change. Not reproduced before the change. Checks that passed: pass_cc_check on every runtime file (a header changed), no new -Wall -Wextra warnings in vk_backend.c and vk_sync.c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -963,6 +963,9 @@ void vk_gpu_parts_log(uint64_t frame, uint64_t t0, uint64_t t1, double fence_ms)
|
||||
void vk_gtl_note(int kind, uint64_t sub_ns, uint64_t start_tick, uint64_t end_tick);
|
||||
void vk_gtl_log(uint64_t frame, int frames);
|
||||
extern int vk_sub_in_frame; // replay: the submission being recorded is the frame's n-th (0 the first; vk_backend.c)
|
||||
// vk_sync.c submit, sub_lock held, for a submission with commands: vk_sub_in_frame takes the place in its frame the
|
||||
// submitting thread noted for it (vk_backend.c vk_be_submit, replay_main).
|
||||
void vk_sub_in_frame_publish(void);
|
||||
// Runs fn(arg) on the completion thread once fence is done on the GPU (event writes, counter reports, sync state).
|
||||
// Callbacks run in the order they were added, after those of earlier values; a value already done runs at once there.
|
||||
void vk_completion_add(uint64_t fence, void (*fn)(void *), void *arg);
|
||||
|
||||
@@ -634,7 +634,14 @@ static uint64_t submit_sync(const uint64_t *handles, int n) {
|
||||
return f;
|
||||
}
|
||||
|
||||
// vk_sub_in_frame is the replay's: vk_sync.c submit sets it under the submission lock from the place the submitting
|
||||
// thread noted for its submission (vk_sub_in_frame_publish), so another thread about to submit cannot change it under
|
||||
// a replay in progress (vk_memory.c sub_place reads it there and on the replay workers). Submissions without commands
|
||||
// of their own (held work, the present thread's blit) leave it as it was.
|
||||
int vk_sub_in_frame;
|
||||
static _Thread_local int sub_place_next; // this thread's next submission's place in its frame
|
||||
|
||||
void vk_sub_in_frame_publish(void) { vk_sub_in_frame = sub_place_next; }
|
||||
|
||||
static void replay_main(void *arg) {
|
||||
(void)arg;
|
||||
@@ -650,7 +657,7 @@ static void replay_main(void *arg) {
|
||||
plat_cond_broadcast(&rcv);
|
||||
plat_mutex_unlock(&rl);
|
||||
if (it.kind == RI_SUBMIT) {
|
||||
vk_sub_in_frame = sub_idx++;
|
||||
sub_place_next = sub_idx++;
|
||||
uint64_t f = submit_sync(it.h, it.n);
|
||||
if (f != it.value)
|
||||
rt_fatal("vk: replayed submission signalled %llu, queued as %llu", (unsigned long long)f,
|
||||
@@ -933,7 +940,7 @@ static void vk_be_program_release(const prog_t *p) { replay_drain(DR_PROG_RELEAS
|
||||
static uint64_t vk_be_submit(const uint64_t *handles, int n) {
|
||||
vk_lowlat_submit_start(); // a frame's first submission: its simulation is over (nothing while low latency is off)
|
||||
if (!gfx_replay_async()) {
|
||||
vk_sub_in_frame = __atomic_load_n(&nvn_submits_in_frame, __ATOMIC_RELAXED); // the front end counts it up after the submit returns
|
||||
sub_place_next = __atomic_load_n(&nvn_submits_in_frame, __ATOMIC_RELAXED); // counted up after the submit returns
|
||||
return submit_sync(handles, n);
|
||||
}
|
||||
vk_sync_start();
|
||||
|
||||
@@ -1483,6 +1483,7 @@ static uint64_t submit(const uint64_t *handles, int n, const OwnCommands *own) {
|
||||
VkCtx *c = vk_ctx();
|
||||
plat_mutex_lock(&sub_lock);
|
||||
vk_present_frames_owed(); // frames presented while another thread replayed close before this replay begins
|
||||
if (n > 0 && !own) vk_sub_in_frame_publish(); // this submission's place in its frame, for the replay
|
||||
vk_mem_dirty_submit(); // NX2NAVI_TRACE=perf: what a mirror would upload before this submit
|
||||
uint64_t fence = __atomic_load_n(&issued, __ATOMIC_ACQUIRE) + 1;
|
||||
cur_fence = fence;
|
||||
@@ -1581,8 +1582,10 @@ int vk_sync_try_locked(void (*fn)(void)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// vk_backend.c's, which runs the frames' bookkeeping (vk_frame_owed.h); builds without the back end have none.
|
||||
// vk_backend.c's, which run the frames' bookkeeping (vk_frame_owed.h) and set the place in the frame of the submission
|
||||
// being recorded; builds without the back end have neither.
|
||||
WEAK void vk_present_frames_owed(void) {}
|
||||
WEAK void vk_sub_in_frame_publish(void) {}
|
||||
|
||||
// st_lock held: p at the end of the queue *q.
|
||||
static void pending_push(Pending **q, int *head, int *n, int *cap, Pending p) {
|
||||
|
||||
Reference in New Issue
Block a user