Repository navigation
Build F: newest Lichii (with Ocarina DLSS) + build D (shader cache change + upstream PR 345) - #6
Merged
Merged
Conversation
… front The split's front drained the back before every native macro DMA read and every semaphore acquire. Games read through MME DMA often (Ocarina of Time, where this was measured: ~20,000 reads a second, ~48% of the front spent draining), so the two GPU threads kept waiting on each other. Applies to every Switch 2 title running on the split. - gpu_split: track queued writes per 64-byte block, plus a barrier position for work whose writes are not tracked by address. A front read waits only until the back has run the last queued work that may write its words. - dma_pusher: classify writers (compute and copy launches, as before) and barriers (host methods and other engines that write memory untracked); command pages already fetched as CPU-written skip the writer wait until the GPU writes them. - maxwell_3d: inline-to-memory uploads, report semaphores and inline constant buffer data note the ranges they write; reads of inline constant buffer words still queued are answered from the front's copy of them. Every 4096th read still drains, and a read of GPU-written memory turns the precise reads off. - puller: skip the back drain for greater-or-equal acquires already met in memory and for acquires the channel's own queued release meets; otherwise wait only for writers of the semaphore. Addresses queued GPU work met 8 times in a row are trusted, and the back checks each skipped acquire and stops trusting an address it finds unmet. - gpu_thread: a GPU release that latches a suspended acquire wakes the GPU thread at once instead of after its 1 ms poll. - EDEN_NX2_MME_DMA_STATS: why reads and acquires waited, barrier sources and GPU thread time spent with channels suspended. Measured in Ocarina of Time (Kokiri Forest, RTX 4060 Ti, Ryzen 9 5950X): ~35.5 -> ~39.3 fps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…are in place Native programs read a 64 KiB uniform bank with indirect offsets, and writes to it can go unnoticed by the memory tracker. nx2 uploaded such a bank again once a frame; games that rewrite per-draw data in it between draws then draw with stale words for a frame now and then (white flashes in Ocarina of Time, where this was measured, Eglantine 031e074). - Check the bank on every bind, comparing each of its pages with a snapshot of its last contents, and mark only the pages that changed as CPU-modified so the normal upload path refreshes them. Unchanged pages keep their tracking (marking costs two mprotect calls per page). - Small uniform buffers within one device page are compared in place instead of being copied to the scratch first; the slot's copy is what gets uploaded, so a later reuse finds exactly the uploaded bytes. - InvalidateGPUCache gathers the CPU-written ranges first so the rasterizer takes each cache's lock once instead of once per range. - EDEN_NX2_MME_DMA_STATS: checked bank pages (same, new, changed, and whether the tracker knew of the change) and page protection counts. The tests now expect page-granular marks instead of a direct upload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… them Builds on Lichii zortos293#215 by WeslieDE (which includes zortos293#204 by vouion): below High GPU accuracy the query cache holds report and semaphore writes until a fence, and a fence runs its callback at once, so macro DMA reads of report memory saw stale occlusion counts (white flashes in Ocarina of Time, where this was found). FlushQueryResults writes the region's reports out and waits for an operation queued behind the pending report writes. Without the split the macro engine flushes this way before its DMA reads. On the split's precise front (previous commits), the flush runs on the back only for reads of pages report_semaphore writes went to, and not for reads answered from queued inline constant buffer words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the split front In ShadowRamControl::Replay the back writes the shadow RAM values, not the method arguments, so the front's cb_shadow copy of those words was wrong. Note such writes as opaque and keep them out of cb_shadow: macro DMA reads of them wait for the back. Covers single and multi method writes. Reported by CodeRabbit on zortos293#345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A command fetch from a page first fetched as a CPU-written list skipped the wait for queued compute and copy work. Nothing guarantees that such work can't write that page before the back runs it, so the front could parse stale words (Ocarina rewrites 28 such pages while loading). Command fetches wait for queued writers again, as on nx2. This costs ~2-3 ms per frame in Kokiri Forest. Reported by CodeRabbit on zortos293#345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…PU-written DMA sources From CodeRabbit's review of zortos293#345: - Queued writes and report pages are keyed by device address, so a write and a macro DMA read through different GPU addresses of the same memory meet. - Past 4096 report pages, every macro DMA read flushes pending query reports instead of missing the new pages. - A precise macro DMA read of pages the GPU has written lets the back check the buffer cache and download newer data first; waiting for the back alone left it in a host buffer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te can change the value The greater-or-equal fast paths (SEM_ACQUIRE and SEM_EXECUTE) assumed releases only raise the value. A queued release can lower it, and GPU-written data may still be in the buffer cache, so they now also require that no tracked write to the semaphore is queued and that its page is not GPU-written. Reported by CodeRabbit on zortos293#345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WaitForWriters returns false when the writers have already finished, which skipped the recheck: a writer that marked the pages after the first check left the fetch on an old submitted snapshot. Reported by CodeRabbit on zortos293#345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ew of zortos293#345) - Drop learned acquires: an acquire that queued work may meet now waits for it. Skipping it on past successes let the commands after an unmet acquire run. - StableSemaphore also waits for queued compute and copy work. - A channel's own queued release meets an acquire only if no later write to the word is queued, and not at High GPU accuracy (releases land at fence time). - Key the constant buffer shadow by device address, like the write tracking, and keep only the words ProcessCBMultiData writes within the buffer size. - Track report pages globally: the front marks the 3D reports it queues, the back marks every report left pending in the query cache (any engine or channel), instead of a per-channel list capped at 4096 pages. - Bound the FlushQueryResults wait to 2 s with state the callback shares. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps nx2's OnCacheInvalidations (it claims CPU writes first, zortos293#397) in place of this branch's batched version, and the bounded query flush wait of cc808c1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MSVC 14.51 treats C4456/C4457/C4458 as errors: the stats loop in Maxwell3D's macro DMA read reused 'source' and 'count', and Query's 'device' hid RasterizerVulkan::device. No behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… pending Report pages stayed marked for the whole session, so nearly every read of them drained the back to flush the query cache: madebyjordan counted only 540 of 2.08 million such reads with a pending result in the words read. The query cache now counts, per 16-byte slot hash, the reports it registers and the results it writes out, as in Lichii zortos293#243 by tibzejoker. The front flushes only when the counts differ for the words read. The wait before it has already run the queued reports the read may see, so the back has registered them. The page bitmap is gone. EDEN_NX2_MME_DMA_STATS also reports how many reads flushed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nels Each channel kept its own copy, so a word uploaded by one channel and then by another could be served with the first value. The copy now lives in GpuSplit, keyed by device address, and the last upload of a word wins whichever channel sent it. Reported by CodeRabbit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GCC 13.3 at -O3 unswitches the per-word loop of FrontCallMultiMethod on the switch that zortos293#178 inlined into it. The loop that the other methods take then has no case for the macro upload methods: load_mme.instruction never reaches AddCode, the front's macro RAM stays empty, and every Turing macro fails with "instruction outside uploaded RAM" (black screen at boot in Ocarina of Time). In the object file the function has no AddCode or ClearCode call left; with the helper kept out of line both are back. MSVC and clang builds are not affected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s branch boot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aphores on the split front (review of zortos293#345) - A draw that writes a storage or texture buffer makes the front count the draws before the next wait for idle as writers, so macro DMA reads after it wait for them. Nothing changes while no draw writes memory. - Each split stop starts a new epoch; a channel's queued releases from an earlier one are dropped instead of meeting acquires. - An acquire met after its wait is accepted only if its page is not GPU-written; otherwise the drain path flushes the word first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the split front The flag that enabled this was set by the back when it bound a written storage or texture buffer, so the front could pass the wait for idle after the first writing draw before the back had seen it, and a following macro DMA read could miss its writes (CodeRabbit on zortos293#345). Track draws unconditionally instead, from draw.begin: in an instance loop the front skips draw.end and the back defers the draw until the wait for idle flushes it. Tests cover a plain and a deferred instanced draw before a wait for idle, host syncs, and a macro read position waiting for a stalled back. Ocarina of Time in Kokiri village: macro DMA reads that wait for writers stay at the 313 from boot, fps unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…records - EvictUnusedPipelines only evicts while more than 8,000 graphics pipelines are cached, and then the longest unused ones a draw has used, down to 7/8 of the limit (EDEN_NX2_PIPELINE_EVICT_ABOVE; 0 restores the old behavior). Prebuilt pipelines no draw has used keep zortos293#550's budget. Ocarina of Time evicted 6,182 pipelines in a 37 min session (~1,000-2,400 cached at a time) and draws waited 230 s in all for pipelines being built again. - The first boot copies the cache version 53 records beside this version's (vulkan_import, loaded after it) and merges the v53 used-pipeline list, so pipelines a v53 build used are built at boot again. The records are the same format: zortos293#432 bumped the version only for the SPIR-V it emits, and every record is translated again when it loads. The v53 files are left as they are. Skipping draws on unbuilt pipelines is left to zortos293#465's native_async_draws setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LTxNSeWfimx1VbMuL9DgoN
Test build D: merge the oot-split-front-and-flashes branch into oot-shader-345
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Build F for Ocarina of Time testing: Lichii's newest nx2 (b7ff181, which includes upstream PR 606, NVIDIA DLSS for Ocarina of Time) plus build D (branch oot-shader-345): build C's shader cache change (a49a1a3) and upstream PR 345 (head 09f3c7a).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Fp7Vt3eYkQsGicwZZK3hFa