mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-01 12:45:56 +00:00
A linear color target got a resident image only when its memory already had a host import (#6892). Every other draw into it was synchronous: copied in, drawn, waited for on the CPU and copied back. #6892 only looked the import up because a first version that made it broke agc_driver_pixel_ancillary_word and agc_driver_pixel_fixed_point_position: the import over a short-lived block was compared, and the next block allocated at the same address stayed outside the write watch. A page committed again inside an excluded block is watched again since #6759. On a lookup miss the draw now makes the import itself, with the new ColorTarget requester, when its registered ranges are writable, the whole import run is write-watched and the import keeps it watched: a separate alias of shared memory, a direct import of private memory that settles on Windows (1 MiB or more, when the import probe keeps the watch and a settle queue exists), or an import the probe keeps watched on other systems, where a dma-buf import must stay watched too if the range has shared backing. Private pages that the write watch armed read-only count as writable when their guest protection is, because the import opens them (a resident direct-memory run the CPU has not stored to since its last collect). The gate's scan stops at the first page that decides a refusal, and a run of private memory whose direct import would be compared is refused after one page query. A refusal is remembered for its run until the registry, the committed pages (Windows) or the write watch change, or a shared alias is mapped over the run, so a target that stays synchronous costs a lookup per draw. importRunAt checks this after its remembered failures and refusals and before it retires or evicts anything, through the helpers its own decision now uses: importWatching (settled, watched host-pointer and dma-buf imports) and importPages (the Windows page scan). A target whose import would be compared stays synchronous, because a compared import makes every refresh of the resident image compare the whole target. A target over an import that already exists is resident as before, with ExistingHostImportFor as the fast path, and APS5_NO_RESIDENT_LINEAR=1 still keeps every linear target synchronous. This is the case draft #1191 (MichonGoddijn231849) was to bring back on top of #6892 once partial-block write-watch coverage existed. agc_driver_linear_target_import_creation covers a target in freshly registered, write-watched memory (the draw is recorded, the target is imported and stays watched), a block freed and allocated again at the same address (it is watched, and the next draw starts from the CPU's bytes), a resident direct-memory run armed read-only by the write watch (the draw is recorded and the target imported; Windows), the gate over armed and read-only private memory (a compared import of an armed run is refused without opening it, memory committed read-only behind a writable registry range is refused without a count, an armed run is imported where imports stay watched; Windows), a 64 KiB block whose import would be compared (no import, a synchronous draw, the block stays watched), a 1 MiB block the guest registered read-only (no import, a synchronous draw), a 1 MiB run with one 64 KiB block outside the write watch (refused, the target stays watched), and the same run once that block is committed again (the refused run is imported; Windows). On other systems the test forces ImportWatch::Watch, so the watched cases also run where imports are compared (lavapipe in CI). The import requester tests count the new requester and check that it makes no compared import, no import of a range the guest cannot write and no import of memory outside the write watch. Co-Authored-By: Claude <[email protected]>