A program with one GLC or DLC buffer load or store decorated the whole
guest buffer array Coherent, so its other loads were coherent too. On
NVIDIA that keeps them out of the L1 cache: one GLC store made the
re-reads of a 4 KiB window about 2.7 times slower.
RDNA keeps those loads incoherent. A load without GLC or DLC can hit the
per-CU L0 and per-SA L1 caches, which are not coherent between
work-groups, and code that needs another work-group's data reads it
with GLC/DLC or invalidates the caches first (LLVM AMDGPU memory model,
GFX10: an acquiring load is followed by buffer_gl1_inv; buffer_gl0_inv).
The program metadata now records whether a program invalidates a cache
(buffer_gl0_inv, buffer_gl1_inv, s_gl1_inv, s_dcache_inv). Without one,
a program with GLC/DLC accesses gets a second array on the same binding,
buffers_coherent, decorated Coherent, and both arrays are Aliased as
buffers_u64 already is. Loads without GLC or DLC read buffers; GLC/DLC
loads, stores and atomics use buffers_coherent. A program that
invalidates a cache keeps the whole array Coherent.
gh label create exits non-zero for a label that already exists, and the
step runs with bash -e, so the first existing unforced label stopped the
job. Skip labels that already exist, keeping hand-set colors.
Fixes#2320
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelAprSubmitCommandBuffer rejected a buffer object with EINVAL
unless sceAmprAprCommandBufferConstructor had tagged it. The tag is
AnyPS5's own: in the retail layout the type word only carries state
bits and the constructors zero the object, so a zero-filled object
bound with SetBuffer is a valid APR buffer.
CRI's file system in Sonic Origins (PPSA05324) lays out its
AprCommandBuffer objects in its own zeroed work memory and never calls
the constructors. Its first read submit failed with 0x80020016, and the
CRI file system stopped there.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceNpEAAccessInitialize and sceNpEAAccessTerminate resolve the NIDs
7CxI50-xlCk and pMxXhNozUX8, which shadPS4 names in np_partner.cpp. The
stubs still throw; only the names and no-argument signatures change.
FreeBSD's unlink ignores the file's own permission bits, so remove()
succeeds on a file the guest made read-only with chmod(0400). On Windows
the guest chmod sets FILE_ATTRIBUTE_READONLY, and DeleteFileW then fails
with ERROR_ACCESS_DENIED, which remove() reported as EACCES. Clear the
attribute and retry, restoring it if the retry still fails.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Use INFINITY and NAN from <cmath> instead of a new <limits> include, and
list the TechnicalDebt entry beside the other NGS2 voice entries, so the
change merges cleanly with the pan, channel map and reverb changes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The template allocated a fixed 4 KiB of LDS, so kernels with immediate
offsets past it could not run. --lds (Python lds) sets the group segment
size in bytes, up to 64 KiB, with 4096 as the default.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The guest passes and expects UTF-8 names, but on Windows opendir and
readdir used MinGW's narrow dirent API, which works in the ANSI code
page: opendir failed for a directory whose name is outside the code page,
and readdir returned names as ANSI bytes, with "?" for characters the code
page lacks. Use _wopendir and _wreaddir there and convert each name to
UTF-8.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A reverb_size other than the default was accepted and ignored, and below
about 7.5 kHz an allpass length went negative and wrapped to a 16 GB buffer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
WindowsMappings::Collect resets each part of the range as it walks it:
it marks shared views seen and resets private pages' write-watch bits.
When it then met a NOACCESS view or memory that is not committed
private memory, it returned false with the earlier parts already reset,
so their writes were lost to the caller's fallback. With reset, the
whole range is now checked first and nothing is reset when it fails.
AI-assisted (Claude Code).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Parse legacy decimal, octal and hexadecimal forms before host lookup. Preserve FreeBSD shorthand, whitespace and 64-bit accumulation, clear the SDK resolver error on numeric success, and add regression coverage.
getcwd(NULL, size) returned memory from the guest heap directly, while
the caller frees it with free(), which goes to the application heap.
With a title's malloc replacement registered, that free reached the
replacement with a pointer it never returned. Allocate from the
application heap like strdup, and report ENOMEM when it returns null.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolve the missing EVO-PLAYER import reported in #1578. Convert native host entries into the guest ABI with owned per-thread storage, and use the SDK network error location for failures.
Check numeric address bytes, guest hostent fields, per-thread result lifetime, and the SDK resolver error location. The check currently fails to link because the reported export is missing.
EmitClassifyF32Bits found a NaN from the exponent and mantissa fields
separately. The magnitude settles it: a NaN is above 0x7f800000 and a
zero is 0.
min and max ended with two NaN selects. An ordered compare is false when
either operand is a NaN, so the ordered pick already returns rhs for a
NaN lhs; only the select that returns lhs for a NaN rhs, also when both
are NaNs, is needed.
med3 is the minimum of the three when any operand is a NaN and the
median otherwise. The median is used only without NaNs, so it is now
built from compares and the zero-sign rule alone, and the minimum reuses
the operands' NaN tests instead of classifying intermediate values.
MIN_LOD_WARN, MIP_STATS_COUNTER_EN and MIP_STATS_COUNTER_ID are ignored by the texture decoder, but the cache
key held the raw T# words. A title that rotates the counter fields per use got a cache entry per variant of the
same texture, and the extra entries evicted live ones under the budget.
sceAgcCreatePrimState only packs registers, but it now also resolves the
graphics ABI ahead of time, and that resolve throws when the primitive
type is a patch list without HS_EN or a hull stage with another type.
No draw can use such a state, so leave it to draw time and return the
registers. Bit 2 of VGT_SHADER_STAGES_EN is HS_EN, not an NGG bit.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A flip still queued or in presentation when the title closes its port is discarded, as on hardware, rather than stored as a driver failure. A closed port no longer terminates the presentation thread nor surfaces from Shutdown. The lifetime test now expects cancellation and the reopen mode is registered in ctest.
#2083 chooses the NaN result of the f32 fma family on the bits: the first
NaN source, quieted in IEEE mode, with the addend skipped when the
product is infinity times zero, and 0xffc00000 otherwise. The selection
and the infinity-times-zero test ran for every fma, but a NaN source
always gives a NaN result, so for any other result they return it
unchanged.
FPNanResultFma32 carries the result and the three sources, with the IEEE
mode as a flag. The SPIR-V emitter makes the selection, including the
infinity-times-zero test, in a branch taken only for a NaN result, and
the SRT evaluator computes it exactly. Add, sub and mul keep the inline
selects: with two sources a branch costs more than it saves.
winpthreads initializes a PTHREAD_RWLOCK_INITIALIZER lock on its first
use and fails a concurrent first lock with EINVAL. std::shared_timed_mutex
ignores that result in release builds, so two guest threads could both
hold a fresh guest rwlock.
Lock and unlock the mutex once when the guest rwlock is created, before
another thread can reach it, and record the remaining host exposure.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD's unlink(2) reports EPERM for a directory, but the host call
returns EACCES on Windows and EISDIR on Linux, so the guest saw a
different error on each host. Check for a directory, not following a
symbolic link, before unlinking.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelMunlock and the POSIX munlock unlock the page-rounded range with
FreeBSD's results: 0 for a mapped range whether or not it is locked, EINVAL
for a range that wraps around zero, ENOMEM for an unmapped range. On Linux
the host munlock gives them. On Windows a reserved placeholder counts as
mapped only while the guest reservation or protection registry covers it,
and a region VirtualUnlock refuses as not fully locked is unlocked page by
page, as VirtualUnlock is all-or-nothing. sceKernelMlock shares the range
rounding.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_012GLfKH7Sqe51wX254k1XsV
The sampled texture cache let go of its least recently used entry even
when a build, a recorded batch or a cached resource set still held that
texture, which frees no memory and makes the next lookup create a
second copy. A frame that samples more textures than the cache holds
also missed on all of them every frame.
Eviction passes over an entry whose texture is held elsewhere, or a
view of a cached storage image, up to a quarter over the budget, and
rescans for released textures about once a second. While the least
recently used entry was used in this frame or the previous one, a
texture's first use in the frame is returned uncached and only a second
use evicts, so the next frame finds the cached textures again, even
after an early miss; a new set replaces the old one on its second
frame. APS5_PROFILE_DRAW prints the cache's counts every 10 s.
The device-local tier of BufferPool only reused a buffer of the exact
size and usage it was asked for. Partial storage-image detiles and
retiles ask for a new size and the other transfer direction almost
every time, so the tier sat at its budget and missed and evicted
dozens of buffers per frame, and the vkFreeMemory calls on the release
thread held up submits and allocations on the recording threads.
Device-tier requests of 1 MiB and more now round up to an eighth of
their octave, the tier's buffers are created for storage and both
transfer directions, and a request takes the smallest retained buffer
from its own class up to twice its size. Host tiers, the budget and
eviction are unchanged. agc_buffer_pool covers the classes, the fit
and its bound, reuse only after release, the budget and the unchanged
lists.
An address-based build whose heap mirror the device refused, or one past
APS5_HEAP_MIRROR_MIB, stopped the process inside acquireMirror. PPSA26344
hit it at 478 s with 6.8 GiB of heap mirrors beside the host imports.
- a mirror that would go past the budget first sweeps the mirrors whose
registered range is gone, before its allocation; if it still does not
fit, the build throws "past the budget"
- the mirror is allocated once: a refusal throws with the range, the
Vulkan result and the mirror totals, so the draw or dispatch fails like
any other allocation; nothing is registered for the refused range
- the BDA resource tests run with a 4 MiB mirror budget and a mock memory
limit: a mirror past the budget is made in the swept mirror's memory,
and a refused one fails after a single allocation attempt
Every BDA dword read site still emitted in the entry function the add
of its first dword address with the overflow fault, a probe_bda_pointer
call, the wide loads, and one read_bda_dword_bytes call per extracted
dword. NVIDIA's pipeline compile time grows with every call left in the
entry function, so large compute programs with a few hundred such reads
spend 47-77 s in vkCreateComputePipelines.
A read site is now one call to a DontInline read_bda_span function, in
a stop and a coherent variant, taking the address, the immediate offset,
the mask of extracted dwords and the pc, which does the same steps in
the same order. Fault reasons, addresses, pcs, Volatile, the stop
behaviour and the APS5_BDA_BYTE_READS path are unchanged.