Repository navigation
fix(agc): sync a host read on a store recorded after its snapshot check - #8751
Conversation
FlushForAccess checked the pending-write snapshot before it looked for overlapping pending and flushing images. A flusher moves an image the other way: pending, flushing, recorded into the open batch, landed. A reader descheduled after the snapshot check while the store was recorded and the image unregistered found nothing flushing and read guest memory before the recorded copy ran. Sync again when the snapshot overlaps the range after the image checks.
|
Reviewed head |
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed the current head 89f829b5d8356783431796408cf27246422e422e. The final atomic snapshot-overlap recheck appears to close the documented transition from flushing to recorded writes before the reader decides whether to sync. The range-targeted SyncThrough remains intact. The PR reports a forced-delay regression that fails on main and passes repeatedly with the change, plus no-delay runs; eligibility, conventions, intake, labels, and report checks pass. Hosted Linux/Windows and runtime jobs are skipped, so those are not independently validated here.
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
@janzezno thanks, the window you describe matches the order of the checks in A copied buffer's write-back store runs inside Since the race you are fixing is on reader threads, could the new term exclude completion actions, e.g. |
ce84b59 to
89f829b
Compare
|
@oneandonlydean thanks, you're right. A batch's write ranges are republished only by the scope guard at the end of if (stored || published || (completionDepth == 0 && SnapshotOverlaps(address, bytes))) {Inside a completion action the branch is now taken only for a stored or published image, as on |
|
AMD Windows data with the validation layer: with the 5 ms hook delay from the description, Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7, Release, AMD Radeon RX 9070 XT (
The delay line is the one in the description, added after the snapshot block of AI-assisted: yes (Claude Code) |
|
@savvaniss thanks for the Windows/AMD run. It's good to see the forced-delay result hold on a second platform, with no new VUIDs. |
MarcZX10
left a comment
There was a problem hiding this comment.
The latest head incorporates the completion-depth guard suggested in the thread. In the recorded-write case, SyncThrough now runs only for readers (completionDepth == 0), while completion actions retain the previous stored/published behavior; this resolves the reentrancy concern from the preceding review. The PR reports forced-delay red/green results on Linux/RADV and Windows/AMD under validation, with no new VUIDs. Local diff whitespace and conventions pass. I have not run Vulkan tests on this host.
One current-main integration blocker remains: tools/check_main_sync.py --base upstream/main --head <head> reports 2 commits ahead / 1897 behind current upstream/main (merge base eea640a5b), though it merges cleanly. CONTRIBUTING requires branches to be kept up to date. Please merge current main and rerun the focused reader/recorder tests with the validation layer on the resulting head. This request is about integration freshness, not intake volume.
What
A host read now waits for a storage image store that another thread recorded while the read's flush hook was running.
FlushForAccesschecks the recorder's pending-write snapshot first. Only after that does it look for overlapping images, pending (AccessKeptByCpu/FlushPending) or flushing (WaitForFlushing, from #7744's fix). A flusher moves an image the other way: pending, then flushing, then recorded into the open batch (which puts it in the snapshot), then landed. So a reader can miss the store:flushing. The store isn't recorded yet, so the snapshot doesn't overlap, and the reader skips the sync.writeBackrecords the copy into the open batch, andUnregisterremoves the image fromflushing.WaitForFlushingfindsflushingempty and returns false.storedandpublishedstay false, so the finalSyncThroughdoesn't run, and the CPU reads guest memory before the recorded copy has run.The final sync now also runs when the snapshot overlaps the range after the image checks. The reader then checks each state in the order the image goes through them, so an image it doesn't find pending or flushing is either in the snapshot or already landed. When nothing is recorded over the range, the extra cost is one lock-free snapshot lookup.
This is the remaining cause of the
agc_driver_storage_read_during_idle_storeflake. #7984 is related but does not overlap. It makes the idle flusher sync its own unit-shadow publish, but this window is on the reader's side, for a store thatwriteBackrecorded. With #7984 merged and without this change, the forced-delay run below still has 20 of 20 stale reads. The two PRs touch different files.pr_overlap.pycould not compare 13 open PRs that conflict withmainand shareRecorder.cpp, so I checked their diffs by hand. Only #6682 changesFlushForAccess. It changes thewaitedargument passed toPublishShadowsOnlyandFlushPending, in the lines just above the condition this PR changes. It does not change the condition itself. Whichever merges second needs a one-line textual merge; neither changes what the other does. #7464's hunk adds code after the function. The other 11 do not touchFlushForAccess.Tested
Arch Linux, kernel 7.2.11, AMD Radeon RX 7900 GRE (RADV NAVI31), Mesa 26.2.5, GCC 16.2.1, Release,
BUILD_TESTING=ON,maineea640a5b.The window can be forced with a local 5 ms delay after the snapshot block of
FlushForAccess, on threads that do not hold the GPU mutex (the idle thread's own store also goes through the hook). The delay is not part of this PR:recorder->SyncThrough(address, bytes, true); } } + if (const char* delay = std::getenv("APS5_DEBUG_HOOK_DELAY_MS"); delay != nullptr && bytes >= 0x20000 && !GuestMemory::GpuMutex().HeldByThisThread()) std::this_thread::sleep_for(std::chrono::milliseconds(std::atoi(delay)));agc_driver_storage_read_during_idle_store:mainInstrumenting the hook on
mainshowed the failing read takingsnapshot overlaps = 0,images = 0,stored = 0,published = 0after the idle thread's flush ended. With the change, the same read syncs.ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ctest --test-dir build -R 'agc|shader|recompiler|request_serializer' -V:main: 842 of 845 pass. This PR: 842 of 845 pass.agc_driver_guest_memory_lifetime(agc_driver_guest_memory_lifetime fails on RADV since the host-import cut larger-side keep (16473dbbe, #6499 family) #7784),agc_driver_image_array_window_past_layer_limit(test(agc): match array sample expectations to the view #8361),agc_driver_tessellation(Mesa, agc_driver_tessellation segfaults on RADV with Mesa 26.2+: nir_opt_varyings corrupts the TCS input offset's use list (Mesa bug) #5444).VUID-set and counts on both, none new:00118×2,02251×2,02275×6,00605×26,01123×2. Neither log containswas not found but was requested.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)