VirtualQuery describes the pages from the queried address to the end of the run of equal pages, so the reported seg0 begins at the queried page. The cached entry returned the first lookup's page for every later address in the run. It now returns the queried page and the bytes up to the end of the cached run, which is what VirtualQuery returns.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
sceSaveDataSetSaveDataMemory2 read the whole slot file, patched it and
replaced it through a temporary file on every call, so each call cost a
full rewrite of the slot (up to 32 MiB). The changed ranges now go to a
small journal that is staged through the slot's temporary file and
renamed into place, then written into the slot file in place, and the
journal is removed. A journal left by an interrupted call is replayed by
the next setup, get, set or sync of that slot.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A geometry program with VGT_GS_OUT_PRIM_TYPE 1 was refused as an
unsupported output assembly. Each primitive export of an NGG line-strip
program is one line whose indices are packed like a triangle's, so the
mesh module now declares OutputLinesEXT with PrimitiveLineIndicesEXT for
it. A subgroup gets VGT_GS_MAX_VERT_OUT - 1 lines per input primitive and
at least GE_MAX_OUTPUT_PER_SUBGROUP line slots; fast launch keeps using
PRIM_AMP_FACTOR. The output size is part of the cache, draw, validation
and pipeline keys, and the request serialization version becomes 31.
Triangle-strip geometry is unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The OpenOrbis create-fself drops a DT_INIT_ARRAYSZ of 0, so a PS4
program without constructors, such as the ClassiCube PS4 port, has
DT_INIT_ARRAY and no size. Code analysis rejected it with "incomplete
initializer array". FreeBSD 11.4's rtld takes the number of
initializers only from DT_INIT_ARRAYSZ and starts it at 0, so such an
array calls nothing; code analysis now adds no roots for it. A size
without an array still fails.
Two defined ELF exports that are renamed to the same name, such as foo
and foo_nid_disambig1, were both written as one name and the patcher
exited 0, leaving a lookup that can reach only one of them. The PE and
Mach-O back ends already reject this.
The ELF patcher now remembers the address (st_value and st_shndx) of
each patched export name and throws "duplicate patched export name"
only when the name comes from a symbol at a different address. Aliases
of one address are kept: the Linux libc defines __cxa_throw and
__cxa_throw_nid_no_patch_cut as aliases of __cxa_throw_nid_postfix, so
both become __cxa_throw, and any lookup of that name resolves to the
same code.
The Linux libc also exported __gxx_personality_v0 twice at different
addresses: the forwarding function in Personality.cpp and the
__gxx_personality_v0_nid_no_patch_cut alias of the guest personality.
Drop that alias, so the name keeps only the forwarding function, as
in the PE build.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With APS5_VERIFY_DRAW_ENTRIES=1 every hit is captured again, so drawHit is false and no relocated hit counted for its shader set's trial, which judged every set unproductive and turned the relocation off under the very mode meant to check it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Expand named a DB expand's store, but nothing passes it: main has no DB
expand, and the open DB expand change stores its planes only where host
imports already hold them, through HostImportOverlaps and the storage
write-back, without making or retiring an import. The requester could
never count, so the shutdown line always ended with expand 0/0/0.
agc_driver_graphics checks the requester names and the shutdown report
without it.
Lines queued behind the logger were lost when the process ended through
abort(), std::terminate, the Windows crash report or a guest _Exit,
because only driver failure, Driver::stop and a normal exit flushed the
queue.
libc keeps one end flush (LibcSetEndFlush_nid_no_patch) and runs it from
those paths. Its first registration chains a SIGABRT handler in front of
the previous one, so every abort() and std::terminate in the process is
covered, on Linux as well; with the default disposition the handler
restores it and raises again, so raise(SIGABRT) still ends the process.
Guest abort() and _Exit, and ReportCrash for the first fatal exception,
run the flush directly. AsyncLog registers a bounded flush (FlushFor, 2 s)
that polls two counters and takes no lock, so a dying process cannot hang
on a blocked stream or on the queue lock; after its first timeout it
returns at once. Flush counts queued and finished entries instead of
watching the queue and the writer flag, so it waits for the lines queued
before the call and not for a moment in which no thread is logging.
agc_async_log_fatal runs the test executable as a child that queues lines
behind a held stream and ends in abort(), std::terminate(), raise(SIGABRT)
(POSIX) or an access violation (Windows), and once more with the stream
never released. The lines of the first four must arrive in order, the last
child must end after the bound, and every child has a watchdog.
agc_async_log gains the bounded flush case.
Flush must not return while the logger still waits for a stream that
another thread holds (the regression reported on the pull request: it gave
up after two seconds), and a full queue must block its caller instead of
dropping a line. AsyncLog::Capacity becomes public so the test sizes its
load from it.
Texture creation logged one stdout line per texture and per mip through
WriteLogLine, which formatted with the mingw printf and flushed every
line on the queue worker (about 786k lines in a 25 minute cave run).
AsyncLog keeps a bounded queue and a logger thread. AGC_LOG_DEFERRED
captures numeric arguments on the caller and formats them on the logger
thread; WriteLogLine hands finished lines to a per-module sink in
libc/LogMacros.hpp that AgcDriver installs, so all AgcDriver stdout
lines keep their order and are written one flush per batch. A full queue
blocks the caller, so no line is dropped. Flush runs on driver failure,
shutdown and at exit. APS5_LOG_SYNC=1 restores the synchronous path.
Identical "deferred write-back failed" notes are printed three times per
10 s and then counted into one "repeated N more times" line. A
"[log] 10 s" line reports lines, bytes, caller time and logger time
(APS5_LOG_STATS=0 hides it).
The execution part of the AMD64-only converter tests was compiled for
Linux x86-64 only, so the SSE4A, SHA-1, SHA-256, CLZERO and reciprocal
stubs were never run on a macOS x86-64 build, unlike the ANDN lowering
tests. Rosetta maps no memory below 4 GiB, so the CLZERO case that needs
a 32-bit address is left out when that mapping is unavailable.
The lazy mode of agc_driver_prepared_shaders only checked dispatch output and failure reporting, which eager preparation also produces. Read the registered snapshot through Driver::RegisteredShaders: registration leaves it deferred with no prepared artifact, and the first dispatch prepares it.
APS5_LAZY_SHADER_PREPARE=1 keeps registration validation and decoding but skips queueing the preparation. Draws and dispatches prepare a deferred snapshot on first use and cache it; explicit ABI resolution still prepares its stages. Titles that register thousands of shaders at boot no longer hold every prepared shader in memory before the first frame.
Cover lazy dispatch, metadata and failure cases in both asynchronous and synchronous modes.
Storing a storage image's pending results needs a staging buffer, and under memory pressure that buffer comes from the heap whose allocation just failed. The release turned to dirty images once the clean ones did not cover the request, so with the device and shared heaps full it failed on a 4 MiB write-back buffer at every call (PPSA26344 on Windows). StorageTexture::Flush clears the pending state before it stores, so each failed store also dropped that image's results. The release now takes only sampled entries and storage images without pending results, and its line reports how many images with pending results it kept.
WriteBackBuffers threw the fault before guestMemory.WriteBack(), so a
dispatch that recorded an unaligned BDA access lost the stores of its
other invocations, although the shader only skips that access. The
write-back now happens first and the report follows. A fault of any
other kind still fails the command before anything is published.
A shader that records an unaligned BDA access on every dispatch formatted
and printed one line per completion. CheckFault now throws
BdaUnalignedAccess for that fault, and the recorder prints the first 8
deferred reports of it whole, then every 1024th with the count. Every
other deferred failure is still printed each time.
AnyPS5 exports some libkernel functions, such as __error, from
libc.prx, which libkernel.prx links. On Linux they resolve through that
dependency. On Windows, the import stubs search only the listed
modules, and libc.prx was listed only when libSceLibcInternal.prx was
needed. A PS4 homebrew that needs libkernel.prx but no C library (the
OpenOrbis graphics sample) failed with "unresolved ELF import
9BcDykPmo1I". libc.prx is now also listed when libkernel.prx is needed.
PS5 executables need libSceLibcInternal.prx and convert unchanged.
Village's 2x checkerboard puts its two samples at x = +4/16 and -4/16
and swaps their indices on odd rows. On a device without a 2x2 sample
location grid every pixel takes pixel (0,0)'s locations, so the odd
rows hold the console's sample 1 in sample 0 and the reverse: a pass
that reads the samples by index, as checkerboard reconstruction does,
exchanges the two half-pixels of every odd row, and SampleID, sample
masks and exported coverage name the wrong samples there.
Such a pattern holds one set of positions in every pixel, so drawing
with pixel (0,0)'s locations is exact up to the order of each pixel's
samples. The draw now keeps the guest's order: the pixel shader reads
SampleID, applies the sample mask and exports coverage through each
pixel's order, and every render pass drawing with the stand-in puts the
samples of its multisampled attachments in the stand-in's order before
it and back in the guest's after it. Color targets do that through a
storage view of their texels as unsigned integers, depth through a copy
and a per-sample pass writing FragDepth, and stencil through
VK_EXT_shader_stencil_export or one pass per bit.
It needs shaderStorageImageMultisample with a storage view of the color
format, sampleRateShading, and a depth format FragDepth writes back
exactly (16-bit or 32-bit float); otherwise, and for patterns whose
pixels hold different positions, the stand-in alone is used, and the
log line says why. Devices with the grid are unchanged.
Recompile requests carry the order as serialization version 32 (#6470
takes 31), and the shader cache format becomes 40 (open pull requests
take 37 and 39).
sceImeDialogInit wrote "Slayer" into an empty text buffer and the
dialog finished on the second status poll, so a title never got text
from the user: ProsperoRadio's search typed "Slayer" by itself and
found no station.
The dialog now runs until the user answers on the host keyboard, the
way #4756 made sceImeOpen's panel-less IME take it. While no IME panel
is open, libSceIme hands the game window's text and editing keys to
a sink that the dialog registers. Typing edits the text up to
maxTextLength without splitting a surrogate pair, Enter writes it to
the title's buffer and finishes with end status 0, and Escape finishes
with 1. Abort still finishes with 2. A second Init reports busy, and a
null parameter or buffer or a maximum length outside 1 to 2048 is
refused, as in shadPS4.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
MatchDwordPatternFill took the 69-word pattern-fill kernel only word for
word. Hades (PPSA03355) runs the same kernel with words 27 to 29 in the
other order: the SDWA v_cmp that writes s12 (0x7d8c02f9 0x06068c02)
comes before the v_cmp that writes vcc_lo (0x7d860609). Neither compare
reads what the other writes, so both orders compute the same fill.
The matcher now takes either order; every other word and every
user-data and packet condition is unchanged.
The test runs both orders through the matcher and through Submit, flips
each word of the swapped kernel, refuses the other orders of those three
words, and is registered a second time with
APS5_NO_FILL_HLE=1 so the translated kernel must give the same bytes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Its registration and its command-line option followed the split write-back test's, where another open pull request adds its own. They now follow the copied-direct ordering and CMASK tests. No test changes.
A resource-cache entry keeps every sampled texture of its descriptor sets alive. The sampled texture cache passes over textures something else holds and, past its ceiling, drops them anyway; textures it makes without caching are never in it. Entries holding either kept them alive with no budget counting them, bounded only by the 1,024-entry and 65,536-element counts, until device memory ran out.
The texture cache now marks such textures released. ResourceCache::Insert refuses descriptor sets holding one and hands the entries that hold one back to the caller, like RemoveImage does for evicted storage images.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A depth surface is one level: the driver rejects draws that render a
depth mip. A sampled or storage view at the surface's address and extent
that starts at a later level, or a storage access to a later level, does
not touch that level, so it is not the depth plane. DepthSurfaceTexture
and DepthSurfaceStorage still sent such views to the surface, which
rejected the level. Forspoken (PPSA03984) builds a depth pyramid from its
1984x1116 D32 depth surface with a compute shader that samples one level
of a five-level R32F view and stores the next, and stopped there.
Both now leave such views to the texture and storage caches, as they
already do for a view of another extent or format.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
DB_RENDER_CONTROL.COPY_CENTROID and COPY_SAMPLE select the sample that
DEPTH_COPY or STENCIL_COPY copies. Forspoken (PPSA03984) draws with
DB_RENDER_CONTROL 0xc0, DEPTH_COMPRESS_DISABLE and COPY_CENTROID with
neither copy bit set, and stopped at 43 s because both
DepthMaintenanceRejection and decodeDepth took the selection for a copy.
Accept the selection fields when no copy is enabled; draws that copy are
still rejected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>