With APS5_PROFILE_DRAW set, the [rescache] line now counts the template
hits that took a data refresh while the template held fewer bindings
than the shader (no image table binding of its own): the refreshes that
threw "template bindings disagree with the shader" before the bindings
were paired by binding number.
A resource template keeps no binding of its own for an image table: the
build hands the shader's image table binding to the table stage. Its
binding list is therefore one shorter than the shader's, yet
DataWordsDiffer and refreshData paired the two lists by index and
required equal lengths. Every data refresh of a compute template whose
shader reads an image table threw "template bindings disagree with the
shader", and DataWordsDiffer reported different words for the shader the
template was built from.
Evidence: a title stopped once its pipelines came from the cache with
"compute shader 0x80003c7100: AGC graphics: template bindings disagree
with the shader". The shader listed 9 bindings (guest buffers, three
guest image arrays, the fault buffer, the flattened SRT, the sampler
table, the image table map and the image table at 260); the reused
template held 8, without binding 260.
Both functions now look up the template binding of each data binding by
its binding number.
Tested: agc_driver_graphics builds a compute template from an image
table map, an empty image table and shader data, checks that its own
words compare equal, refreshes it with other words, and checks the data
buffer and the compare afterwards. Without the change it fails with "a
template's own words differ from the shader that built it".
Cherry-picked from fable-void's 7bb699b85c; conflict in tests/Graphics.cpp resolved to main's image table ABI: the test's header no longer sets HeaderImageSlots, a word main's ABI does not have (main keeps HeaderElementBase at that index), and its mock context gets the image table limits main's imageTableAllocationTests sets (image table capacity and sampled images per set and per stage, 2 each), since main refuses image tables on a context without them.
importMappedFailureGenerationTests (#8802) maps a single 64 KiB range and
expects ImportMappedRanges to try its import. Ranges of 64 KiB are now left
to their first GPU use, so the probe saw no allocation. The fixture maps
128 KiB as one window, which is still imported at map time.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The import-requester test now counts the map requester on a 128 KiB range
and asserts that a 64 KiB range is not imported at map time and is imported,
for the access requester, at its first use. The over-budget map test maps
128 KiB so it still reaches the budget check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Nothing runs in VR2D without a headset, so sceHmdInternalIsGameVr2d,
IsMiniAppVr2d, IsCommonDlgVr2d and IsCommonDlgMiniAppVr2d return false,
the answer the console gives to the same four queries in libSceHmd2.
sceHmdOpen never issues a handle without a headset, so the distortion
correction, wide-near correction and 2D VR command queries, and their
sceHmdDistortion* export aliases, answer as the other handle queries:
NOT_INITIALIZED before sceHmdInitialize and HANDLE_INVALID after it,
leaving the command buffer unwritten.
A fourth title reached the refusal on another GPU and OS (reported on the
PR), so the entry no longer names a count.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The private collect counted its GetWriteWatch calls and pieces on every
call, under the mappings mutex, for agc_private_collect to read. They
are now compiled only where APS5_COUNT_MAPPING_QUERIES is set, as the
address-space query counter is: agc_private_collect_tests sets it, and
the runtime's Collect updates no counter. libc's GuestArenaCollectWork
export, which nothing calls (the test reads its own WindowsMappings),
is removed.
Adapts fable-void's 2760ad808.
A private collect read from the allocation map makes no query, so it
can't see memory that code bypassing WindowsMappings changed inside a
recorded allocation. A page decommitted in place there is the case it
can't catch: GetWriteWatch still succeeds over it, so the collect
reports no writes where a query would have refused the range.
With APS5_VERIFY_DIRECT_COLLECT set, each such collect also queries its
span's regions, and Collect throws, naming the span and the switch, when
GetWriteWatch succeeded over memory that is no longer committed
private. ENVIRONMENT.md lists the switch.
windows_write_watch_verify_direct (the same test binary with
--verify-direct, the switch set) collects a recorded private allocation,
checks its write is still reported, decommits one page in place and
requires the next collect not to succeed. Without the check the collect
succeeds.
Adapts fable-void's 2760ad808.
Collecting private guest writes from the allocation map trusts the
extent the mappings recorded and calls GetWriteWatch without a query.
When memory in that extent was released by code that bypasses
WindowsMappings, the call fails and Collect threw "collect
private guest writes". Before the map, the query found the memory no
longer committed private and Collect returned false, which its callers
already handle.
A failed GetWriteWatch now queries the region at the cursor. If it is
no longer committed private memory, Collect returns false as before;
otherwise the failure is still fatal.
windows_write_watch releases a collected private allocation with
VirtualFree behind the mappings, then collects it again: it must return
false without throwing. Without the query it throws.
Adapts fable-void's 2760ad808.
Collecting guest writes over private memory asked VirtualQuery for every
region before reading its write watch, and a region ends at every
protection change, so each 16 KiB piece cost two system calls and an
allocation with several protections was read in several parts. The hot
sweep reads every unguarded private page at every ordering point, so
this cost was paid per hot page per dispatch.
The mappings now keep the extent of every private allocation they make
(added when a placeholder is replaced, erased on release) and collect
one GetWriteWatch per allocation from that map. A write watch read
cannot span two allocations, so pieces committed one by one still take
one read each; the query per piece is gone and the reported pages are
unchanged.
Tested: built; the new agc_private_collect test (256 MiB of 16 KiB
pieces with scattered writes returns the same pages as a reference
read, at most one system call per piece; one allocation in five
protection regions takes one call) fails before (32768 calls for 16384
pieces) and passes after (16384). The new hot-sweep case of
agc_driver_residency_dispatch_work fails before (51324 calls over 25660
pieces with 256 hot runs, about 1500 us per dispatch) and passes after
(25660 calls, about 1160 us). 47 residency, write-watch, guest-memory,
address-space and shared-write tests pass.
The VirtualQuery counter that windows_write_watch_tests reads is now
compiled only into that test, through APS5_COUNT_MAPPING_QUERIES, so
the runtime's WindowsMappings::query does no atomic update per query.
sceNpTssCreateNpTitleCtxA creates a context like sceNpTusCreateNpTitleCtxA,
and sceNpTssCreateNpTitleCtx checks its NpId and service label first, as
shadPS4 does; both share the TUS table, its 32-context limit and its
requests.