Repository navigation
Conversation
|
@parl0v an overlap note from #8887, which rewrites the same What each changes
Where the two collide (merge-tree of 02aebc8 against 017123e; #9400 is clean against
Combined behaviour
Data on offer. In 007 First Light (PPSA11386) on Linux/NVIDIA, the draw committer waits for the GPU mutex behind the async queues' dispatch and indirect holds, with fence waits in AI-assisted: yes (Claude Code) |
|
@SleglJan thanks, that's a precise map of the collision. I agree with the carry: if #8887 lands first, I'll rebase this onto it, wrap your two calls with the counters, and have Yes please on the 007 First Light runs, #9400 alone and with #8887. A second title is exactly what this PR is missing; MCD2 is the only one I've measured. The |
|
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.
|
MarcZX10
left a comment
There was a problem hiding this comment.
The proposed move of storage-writer waits into pre-sync is well motivated and the PR has unusually thorough evidence: paired validation-layer runs on the same RTX 4060 show 10/10 baseline tests and 11/11 on the change with no VUIDs, and the title traces and measurement limits are described clearly. The mock regression also checks the open-batch, in-flight, and no-writer cases. git diff --check passes and the current head merges cleanly with main.
I’m requesting changes for the remaining repository requirements:
- The latest paired validation runs are on
main0c6a5bd59; currentmainis4a17c71757. Please rebase onto currentmainand rerun the same focused tests on both trees with the required validation-layer settings and VUID comparison. The gameplay and title-screen performance comparisons were measured on older base36f60df9e; refresh the summaries and traces against current main as well. - The current overlap scan identifies open #7307 in the recorder wait/completion path and open #8887 in
StorageTexture::FlushPending, which both intersect this PR’s new writer-wait attribution and pre-sync behavior. Please coordinate with their authors on sequencing and integration, and updateDepends on:if either needs to land first. The scan also identifies shared texture/header and documentation lines; refresh it after rebasing and manually resolve actual overlaps. #7769 is already merged, so that earlier relationship is now part of main.
No local AGC test or GPU run was possible in this review environment. Hosted eligibility, conventions, intake, labels, and report checks pass; product build/test jobs are skipped. The existing older-base results are strong but do not satisfy current-main validation for this head.
|
@parl0v the 007 First Light runs you asked for, #9400 alone and with #8887. Setup. 007 First Light (PPSA11386, content 01.018.000), Linux 7.2.10 (CachyOS), RTX 3080 10 GB, driver 615.78.08, Ryzen 9 7950X3D, Release builds, 3840x2160, warm shader cache (the same seed cache copied before every run), default VRAM headroom.
11 runs: P1 W1 WR1 P2 W2 WR2 P3 W3 WR3 alternated, then P4 and W4 later the same day (not alternated). P3 and W3 are left out because the storage image cache budget reached its 512 MiB floor at or after present 1400: P3 from present 1567 (its last ~13 presents), W3 from 1452; over its window W3 waited 1,100 ms per present for pipeline room, at a frame p50 of 3,787 ms, and hit the 1,200 s limit at 1573. P3 carries neither PR. Of the runs shown, P2 and W2 ran most of the window with that budget lowered to about 1,000-1,500 MiB, falling to 681 and 685 MiB near the stop; the other seven stayed at 1,757-2,197 MiB, apart from one 876 MiB line in P1 near present 1405. P2 and W2 are their arms' slowest runs. Per present over the window (sums of the 10 s or longer lines inside the window, divided by its presents; pre-syncs and
The arms' ranges overlap in every row but the pre-syncs (arm means: frame time 1,264 / 1,313 / 1,397 ms, room wait 285 / 332 / 256 ms). WR's pre-syncs waited 30.8-32.9 ms per present against 24.2-28.3 in P and W, in all three runs.
So in W, 94-120 writer-only pre-syncs per window stand against 8,475-9,961 writer waits in AI-assisted: yes (Claude Code) |
02aebc8 to
114c160
Compare
|
@MarcZX10 rebased onto
@SleglJan thanks for the 007 runs. They match what I see: in your windows the writer-only pre-syncs (94-120) are a small slice of the 8,475-9,961 locked |
|
Data from Astro's Playroom (PPSA01325) with #9400 (114c160) and #8887 (017123e) merged together, in case it helps the review. Base: #9508's head (5547aa1),
About +3.5%, with the window ranges not overlapping. A profiled run ( |
|
@Raghav314 thanks for the Astro's Playroom runs. Your |
adriadam10
left a comment
There was a problem hiding this comment.
main moved again (e7f46f5) and the branch now conflicts in Texture.hpp (next to the idle-image reclaim from 3bcd89e) and ARCHITECTURE.md. The logic is untouched; a rebase is needed.
Still open from the CHANGES_REQUESTED review, which is what blocks the merge queue:
- Validation-layer comparison on current
mainand on this change:ctest -V -R "agc_driver_(storage|dcc|presync|flush)"with the settings from CONTRIBUTING, the VUID count of both logs, and the missing-layer check. The 10-22 runs are on e5c5329. - Title and gameplay summaries refreshed against that same
main.
#7307 and #8887 are already sequenced in the thread, so nothing else is needed there. Once the rebased head and the runs are posted, MarcZX10's re-review can clear the CHANGES_REQUESTED.
…the GPU mutex A cached dispatch's Revalidate refreshes the storage images it binds (StorageTexture::Refresh). When another image has results pending over one of them, the refresh's FlushPending waits with the GPU mutex held for the newest batch that writes or leases that memory: an address-based dispatch's write marks must land before the store chooses the blocks it keeps. At the Minecraft Dungeons II title this wait held the mutex about 900 ms per 10 s on queue 0x20 (RTX 3060), about half of it a Sync of the open batch and half a FinishUpTo of a batch in flight. For an object from the resource cache, PresyncSurfaces now also lists the memory of every storage image it binds, of the image each of its sampled views reads, and of its imported regions (PresyncSurface::writerOnly). presync waits for such a range only when another image has a pending unit inside it (StorageTexture::OthersPendingInside: FlushPending's listing without an image of exactly that surface, taken without the GPU mutex) and, under the mutex it takes for a moment, recorded work writes or leases it (PendingWriterSerial, the test FlushPending makes before it waits). The dispatch reaps that batch before Revalidate, so the locked FlushPending finds no writer. Work recorded after the pre-sync falls back to the locked wait as before. APS5_NO_WRITER_PRESYNC=1 leaves the ranges out. The [presync] line counts the writer ranges checked and the pre-syncs that only a writer required; a [flushwait] line counts FlushPending's writer waits by open batch or batch in flight and by lease only or write, with their time and how many ran inside a caller's hold of the mutex. FinishUpTo takes the sync source, so FlushPending's drain of a batch in flight counts as a pending-write or address-based sync instead of idle. The test agc_driver_storage_presync_writer covers the locked wait, a writer in the open batch and in flight, and a pending image without a writer, and skips with the reason check_skips.py expects when the device has no timeline semaphores.
114c160 to
4d578a4
Compare
|
@adriadam10 @MarcZX10 rebased onto On that Title and gameplay summaries on the same |
|
I tried this on Ghost of Yōtei (PPSA26344 v1.008) in the open world, on our own tree rather than The 60-frame title check is bit-identical with it, and your tests pass on Windows. I made Per-phase means (A = pre-sync on, B = APS5_NO_WRITER_PRESYNC=1) |
|
Closing this one. Thanks @Celegans12, @Raghav314 and @SleglJan for running it on titles I can't, and @MarcZX10 and @adriadam10 for the reviews. What the runs add up to:
A few percent on one title screen against a measured regression in an open world isn't a trade I'd ask anyone to merge. If it comes back, it should wait only where the locked wait would otherwise have run under a caller's hold, and @SleglJan's per-call-site split of |
What
A dispatch served from the resource cache revalidates its object under the GPU mutex, and
Revalidaterefreshes the storage images it binds (StorageTexture::Refresh). When another image has results pending in that memory, the refresh'sFlushPendingfirst waits for the newest batch that writes or leases the memory, so an address-based dispatch's write marks land before the store chooses which blocks to keep (#6364). That wait is aSyncof the open batch or aFinishUpToof a batch in flight, both with the GPU mutex held, and the other queue workers wait behind it.This change moves that wait into the stage-A pre-sync (
VulkanDevice::presync), which already waits without the mutex for surfaces and, since #6631, for DCC key writers:ShaderResources::PresyncSurfacesalso lists the memory of every storage image it binds, of the image each of its sampled views reads, and of its imported regions (PresyncSurface::writerOnly), whether or not a host import serves them.presyncwaits for such a range only when another image has a pending unit inside it (StorageTexture::OthersPendingInside: the listingFlushPendingmakes, without an image of exactly that surface, which is the refreshed image itself or its alias; lock-free through the registry's published ranges when nothing pending overlaps) and, in the short locked section it already takes, recorded work writes or leases the range (Recorder::PendingWriterSerial, the testFlushPendingmakes before it waits). If that batch is the open one it is submitted; the wait itself runs without the mutex, and the dispatch reaps the batch beforeRevalidate, so the lockedFlushPendingfinds no writer.APS5_NO_WRITER_PRESYNC=1leaves the new ranges out (row inENVIRONMENT.md);APS5_NO_PRESYNC=1still disables the whole pre-sync.Counters, printed with
APS5_PROFILE_DRAW=1on the existing 10 s cadence: the[presync]line adds the writer ranges checked and the pre-syncs that only a writer required, and a new[flushwait]line countsFlushPending's writer waits by open batch or batch in flight and by lease only or write, with their time and how many ran inside a caller's hold of the mutex.FinishUpTonow takes the sync source, soFlushPending's drain of a batch in flight shows up in the[recorder]site table as a pending-write or address-based sync instead of "idle".Test:
agc_driver_storage_presync_writercaches a dispatch that stores into storage image B, leaves image A pending over B, then records an address-based global store over A. A dispatch built under the mutex waits once for that store under the mutex (the control case). AfterPrepareDispatchthe pre-sync has waited for it, with the store in the open batch and with it in flight, and the locked dispatch does not wait again. A pending image that no recorded work writes or leases makes neither wait. The data checks are the ones fromStorageFlushOrdering: the pending image's texel outside B is stored, and the newer address-based store is not overwritten.ARCHITECTURE.md's pre-sync paragraph describes the new ranges.Why
On
main64e2a81, at the Minecraft Dungeons II (PPSA16064) title screen on an RTX 3060, queue 0x20 held the GPU mutex in this wait for about 900 ms per 10 s: about 460 ms as aSyncof the open batch and about 440 ms as aFinishUpToof a batch in flight, which the[recorder]site table listed as "idle". The path is a resource-cache hit,Revalidate, the storage image lookup,StorageTexture::RefreshandFlushPending(..., "storage refresh"). The wait itself is needed, so this change moves it out of the lock instead of removing it.The title screen is GPU-bound (GPU busy about 92 ms per present at a 111 ms frame p50 on the RTX 3060), so the same move changes its frame time by 0.8 % against
main36f60df and by about 3 % againstmaine5c5329. Gameplay is bound by the queue workers: in themaintrace below, queue worker 0x0 is 99.7 % busy and the GPU is busy 140.7 ms of a 669.5 ms frame p50, so worker time that no longer goes to locked waits can become frames there.Measured
Refreshed on current
main(2026-10-24). This branch at 4d578a4 againstmain5d3ab77, built the same way (Release, same toolchain), MCD2 relinked with thatmain's relinker. All on the RTX 4060 8 GB (NVIDIA 617.42), Windows 10 19045, i5-14400F; my RTX 3060 machine was not available.APS5_TEXTURE_CACHE_MIB=3072 APS5_TRACE_SECONDS=120:12): frame p50 123.6 and 121.2 ms onmain, 118.3 and 117.9 ms with this change (-4.3 % and -2.7 %, ahead in both pairs). The mean frame moves -2.7 % in the first pair and +0.3 % in the second, so I read the title gain as a few percent on the median, not on every frame. UnlockedRecorder.WaitSerialgrows from 29.5 / 29.3 to 53.0 / 60.3 ms per frame, the wait leaving the lock.APS5_TRACE_SECONDS=105:12; the load got shorter on thismain, so the earlier 85 s window now lands on the load): frame p50 324.5 ms (34 presents) onmainand 565.7 ms (23 presents) with this change, so this pair favoursmain. I don't attribute it to the change: over this change's window its writer-only pre-sync counter stayed at 1,967, so the pre-sync did not fire in gameplay, while the two rows ran with different storage image cache budgets (1,361 MiB onmain, 899 MiB with this change, set from the reported heap usage) and this change's row created 18,700 storage images against 8,450. That budget moves between runs of the same build (512 to 1,614 MiB onmainacross my rows this week) and decides gameplay frame time on this card far more than this change does; on 2026-10-22 the gameplay pair went the other way (588 against 439 ms).mainstopped twice in the menu before this capture atstoring storage image results pending over memory outside the write watch without the guest bytes saved before them is not implemented(fix(agc): save the guest bytes of results that become pending over a surface that is no longer fully write-watched #7048 covers it).Summary lines, 2026-10-24
tools/performance_compare.py, title screen pair 1, 2026-10-24
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
tools/performance_compare.py, title screen pair 2, 2026-10-24
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
tools/performance_compare.py, gameplay, 2026-10-24
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
Traces from 2026-10-24: https://github.com/parl0v/AnyPS5/releases/tag/perf-traces-2026-10-24 (title screen
aps5-trace-5d3ab7791dc4-18548.json.gz/aps5-trace-4d578a4df71c-5920.json.gzandaps5-trace-5d3ab7791dc4-19204.json.gz/aps5-trace-4d578a4df71c-18624.json.gz, gameplayaps5-trace-5d3ab7791dc4-16984.json.gz/aps5-trace-4d578a4df71c-10812.json.gz).Earlier, on
maine5c5329 (2026-10-22). This branch at 114c160 againstmaine5c5329, built the same way (Release, same toolchain), MCD2 relinked with thatmain's relinker.APS5_PROFILE_DRAW=1 APS5_PROFILE_GPU=1, FPS over the last ten 10 s windows:main10.50, 10.52, 10.50; this change 10.81, 10.82 (+3.0 %, ahead in both complete rounds; GPU busy 78 ms per present on both, GPU idle gaps 18 ms onmainand 15 ms with this change). This change's third row stopped about 20 s in atstoring storage image results pending over memory outside the write watch without the guest bytes saved before them is not implemented;maine5c5329 stopped at the same check in one of my gameplay rows on the RTX 4060 today (fix(agc): save the guest bytes of results that become pending over a surface that is no longer fully write-watched #7048 covers it).APS5_TRACE_SECONDS=120:12: frame p50 91.9 ms onmainand 88.4 ms with this change (-3.8 %), p90 104.0 and 104.0 ms. The time queue workers spent waiting for the GPU mutex (Driver.Packet.device_lock) fell from 32.6 to 19.4 ms per frame, and 40.5 ms per frame of unlockedRecorder.WaitSerialappears in its place.APS5_TRACE_SECONDS=85:12): frame p50 588.1 ms (21 presents) onmainand 438.7 ms (28 presents) with this change. I don't attribute that to this change: over this window the counter of pre-syncs only a storage refresh's writer required stayed at 1,558, so the writer pre-sync did not fire there, and the difference is within what scene and run variance gave me before. My untraced gameplay rows on this base were too short and too often stopped by crashes onmainand on this change alike (a game access violation, and the check above) to compare.Summary lines, 2026-10-22
tools/performance_compare.py, title screen, 2026-10-22
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
tools/performance_compare.py, gameplay, 2026-10-22
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
Traces from 2026-10-22: https://github.com/parl0v/AnyPS5/releases/tag/perf-traces-2026-10-22 (title screen
aps5-trace-e5c5329251d0-8084.json.gzandaps5-trace-114c1604ccbd-1748.json.gz, gameplayaps5-trace-e5c5329251d0-25748.json.gzandaps5-trace-114c1604ccbd-18792.json.gz).Earlier measurements, base 36f60df. In short, on that base: title screen +0.8 %, gameplay +4-12 % across sessions. Every number below was measured at 96c7091cd, the same change on base 36f60df. The rebase onto current
mainchanged none of its lines: the two conflicts were context only,WaitForFlushingfrom #7769 next to the newWriterWaitCountsinTexture.cpp, and a neighbouringARCHITECTURE.mdline.Gameplay. RTX 4060 8 GB (NVIDIA 617.42), Windows 10 19045, PPSA16064 01.100.100, a saved game and a scripted walk, automatic texture budgets,
main36f60df against this change at 96c7091cd. Ten rounds over two sessions, the two builds alternating; FPS is the mean of the gameplay 10 s windows of a row.main36f60dfThe change is ahead in 7 rounds, tied in 2 and behind in 1. Welch's t 1.89; a one-sided permutation test over the 184,756 splits of the 20 rows gives p = 0.039. The gain is +22 % in session 1 and +4.3 % in session 2. The change stayed at 1.82 and 1.81 FPS;
mainmoved from 1.48 to 1.74 between the sessions, so I read the effect as somewhere in that range, not as the pooled 12.6 %.In the last five gameplay windows of each session-1 row, with
APS5_PROFILE_DRAW=1:mainrowsFlushPendingwriter waits left under the mutex ([flushwait])The counters show waits moving out of the lock; they do not split the FPS gain further, and part of the writer waits stays locked (work recorded after the pre-sync, and lookups the pre-sync does not list, such as a build that misses the resource cache).
One traced gameplay row on each side (session 1),
APS5_TRACE_SECONDS=85:12: frame p50 669.5 ms (18 presents in the window) onmainand 557.0 ms (21 presents) with this change, mean frame 666.9 and 605.0 ms, p90 760.4 and 779.9 ms. In this traced row with the change, the writer pre-sync fired 0.2 times per 10 s in gameplay, so this window shows little of the mechanism (its lockedRecorder.Synctime is 849 ms against 698 ms onmain); the title captures below show it.APS5_LAB_HEAP_CENSUSin both summary lines is a variable of my run script; neither commit reads it.Traces, they open in ui.perfetto.dev: https://github.com/parl0v/AnyPS5/releases/tag/perf-traces-2026-10-21 (
aps5-trace-36f60df9edb3-18888.json.gzandaps5-trace-96c7091cd26f-12372.json.gzfor gameplay,aps5-trace-36f60df9edb3-11636.json.gzandaps5-trace-96c7091cd26f-6628.json.gzfor the title screen)tools/performance_compare.py
Performance comparison
Configuration differences
Frame and GPU times (ms)
Top phases (ms per frame)
The configuration difference it reports is the window's first present (1651 against 1658): the window is set in seconds, so it starts at a different present.
tools/trace_digest.py, main 36f60df
seconds 85:12 from present 1651: 18 presents, frame p50 669.5 / p90 760.4 / p99 808.7 / max 808.7 ms, GPU busy 140.7 ms per present
NVIDIA GeForce RTX 4060, NVIDIA 617.42, Windows 10.0.19045, 3840x2160, commit 36f60df, dropped: no
{"commit":"36f60df9edb3","dirty":false,"env":{"APS5_LAB_HEAP_CENSUS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_PROFILE_DRAW":"1","APS5_TRACE_SECONDS":"85:12"},"gpu":"NVIDIA GeForce RTX 4060","driver":"NVIDIA 617.42","os":"Windows 10.0.19045","resolution":"3840x2160","window":{"spec":"seconds 85:12","first_present":1651,"ms":12005.055},"presents":18,"frame_ms":{"p50":669.478,"p90":760.423,"p99":808.679,"max":808.679},"gpu_busy_ms_per_present":140.701,"worker_busy_pct":{"queue worker 0x0":99.705,"queue worker 0x20":97.928},"top_phases_ms_per_frame":{"Driver.Packet":1317.635,"Driver.Packet.memory_wait":425.336,"Driver.Packet.dispatch":366.131,"Driver.Dispatch":364.816,"Resources.Complete":358.141,"Graphics.Draw":331.012,"Graphics.Draw.draw_and_resource_release":299.075,"Driver.Packet.draw":257.558},"trace_dropped":false,"trace":"aps5-trace-36f60df9edb3-18888.json.gz"}Slowest frames (largest slices inside each, inclusive)
Threads (ms per frame)
Largest slices (ms per frame, inclusive, all threads): Driver.Packet 1309.1, Driver.Packet.memory_wait 425.2, Driver.Packet.dispatch 365.7, Driver.Dispatch 364.3, Resources.Complete 357.4, Graphics.Draw 330.4, Graphics.Draw.draw_and_resource_release 298.3, Driver.Packet.draw 257.0, Driver.Draw 256.6, Vulkan.Dispatch 250.5
Longest waits
Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)
tools/trace_digest.py, this change 96c7091cd
seconds 85:12 from present 1658: 21 presents, frame p50 557.0 / p90 779.9 / p99 807.0 / max 807.0 ms, GPU busy 133.6 ms per present
NVIDIA GeForce RTX 4060, NVIDIA 617.42, Windows 10.0.19045, 3840x2160, commit 96c7091cd26f, dropped: no
{"commit":"96c7091cd26f","dirty":false,"env":{"APS5_LAB_HEAP_CENSUS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_PROFILE_DRAW":"1","APS5_TRACE_SECONDS":"85:12"},"gpu":"NVIDIA GeForce RTX 4060","driver":"NVIDIA 617.42","os":"Windows 10.0.19045","resolution":"3840x2160","window":{"spec":"seconds 85:12","first_present":1658,"ms":12704.108},"presents":21,"frame_ms":{"p50":557.018,"p90":779.851,"p99":806.963,"max":806.963},"gpu_busy_ms_per_present":133.644,"worker_busy_pct":{"queue worker 0x0":99.639,"queue worker 0x20":97.503},"top_phases_ms_per_frame":{"Driver.Packet":1192.2,"Driver.Packet.memory_wait":380.283,"Driver.Packet.dispatch":358.65,"Driver.Dispatch":356.822,"Resources.Complete":319.993,"Graphics.Draw":261.948,"Vulkan.Dispatch":254.628,"Vulkan.Dispatch.shader_resources":249.327},"trace_dropped":false,"trace":"aps5-trace-96c7091cd26f-12372.json.gz"}Slowest frames (largest slices inside each, inclusive)
Threads (ms per frame)
Largest slices (ms per frame, inclusive, all threads): Driver.Packet 1183.2, Driver.Packet.memory_wait 380.1, Driver.Packet.dispatch 358.2, Driver.Dispatch 356.3, Resources.Complete 319.2, Graphics.Draw 261.2, Vulkan.Dispatch 254.0, Vulkan.Dispatch.shader_resources 248.5, Graphics.Draw.draw_and_resource_release 245.7, Driver.Packet.draw 211.1
Longest waits
Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)
Title screen,
mainagainst this change. RTX 3060 12 GB (NVIDIA 617.42), Windows 10 19045, PPSA16064 title screen,APS5_TRACE_SECONDS=120:12,main36f60df against 96c7091cd in one session, alternating. Times are per 12 s capture window, from the traces:Recorder.Syncunder the mutex, all threads (ms)Recorder.WaitSerialwithout it (ms)Driver.Packet.device_lock(ms)main36f60dfThe change is faster in 3 of 3 pairs, by 0.8 % on the mean p50 (110.08 against 110.97 ms). The locked
Recorder.Synctime halves and the unlockedWaitSerialtime grows (aFinishUpToof a batch in flight has no slice of its own, so not every locked wait shows up asRecorder.Sync). Worker 0x0 waits about 610 ms less per window for the mutex; at the title the GPU, not the workers, sets the frame time.summary lines, the other title captures (main, then this change)
Title screen, the switch alone. Same card and screen, the same 96c7091cd build with
APS5_NO_WRITER_PRESYNC=1(off) and without it (on), alternating:Recorder.Syncunder the mutex (ms)Recorder.WaitSerial(ms)Driver.Packet.device_lock(ms)On is faster in 3 of 3 pairs (0.7 % on the mean p50), with the same shift from locked to unlocked waits as against
main.summary lines, the switch alone, off then on
Tested
main5d3ab77) and onmain5d3ab77, RTX 4060 (NVIDIA 617.42, Windows 10 19045, WinLibs GCC 15.2.0, Release withBUILD_TESTING=ON):ctest -V -R "agc_driver_(storage|dcc|presync|flush)"withVK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn, Vulkan SDK 1.4.363.0. 12 of 12 pass with this change (the 11 onmain, which now includeagc_driver_storage_write_back_overhang_draw_pipeline, plusagc_driver_storage_presync_writer) and 11 of 11 onmain. Neither log has awas not found but was requested by env var VK_INSTANCE_LAYERSline, and both have 0VUID-lines (each has the same 10WARNING-VkImageSubresourceRange-layerCount-compatibilitylines fromagc_driver_storage_write_back_no_window). The same comparison on e5c5329 gave 11 of 11 and 10 of 10.APS5_NO_WRITER_PRESYNC=1the new test passes its control case (one locked wait) and then fails with "storage pre-sync writer, writer in the open batch: stage A did not list the storage image of the cached build as a writer range". Onmainit does not build: the counters it reads are new.agc_driver_graphicspasses on 4d578a4.git diff --check,python3 tools/check_test_registration.py buildandpython3 tools/check_conventions.py --base upstream/mainpass on 4d578a4. The rebase onto 5d3ab77 conflicted only in context: inTexture.hpp,mainadded awaitedparameter toFlushPendingandStampKeepingNewerResultsnext to this change's declarations (both kept;waitedonly feedsPublishShadowsOnlyand does not touch the writer wait), and inARCHITECTURE.mdmainadded itsAPS5_DRAW_PIPELINEbullet after this change's (kept unchanged). The change's own lines are identical (git range-diff).maine5c5329, MCD2 stops more often than on 36f60df (a game access violation and the write-watch check above), on both sides.Related
FlushPendingthat this change moves out of the lock.[presync]line).WaitForFlushingright afterFlushPending, where this change addsWriterWaitCounts; the rebase keeps both.FlushPendingto the stored layers' blocks. The two merge with a small carry inRecorder.hpp(adjacent declarations) and in the wait inFlushPending(this change's counters andFinishUpTosource around perf(agc): wait on a flush only for writers over the image layers it stores #8887's two calls), which @SleglJan describes and has run in 007 First Light. Either order works; whichever lands second carries it.Recorder::WaitSerialForright aboveRecorder::FinishUpTo, whose signature this change extends with the wait source. That is the only conflict (Recorder.cpp, adjacent lines), resolved by keeping both functions; neither changes what the other waits for. Either order works.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 (none added).mdfiles or images added to the repository