Skip to content

puller: decide met semaphore acquires without draining the split's back (stacked on #243) - #956

Draft
robertveloso wants to merge 5 commits into
zortos293:nx2from
robertveloso:perf/acquire-without-drain
Draft

robertveloso wants to merge 5 commits into
zortos293:nx2from
robertveloso:perf/acquire-without-drain

Conversation

@robertveloso

Copy link
Copy Markdown
Contributor

Stacked on #243. The first two commits are #243's (macro DMA reads on the split front without draining the back), rebased onto current nx2. This PR's own changes are the last three commits.

Changes

With the GPU thread split, every Switch 2 semaphore acquire drains the back before reading the semaphore word: ProcessSemaphoreTriggerMethod on the g_nx2_ampere path, and CanResumeAcquire for a parked channel. Most acquires are already met.

In Ocarina of Time on my machine, the front's profile showed about 3,000–5,800 acquire drains a second, taking 170–450 ms of the front's time each second. At that rate the front and back mostly take turns instead of overlapping. The worst case was Hyrule Field, at about 54 ms per frame.

#243's drain-free read of report memory moves into a function, ReadReportWordsQueued, and acquires use it first:

  • How it reads the word: it reads guest memory and puts the queued writes the front knows on top (fence releases, inline uploads), after the queued compute and copy writers ran.
  • Met: the acquire continues without a drain. It notes a sync point (NoteSync), because a drain would have run the work queued before the acquire. A GPU-written command list fetched after it still waits for that work (WaitForSync).
  • Not met, or not readable this way: takes the drained path, as before. Not readable means not report memory, a GPU-written page, or a report or fence write still pending.
  • Verify mode: EDEN_NX2_PERF_VERIFY=1 drains anyway and logs a met acquire that the drained read disagrees with.

The last commit only adds measurement:

  • The profile counts the outcome of each drain-free read.
  • The writer wait those reads make gets its own wait site, acquire writers.

Known gap: a queued draw that writes the semaphore word through a storage buffer isn't seen. That page is only marked GPU-written once the back runs the draw. #243's macro DMA reads have the same limit.

Testing

Machine: Ubuntu 26.04, i5-10400, RTX 3060 (NVIDIA 580.178). Game: Ocarina of Time.

🤖 Generated with Claude Code

tibzejoker and others added 5 commits November 8, 2026 22:11
Reads of report memory (pages 3D reports and semaphore releases write) are
answered on the front from guest memory, with the queued writes the front
knows the words of on top (fence releases, inline uploads), once the back ran
the queued writes it doesn't know that overlap the read. Pages GPU shaders or
copies wrote, counter reports whose host query hasn't completed, and fence
releases the back ran before their host fence signalled take the drained
path, which flushes pending query results (zortos293#215). Queued compute and copy
work is waited for before the page checks.

EDEN_NX2_DMA_READ_CHECK=1 drains, flushes and compares every early read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 7035379)
…known writes

A block-linear upload doesn't write the byte range from its address, and a
linear one only does when every page maps contiguously on the device. Both
now note an unknown write; the inline data reuses the range launch_dma found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 7735da2)
Every Switch 2 semaphore acquire drained the back before reading the word
(Ocarina of Time: ~5,800 a second, ~170 ms of the front's time), and most
are met already. The macro DMA read path already reads report memory as
the back will see it without a drain: guest memory with the queued writes
the front knows on top, after the queued compute and copy writers ran.
That path is now ReadReportWordsQueued, and acquires use it first: one it
shows met continues at once; any other (unknown or not met) takes the
drained path as before. EDEN_NX2_PERF_VERIFY drains anyway and reports a
met acquire the drained read disagrees with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 50f56af)
Review of the previous commit: GPU-written command lists on pages queued
draws wrote are read once the back passed the last sync point
(WaitForSync), and acquires provided one by draining. A met acquire that
skips the drain now notes the sync point instead, so a list fetched after
it still waits for the work queued before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit fb970f0)
The front's profile line gains the outcomes of acquire reads without a
drain (met, not met, not report memory, GPU-written page, pending writes),
and the writer wait those reads make gets its own wait site (acquire
writers) instead of counting as an acquire drain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 1b91ae2)
@coderabbitai

coderabbitai Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Omfgnowai pushed a commit to Omfgnowai/Lichii that referenced this pull request Nov 9, 2026
…quires off by default with bail-out counters

Build-18 runs 12b/12c (Castle Town): EDEN_NX2_EQUAL_ACQUIRE cut drained acquires from
~1.26 M to ~15k per 10 s and frame times from 17-21 to ~17 ms at a 60 cap; its verify
run found 0 acquires passed that a drain doesn't meet. The report-memory read (zortos293#956)
never passed one and waited for the queued writers each time: now EDEN_NX2_REPORT_ACQUIRE=1
turns it on, and the acquire line logs why its reads bail out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTTnurEBDTbs9dv5uKn6x
ThatGuyMcd added a commit to ThatGuyMcd/Lichii-TGM that referenced this pull request Nov 9, 2026
Ports the channel clearing behavior of PR zortos293#615 and the met-acquire sync point guard of PR zortos293#956.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants