Failing run 40410094391 (after #11365, unrelated). The crash report prints [r8] as a string of stack bytes; when it contains '~' (ASLR-dependent) the [^~]* gaps of the PASS regex stop matching. Use .* (matches newlines in CMake regex).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
swprintf and the other wide printf calls accumulated the digits of a field width or precision in an int without a bound, so 99999999999 overflowed: UndefinedBehaviorSanitizer reports signed integer overflow at FormattingWide.cpp:130. A '*' width of INT_MIN also overflowed when negated. A width or precision that does not fit an int now fails the call like any other invalid format; glibc's swprintf also returns -1 for it.
Page 2 now samples its sources once a second, in NotePresent, while it
shows; nothing of it runs while the overlay is hidden or on page 1.
- Busy share per queue worker, the top 5 phases in ms per frame and queue
0's waits (memory, lock, GPU) come from the trace's per-thread totals.
Showing page 2 turns recording on with buffering off, so a timed scope
only adds to its thread's totals; leaving it turns recording off again.
Toggle switches it under a mutex, and ANYPS5_OVERLAY=2 switches it on at
start. An APS5_TRACE_* run keeps its own recording untouched, and page 2
then shows these lines only while that trace records. A driver thread
names itself when it starts (BindThread without APS5_TRACE_* stores the
name only) and binds on its first timed scope while page 2 shows;
unnamed threads are not bound.
- Render passes per frame: the draw path counts a begun pass in the trace
totals while page 2's totals are on (PerformanceTrace::Count).
- Flips/s and the draw cache's hit rate come from the driver through a
source it registers at start (the draw cache's lock is only tried); the
pipeline store's hit rate from PipelineStoreTotals; the compile backlog
from the shader preparation and library prebuild pools (tried locks).
- Dropped frames per second are the presents that found no free swapchain
image; repeated ones are presents of the display buffer shown just before.
The device passes the buffer's address, its present mode and the drops.
- Commit charge against the commit limit: GetPerformanceInfo on Windows,
Committed_AS and CommitLimit from /proc/meminfo on Linux; page faults per
second from PageFaultCount or getrusage.
- Host imports: their count and bytes against the budget, on devices that
import host memory.
- CPU copies: address-based builds count the bytes they copy in a
per-thread counter (a relaxed load and store, folded once a second) with
the largest build of each second against the address-copy cap.
- Unimplemented-function calls: libc counts NotImplemented_nid_no_patch
calls; refused shaders are the APS5_SKIP_REFUSED_DRAWS set's size.
- Title ID (when the title has a param.json) and present mode.
The tests cover the trace deltas, hit rates, present-mode names, the
/proc/meminfo parser and the OS reads, the per-thread copy counter's fold,
the counted unimplemented call, the trace switch with page 2 and lazy
binding without buffering, and on lavapipe the sampler end to end with a
fake driver source, its reset when page 2 is left, and the cost of a
present hidden, on page 1 and on page 2.
A Protect or Unmap that ran out of memory while applying its range patch
had already changed the host mapping, leaving the registry and the mapping
disagreeing. The replacement nodes are now allocated before the apply
callback runs, so applying the patch cannot fail. guest_allocations_oom
injects an allocation failure at every allocation of a Protect and of an
Unmap and checks that the registry is unchanged when the call throws.