Repository navigation
core: give each DeviceMemoryManager its own translation generations - #984
Conversation
The per-thread translation cache (06f294c) belongs to a manager when both its owner pointer and the generation match. Every manager started at generation 1 and bumped it once per Map or Unmap, so a manager built where a destroyed one was, after as many Map and Unmap calls, matched the translations a thread had kept for the old one and read through their host pointers into freed memory. The buffer_cache_ports read download cases hit this: each Fixture builds its MaxwellDeviceMemoryManager in the same stack slot and maps the same way, so in some random orders a case read the previous case's guest memory (13 of 44 [buffer_ports] cases failed with --rng-seed 1, every one passed alone). The emulator can hit it too when a game is relaunched in the same process and a thread that outlives the session reads device memory again. Each manager now starts its generations 2^32 past the previous one's. MemoryManager's MapSerial() + TranslationGeneration() still changes on every Map and Unmap. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
Merge origin/nx2 without replacing the complete zortos293#805 split with its partial ports. Conflicting areas are resolved as follows: - gpu_split.{h,cpp}, dma_pusher.{h,cpp}, gpu_thread.cpp, engines/maxwell_3d.cpp, engines/kepler_compute.{h,cpp}, engines/maxwell_dma.h and their fast-method tests retain zortos293#805's write classification, QMD/front view, position waits, tick/idle hooks, fast method path and sampled method timing. Do not import zortos293#949's reduced acquire table, back_quiet drain scheme or duplicate zortos293#1028 write tracking. Keep the independent scheduler-owner check on CPU/service writes, the new RingFull drain site and opt-in live-read comparisons. - engines/puller.{h,cpp}, nx2.h and query_cache.h combine zortos293#805's authoritative front semaphore view and source-tracking unbounded waiters with zortos293#979/zortos293#1014's unbounded region table and direct-release shadow. Mirror releases only when ViewApplies is false: unsplit, back macros, or delayed/high-accuracy releases. The full front view must not consume a second mirrored counter absent from its original releases. Note both destination writes on the fallback path. Compute max/reduction releases retain shadow combination and zortos293#805 checks. Keep zortos293#874's synced payload handling and FencedPayloadLanding: synced callbacks never advance fenced_landed. - gpu.cpp, rasterizer_download_area.h, rasterizer_interface.h, memory_manager.cpp, buffer_cache.{h,base.h}, vk_buffer_cache.{h,cpp}, vk_rasterizer.{h,cpp} and buffer_cache_ports keep the full zortos293#805 read-back, upload ordering and tracing. Bring in zortos293#1028's review fixes: ClearDownload lands reads before DMA/discard writes, ClearReplacedDownload cancels only bytes reaching guest memory, and pending query results leave newer GPU writes dirty. Retain the new regression cases and the Qt-safe MayHoldGpuWrites boundary. Drop the unused reduced nx2_async_readback diagnostic implementation instead of duplicating zortos293#805's richer GPU-wait/read traces. - device_memory_manager.h/inc use zortos293#984's per-manager generation ranges with Map/Unmap increments and preserve DownloadLanding/write tracking. - nx2_profile.h and video_core.cpp combine zortos293#805's fine counters, sampling, scope depth and runtime switch setup with zortos293#965/zortos293#1039's zone-parent tracking, GPU waits, contention, worker/present/submit zones and stutter sites. - vk_pipeline_cache.cpp takes zortos293#1036's v2 cache, migration, jobs, parallel translation and emission. shader_environment.{h,cpp} keeps zortos293#970's unsafe TIC reads; also omit v2's new pool-wide pretranslation flush, since workers no longer flush descriptors. Keep the AMD e0a992208d87eeb8 exception in pipeline_optimization.h. - vk_graphics_pipeline.cpp, uniform_stream_reuse.h, sampled_views.h and tests converge zortos293#921/zortos293#949 with the adapted branch ports. PrepareImageView uses the single PreparesImage predicate, including valid views of NULL_IMAGE_ID. Keep uniform/descriptor delta replay, zortos293#974 fast-draw checks, zortos293#805 profiling and the empty-descriptor-range guard; no parallel duplicate paths. - vulkan_device.cpp and vulkan_memory_allocator.cpp combine cache-v2 device support and zortos293#880's backable-image failure policy with zortos293#836's synchronized recycler and zortos293#831's 50 ms memory-usage cache. Preserve all remaining branch AMD, query, shader, texture and fast-draw changes in the automatic merges. - nx2_video_decoder.cpp takes nx2's final dav1d/default-thread state. CMake test lists combine both sides; keep zortos293#805 fast-method tests rather than tests of rejected reduced split internals, and adapt waiter tests to >64 owners. Other matching cherry-picks converge to nx2; NX archives, HostTiming, memory/stutter/cache tooling and their sources are retained. Validation before commit: git diff --cached --check passed; 30 cache_metrics and cache_bench Python unit tests passed using workspace-local test data. The requested clang-cl ThinLTO/PGO build is in progress. BUILD_TESTING is OFF; C++ tests and in-game semaphore/read-back/cache/fast-draw validation remain separate. No emulator launched or stopped; no push or other branch changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ortos293#984) The per-thread translation cache (06f294c) belongs to a manager when both its owner pointer and the generation match. Every manager started at generation 1 and bumped it once per Map or Unmap, so a manager built where a destroyed one was, after as many Map and Unmap calls, matched the translations a thread had kept for the old one and read through their host pointers into freed memory. The buffer_cache_ports read download cases hit this: each Fixture builds its MaxwellDeviceMemoryManager in the same stack slot and maps the same way, so in some random orders a case read the previous case's guest memory (13 of 44 [buffer_ports] cases failed with --rng-seed 1, every one passed alone). The emulator can hit it too when a game is relaunched in the same process and a thread that outlives the session reads device memory again. Each manager now starts its generations 2^32 past the previous one's. MemoryManager's MapSerial() + TranslationGeneration() still changes on every Map and Unmap. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Every
DeviceMemoryManagerstarted its translation generation at 1 and bumped it on each Map and Unmap. The per-thread translation cache (06f294c) trusts an entry when the owner pointer and the generation both match. So a manager constructed at the address of a destroyed one, after the same number of Map and Unmap calls, matched translations a thread had kept for the old manager, and read through their host pointers into freed memory.Each manager now starts 2^32 generations past the previous one's. Map and Unmap still bump it, so
MapSerial()+TranslationGeneration()changes exactly as before. Nothing else changes.How it was found: while porting the async read-back tests from #805 (EGLA-91). The
[buffer_ports]fixtures build their manager in the same stack slot and map the same way, so with--rng-seed 113 of 44 cases read the previous case's guest memory. Each one passed when run alone, and all pass with this change, across seeds 1–12 and in declaration order. In the emulator, the same pattern needs a game relaunched in the same process while a thread that outlives the session reads device memory again. That's plausible, but nobody has seen it happen in a game. upstream/nx2 has the same code.Checks: GCC 13 builds
core/memory,video_core/gpu,memory_managerandgpu_device_memory_manager. The aarch64-fsyntax-onlycheck passes oncore/memory,gpuandmemory_manager. The tests that reproduce the failure are only on the async read-back branch, which isn't on nx2 yet, so this PR adds no test of its own.Summary by CodeRabbit