refreshImports checked every live host import, failure and refusal
again at each guest allocation registry change. A title that maps
memory often (SuperTuxKart, ~1650 maps a second) paid a walk that grew
with the live imports: ~34 FPS with ~1.1 GiB of imports on RADV.
The import table now keeps a weak_ptr snapshot of the ranges it was
last checked against and diffs it with the new lease. Only imports
whose import window touches a changed span, and imports made since the
last refresh, are checked again. Every import is checked when the window
is 0 or the window or budget changed. SuperTuxKart's menu goes from
~34 to ~45 FPS with the same imports live.
The entry for the M5 running macOS 26.4 did not say what Rosetta does
with SHA or AVX-512, and the XSAVE entry was measured only on macOS
27.0.1. On that host sha1rnds4 and a 256-bit-wide vpaddd on zmm raise an
illegal instruction alongside RDSEED, CLWB, RDPID, ADCX and ADOX, while
XSAVE writes an XSTATE_BV of 0x7 and XGETBV returns the same x87, SSE
and AVX mask although CPUID leaf 1 still reports neither XSAVE nor
OSXSAVE.
The BMI1 and BMI2 results were compared with the Intel SDM definitions
over 200,000 random inputs each for PDEP, PEXT, BEXTR, BZHI, LZCNT and
TZCNT, so the entry can say they compute the documented result rather
than only that they avoid a fault.
The only conflict is sceKernelGettimezone in Time.cpp: main now reports the host zone, so the zone is built from that into a local and copied out with the checked write.
USAGE.md's performance overlay section now gives F10's cycle (off, page
1, page 2, off) and ANYPS5_OVERLAY=2, a table with one row per line of
page 2 that names each source and the system it comes from, and what the
page costs: the trace totals it turns on while it shows, and the checks
and counters that run while the overlay is hidden or on page 1.
ENVIRONMENT.md's ANYPS5_OVERLAY row lists page 2.
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.
F10 now cycles through three states: off, the existing overlay (page 1)
and a detailed page (page 2), then off again. ANYPS5_OVERLAY=2 starts on
page 2; 1 and 0 or unset keep their meaning, and any other value still
throws, now naming 0, 1 and 2. OverlayPageAfter is the cycle, the
starting page plus the F10 presses modulo 3. Toggle stores the page it
gives under a mutex and PerformanceOverlay::Page loads it, so Visible,
which every present calls, stays one load as before. Each change of
page resets the statistics, as a toggle did.
Page 2 has its own composer, ComposeOverlayDetails, a pure function of
one OverlayDetailSample. It fills a 46-column panel without the graph.
Every value is optional, and a line whose sources are all missing is
left out; a line with some missing shows only the values it has. Each
line names its unit. Names from elsewhere (threads, trace phases, the
title, the present mode) go through OverlayText, which upper-cases
them and turns characters the font has no glyph for into spaces;
phase names are cut to fit the line. Page 1 is unchanged, line for
line.
On page 2, NotePresent keeps the frame statistics and fills the sample
with the frame rate, the last frame's time, presents per second and
the pipelines created in the last second. It reads nothing else, and
it skips page 1's memory reads and packet sums. The next commit adds
the driver and system counters. NotePresent latches the page, so
Record draws the page NotePresent sampled.
Tests: ANYPS5_OVERLAY 2 and 3, 02 and -1; the cycle from each starting
page through three presses and past 2^64 presses; page 2 of a full
sample, line for line, of an empty sample, and of a sample with
missing sources; every character either composer can emit has a
glyph; page 2 laid out at 1280x720, 1920x1080, 3840x2160 and 640x360,
every line drawn, no graph, and a 60-line page shrunk to scale 3 at
3840x2160. On lavapipe, under the Khronos validation layer with no
message: page 2 drawn at 1280x720 bit for bit, and F10 through a real
overlay: page 1, page 2 drawn from its own composer, then hidden, with
the statistics reset at each change.
The panel was fixed at OverlayMetrics::Columns, 27 columns, and always
kept rows for the frame-time graph. OverlayContent now carries its
column count and whether it has a graph, and the panel's width, height,
fit test and scale come from them. ComposeOverlay still fills 27
columns with a graph, so the existing panel is drawn as before, line
for line.
LayOutOverlay refuses a panel with no columns, a graph on a panel
narrower than its 120 frames, and frame times on a panel without a
graph.
The 5x7 font gains %, +, -, _, J, Q, Y and Z, from the same HD44780
character set as its other glyphs, and OverlayFontCharacters lists
every character it can draw.
Tests: every listed character has a glyph no wider than 5 pixels,
non-empty unless it is the space, and unlike any other; characters
outside the list are refused; a 48-column panel without a graph is
laid out and scaled at 1280x720, 1920x1080, 3840x2160 and 320x180; a
140-column panel at 3840x2160 shrinks from scale 5 to 4; a too-long
line, a 20-column graph and frame times without a graph are refused.
A depth plane and the color storage image that holds or receives its texels were copied image to buffer, then buffer to image. With VK_KHR_maintenance8, which the device already enables, vkCmdCopyImage copies the depth aspect directly to and from a single-component color format of its size (D32 with R32, D16 with R16), so those copies record one image copy and two barriers in place of the staging buffer round trip and three barriers. TakeStorage keeps its discard of the new depth surface before the copy. 24-bit depth, the stencil plane and every other format pair keep the buffer path, as does APS5_NO_DIRECT_DEPTH_COPY=1. The graphics Context now carries the maintenance8 flag. No performance claim is made.
The rows cover signed zeros, the smallest and largest denormals, the
smallest normals, both infinities, quiet and signaling NaNs of both signs
with payloads, exp's overflow and underflow edges, log(1), fract's clamp,
and sin/cos inputs at whole, half and quarter cycles up to 2^24 and
beyond. Only results the special rules fix are compared, bit for bit.