Repository navigation
fix(shader): read shader cache file times natively on Windows - #12666
oneandonlydean merged 1 commit into
Conversation
The MinGW std::filesystem::last_write_time reads and sets file times through the UCRT stat and utime calls, which convert through local time using TZ. With a TZ other than the Windows zone, including the one libc applies from the guest environment, times shifted by the difference: under TZ=IST-5:30 on an Eastern host a temporary written that second was 9.5 hours old, so housekeeping deleted it, and a TZ west of the host set the active cache stamp hours in the past. Housekeeping now reads times with GetFileAttributesExW, refreshes the stamp with SetFileTime and compares in system_clock. The housekeeping test runs its child with a TZ 12 hours from the host zone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.
|
|
Linux run at this PR's exact head Arch Linux, kernel 7.2.9, Ryzen 9 7950X, g++ (GCC) 16.2.1 20260810, glibc 2.44, x86-64. Release,
On Linux CMake registers only the |
|
@JJenkx reviewed at e2f86a2. The Windows @adriadam10 we'll merge this once our dispatched Windows run of the housekeeping tests is green, unless you'd rather merge it yourself. |
|
@oneandonlydean exact-head Windows run of the housekeeping tests, for the merge bar you set: head
This is my own run, not a dispatched one, so take it as supporting evidence if you still want yours. Edited: an earlier version said AI-assisted: yes (Claude Code). |
|
Independent confirmation from a whole-suite zone sweep on current
Apart from those, the sweep fails only the two tests that also fail without AI-assisted: yes (Claude Code). |
What
On Windows, shader cache housekeeping deletes temporaries that were just written, or misdates its own cache stamp, whenever
TZdiffers from the Windows time zone.Cause: with MinGW,
std::filesystem::last_write_timereads and sets file times through UCRT's_wstat64and_wutime64. These convert through local time usingTZ, so with anyTZother than the Windows zone, a file's time comes back shifted by the difference. A standalone probe on a host set to US Eastern (summer time) measured the age of a file written in the same second:TZEST5EDTUTC0IST-5:30JST-9When
TZdiffers: the user's environment can set it. So can a game: libc'sapplyGuestZonecopies the guest'sTZinto the host process with_putenv_s, and an empty guestTZbecomesUTC0.Housekeeping compares those times with
file_time_type::clock::now(), which isn't shifted:TZeast of the host: a.tmp.file written moments ago looks hours old, and the 1-hour rule deletes it, possibly while another process is still writing it. Directories near the 14-day limit are evicted early.TZwest of the host: the refreshedlast-usedstamp is written hours in the past.agc_shader_cache_housekeeping_plainshows both: onmainit fails underTZ=IST-5:30(FileNotFoundErrorforfresh.tmp.1) and underTZ=AAA+12("active cache stamp was not refreshed"). It passed only because CI and most hosts leaveTZunset.Fix: housekeeping now handles file times itself on Windows:
GetFileAttributesExW, converted tosystem_clock;SetFileTimefromGetSystemTimePreciseAsFileTime;system_clock::now().Other platforms keep
std::filesystem, converted withfile_clock::to_sys, aslibSceSaveData.nativealready does. libkernel'sstatdecodesFILETIMEitself, so guest-visible file times weren't affected.Test: the housekeeping test now runs its child with a
TZ12 hours from the host's offset (AAA+12, orAAA-12when the host is west of UTC). So the shift is exercised on UTC CI machines too.Tested
Windows 11 (US Eastern), Ryzen 9 5950X, WinLibs GCC 15.2.0 UCRT r7, Release,
main3a2b919816.TZforctestmainmain's source with this PR's test, which picksAAA-12plainfails (FileNotFoundErrorforfresh.tmp.1);extended,extended-longanddevicepassIST-5:30,mainas isplainfails the same way, 3 of 3AAA+12,mainas isplainfails: "active cache stamp was not refreshed"UTC0The
extendedanddevicemodes skip eviction for\\?\and\\.\roots, so onlyplainreaches the shifted comparisons.This PR runs all 9
agc_shader_(cache_housekeeping|disk_cache)tests, 3 of 3 each (--repeat until-fail:3):plain,extended,extended-longanddevicehousekeeping, plus the disk-cache tests. A fullctest -j32run onmainunderTZ=IST-5:30found this; its only other failures wereguest_freebsd_clocks(#12660) andguest_pad, which passes 3/3 alone.Conventions pass.
tools/pr_overlap.py: 45 open PRs share files and merge cleanly. Sixteen that touchShaderDiskCache.cppalready conflict withmainand couldn't be compared, so I searched their diffs forhousekeeping,last_write_time,last-usedand.tmp.. Only #6924 matches: it adds alast_write_timecall that orders cache entries by age, which a uniform shift doesn't change, and it doesn't touchhousekeeping().Not tested: Linux and macOS build or run (their branch only adds
file_clock::to_sys, whichlibSceSaveData.nativealready uses); a game run.Follow-up: #12669 fixes the same shift in
libSceSaveData.native, whose fallbackmtimefor a save without stored parameters came fromstd::filesystem::last_write_time.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)🤖 Generated with Claude Code