mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-02 12:56:05 +00:00
Every capture of a shader with an image table read every record of each column and looked each record up among the snapshot's distinct descriptors. A 32,768-record column of distinct T#s cost 6.1 ms per capture here (2.3 ms with 16 distinct T#s), and Resident Evil Village's title captures such columns on nearly every draw. TableSnapshotter now keeps the last 16 column snapshots per thread (at most 4 Mi words in all, least recently used first out), keyed by heap base and size, record shape and key count: the runs it read, their words, each record's state and code, and the distinct T#s. A narrowed, selected or pointer-indirect column, or one with an unmapped record, is not kept. A capture of a kept column takes the codes and the distinct T#s from it with no per-record work. When they are the snapshot's first words they are taken as they are, and the words index is built only if a later column needs it, so the result is the snapshot a fresh walk would produce, codes and words order included. The runtime gets three optional callbacks: stampWrites gives a stamp for a range before any of it is read, unchangedSince tells whether nothing wrote the range since, and supplyWords hands words that equal guest memory to the capture as read, so they stay in the captured regions the draw cache compares. ShaderMemory implements them with the write tracker. The stamp is CollectWrites's generation, refused when this ShaderMemory already fetched a page of the range or recorded GPU work writes it. A range is unchanged while no block of it is stamped after the stamp (collected CPU stores, the driver's Write, WriteChanged and StoreOwnBytes, MarkWritten for GPU writes into imports), no recorded GPU work writes it and the guest allocation generation is the stamp's. When every run is vouched for, the column is not read at all; otherwise its runs are read and the snapshot is reused only when they are equal word for word. The 32,768-record column now costs 0.48 ms per capture with no word read when unwritten, and about 0.9 ms outside the write watch. APS5_NO_TABLE_SNAPSHOT_REUSE=1 turns the reuse off. The [image-table] profile line counts the reuses, and ResourceMaterializer::TableReuse returns them with the words the snapshotter read.