Commit Graph
7963 Commits
Author SHA1 Message Date
Dean Galvin 889e5d436a fix(agc): refuse depth storage views the plane copy cannot serve
A 2D array or cube view with the plane's extent and format reached the
ordinary path and read guest bytes the depth was never written to; it
throws again, with the message main has for it. A multisampled surface
is refused before the plane copy, as sampling it already is. A written
view that another view of the same plane replaced had its results
dropped at store-back; that throws now.

Update the debt entry to what is supported and what still throws.
2026-10-13 15:00:36 +13:00
Dean 2a55cfe1e8 Merge pull request #2491 from oneandonlydean/up639/depth-plane-unchanged-copy-on-425
perf(agc): skip the depth plane copy when no slice changed
2026-10-13 14:49:05 +13:00
Dean c27687313c Merge pull request #4859 from EagleBearerYS/fix/libkernel-flexible-map-flag-8000
fix(libkernel): accept flag 0x8000 in sceKernelMapFlexibleMemory
2026-10-13 14:48:21 +13:00
David 7126090654 fix(libc): convert local times before 1970 and after 3000 on Windows 2026-10-13 01:47:03 +00:00
Yunus Shaikh 6bdbad4cab fix(libSceNet): follow FreeBSD inet text rules
sceNetInetPton and sceNetInetNtop called Winsock's InetPtonA and
InetNtopA on Windows. Those print IPv4-translated and ISATAP addresses
with a dotted tail, print ::ffff:0.0.0.1 as ::ffff:0:1, and accept a
leading zero in a dotted tail, where FreeBSD does neither. Both now
convert with libkernel's inet_pton and inet_ntop, which follow the
FreeBSD 11.4 rules since #3530.
2026-10-12 18:44:01 -07:00
JJenkx d6cd25e123 fix(ngs2): limit render writes to the configured grain 2026-10-12 21:36:12 -04:00
Dean Galvin 50e5f088c9 perf(agc): skip the depth plane copy when no slice changed
Sampling a depth array, cube or R16_UINT view of depth surfaces went
through DepthPlaneCopy::Refresh on every use. Each use copied every slice
a depth surface holds into the staging buffer and the whole staging buffer
into the copy image, with three ALL_COMMANDS barriers, although nothing
had written the slices since the previous use.

Each depth surface now carries a write serial, bumped when a draw binds it
as its depth target and when a pending fast clear is applied. The copy
keeps the image and serial of every slice it copied. A use copies only the
slices whose surface or serial changed and the guest layers that changed
(as before), and records nothing when none did. A slice whose surface is
the depth target of the latest depth draw is copied at every use until
another depth target is bound, since that draw may still be recorded after
the copy.

Test: agc_driver_depth_plane_guest_layers counts the recorded slice copies
and copy fills; a second use with nothing written records none (it records
one of each without this change), a draw to a slice's surface or a CPU write
to a guest layer copies only that layer.
2026-10-13 14:33:40 +13:00
raghav314andClaude Opus 5.5 1baf077a7e fix(agc): clear a multisampled target on a uniform fill of its color memory
A multisampled target's samples live only in its host image, so a fill
of its color memory never reached them: a title that clears its MSAA
targets that way (with no CMASK) kept drawing over the previous frame.

A uniform fill over the whole color memory now clears the host image to
that value at the target's next use, the same way a CMASK fast clear
does, and a pending CMASK clear still takes precedence. The color memory
is sized with addrlib's block dimensions for the sample count
(ComputeThinBlockDimension): a 64 KiB block holds width x height x
samples elements, laid out width first for 1x and 4x. A fill over part
of it, over a target whose footprint is not computed, or with a value
that has no exact clear value in the format throws at the next use.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 07:01:57 +05:30
Dean 22c30bed2b Merge pull request #4842 from LeandroLP23/fix/agc-ancillary-layer-unwritten
fix(shader): read the ancillary render target index as 0
2026-10-13 14:31:32 +13:00
lorkydey c18daed286 fix(libkernel): validate CPU stop-info buffers and cover handler state 2026-10-13 03:21:58 +02:00
jagrat Singh 8d08caa529 feat(libkernel): implement lutimes 2026-10-13 06:29:45 +05:30
Dean 510a2188cf Merge pull request #4031 from AlxcBTW/carry/pixel-ancillary-word-v3
feat(shader): give reads the masked-select pass keeps the whole pixel ancillary word
2026-10-13 13:59:10 +13:00
Dean 4430780bdd Merge pull request #3644 from DariusHQ/fix/libkernel-poll-pipes
fix(libkernel): poll pipe descriptors
2026-10-13 13:52:54 +13:00
Sanxchep Sharma 8bcf1cc0df fix(agc): size multisample guest guards by fragment blocks 2026-10-13 02:52:51 +02:00
Dean 007759a6b6 Merge pull request #4524 from jagrat04/feat/libkernel-segment-info
feat(libkernel): implement sceKernelInternalMemoryGetModuleSegmentInfo
2026-10-13 13:52:34 +13:00
Yunus Shaikh 4ccf888291 fix(savedata): leave the mount result untouched when sceSaveDataMount3 fails
Animal Well (PPSA22520) checks for its save with a CREATE2 mount it never
unmounts, then saves with a second mount of the same directory. That
mount returns BUSY, and the title keeps using the first mount point for
sceSaveDataPrepare, its save file and sceSaveDataUmount2.
sceSaveDataMount3 cleared the result before its checks, so the save was
written to "/save" in the game folder instead of the save directory, and
the first mount was never released. The result is now written only when
the mount succeeds, as shadPS4 does.
2026-10-12 17:47:46 -07:00
jagrat Singh ec0d61e58e feat(libkernel_sys): implement mkdirat 2026-10-13 06:11:56 +05:30
Dean Galvin 64ca6e3329 fix(libkernel): follow pollscan for a pipe whose other end is closed
FreeBSD's pollscan clears POLLOUT whenever POLLHUP is set, so a write end
whose read end is closed reports POLLHUP alone, with POLLIN and POLLRDNORM
when they were asked for; both host paths reported POLLOUT | POLLHUP.

POLLOUT on a read end now throws. FreeBSD opens both ends FREAD | FWRITE
and pipe_poll reports the read end writable, which a one-way host pipe
cannot back.

guest_poll drained 1 KiB from the full pipe before expecting POLLOUT, but
Linux reports it only once a whole 4 KiB page is free, so the test aborted
there. It now drains the pipe, which is writable on every host.
2026-10-13 13:37:28 +13:00
babyhuey c15e9f2a37 fix(libSceVideoOut): return RESOURCE_BUSY when a bus is opened twice 2026-10-12 20:26:26 -04:00
LeandroLP23andClaude Opus 5.5 3334e41e45 fix(shader): read the ancillary render target index as 0
No pre-rasterization stage writes Layer: vertex layer exports are
ignored, so the first layer is used and the render target index field
of the packed ancillary word is 0. The lowering read the Layer builtin
for it instead. AMD's Windows driver drops the color writes of a
fragment shader that consumes an unwritten Layer, which made
agc_driver_relative_ancillary fail on AMD hardware (#4800); lavapipe
returns 0 there.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:23:56 +13:00
Dean Galvin c52321fab5 fix(shader): move the primitive class to request version 19 and compose the ancillary word with render target index 0
main reads target.vertexSubgroups at request version 18 since #4470, so
reading the pixel primitive class at 18 as well read a version 18
request written by main one byte short. The class is now written and
read at version 19. agc_shader_memory loads a version 18 request as
main writes it, and it fails with "truncated data" when the class is
read at 18.

The composed word no longer reads the Layer builtin for bits 16-28.
Draws render to a single layer and guest layer exports are ignored, so
no stage writes Layer, and AMD's Windows driver drops the writes of a
fragment shader that reads it unwritten (#4800). The field is the
constant 0 and pixel_ancillary checks that the composed program has no
Layer read. The debt entry names the bits that have no source and are
assumed zero (2-7, 12-15, 29-31), and says that a change which makes
draws export a layer must restore the read.
2026-10-13 13:18:51 +13:00
Simon 51c043ba51 fix(agc): keep the texels of CMASK tiles with codes other than 0 and 15
A fast-clear materialization threw when a CMASK nibble held a code other
than 0 (cleared) or 15 (expanded). PPSA18391 (engine: Clickteam Fusion) fast
clears a target whose CMASK it never initialized, so some nibbles hold
leftover values such as 1 and 10, and presentation failed on the first
frame.

Such a tile now keeps its texels like an expanded tile, on the CPU path
and in the compute pass. A cleared tile of a DCC target still throws.
The graphics and CMASK fast-clear tests now check that an unknown code
leaves the tile unchanged instead of expecting the throw.
2026-10-13 02:17:33 +02:00
AlxcBTWandClaude Opus 5.5 d0aca69eff test(agc): a relative read of the whole ancillary word gets the composed word
The relative-ancillary test expected the whole-word read through
v_movrels to be refused, which was main's behaviour before the word was
composed. It now converts that read to float and exports it: the
composed word of a triangle draw is 2 (primitive class 2, sample 0,
layer 0), so the pixel is 255, with and without the implicit position
inputs in front of the ancillary VGPR. TechnicalDebt's relative
addressing entry no longer says that whole-word uses throw.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:06:27 +13:00
AlxcBTWandClaude Opus 5.5 18d9874a06 feat(shader): give reads the masked-select pass keeps the whole pixel ancillary word
A packed ancillary word that still reaches an export, or any other read
the masked-select pass cannot drop, no longer stops the recompile. After
that pass every remaining use gets the composed word: the primitive class
at bits 0-1, SampleId at bits 8-11 and Layer at bits 16-28, with every
other bit zero. Those lanes do export the ancillary VGPR on the console,
so the word has to be right, not just present.

The primitive class (0 point, 1 line, 2 triangle, 3 rectangle) comes from
the draw. RasterPrimitiveOf maps rect lists to 3, line lists on the vertex
path to 1 and everything else the driver accepts to 2, because its
geometry and tessellation paths only output triangles. It reaches the
shader as pipeline specialization constant 8233, the way dual-source
blending does: a request field that is folded into the specialized
module and is part of the result memo, the draw key and the serialized
request (version 17).

Only shaders that read the class pay for it. ShaderInfo records the read
(disk cache format 28), and only those shaders put the class in their
module key, so a shader that reads just the sample or layer field keeps
one module for every primitive class. The draw sets the class only when
the pixel shader loads the ancillary VGPR, so other draws keep the draw
cache entries they have today.

The VRS rates (bits 2-5) and the eye id (bit 7) are 0 because the driver
supports neither VRS nor multiview. SampleId is 0 because the driver
rejects MSAA and per-sample shading, and Layer is 0 while it ignores
vertex layer exports. TechnicalDebt.md records the layout sources and
these assumptions.

Tests:
- pixel_ancillary builds an export to target 0 whose two channels select
  between a packed value and a phi carrying the word. It checks the word
  for each primitive class, sample and layer, checks that the three
  shapes the masked-select pass keeps now compile with the composed word,
  and that a program whose select the pass drops reads no class.
- agc_driver_pixel_ancillary_word exports the word from a draw and reads
  back 2, 3 and 1 for triangle, rectangle and line. A shader that reads
  only the sample field shares one module across the classes, and the
  whole-word shader gets one per class. It also checks RasterPrimitiveOf.
- agc_shader_memory covers the version 17 round trip, and
  agc_shader_disk_cache the new flag.

Both ancillary tests fail with the old refusal when the composition is
disabled.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:06:21 +13:00
JJenkx d6728f4e51 fix(relinker): record declared host imports in guest registries 2026-10-12 20:05:34 -04:00
Dean 1c5e62878a Merge pull request #425 from MichonGoddijn231849/feat/depth-surface-reads
feat(agc): depth planes sampled as 2D arrays, cubes and integer views
2026-10-13 12:58:34 +13:00
Dean e55b881f0f Merge pull request #4598 from Lorkydey/feat/ngs2-listener-transform
feat(libSceNgs2): support default listener calculation
2026-10-13 12:56:18 +13:00
JJenkx 64e5a2c119 feat(libc): implement x87 long-double finite classification 2026-10-12 19:52:22 -04:00
alfalfa-starandClaude Opus 5.5 fd98327ba7 fix(agc): take a memory value fill only when the hardware stores the raw value
The kernel reads its value with s_buffer_load_dword through the V# in
user[4..7] and stores it with buffer_store_format_x through the V# in
user[0..3]. When the value V# covers less than a dword (NUM_RECORDS
times its stride, or NUM_RECORDS bytes for stride 0) the load returns 0,
and a store format other than 32_UINT, 32_SINT or 32_FLOAT converts the
value, so in both cases the HTILE does not receive the dword read from
memory. The match now requires both. Kena's own dispatch (format
32_UINT, a value V# of one 16-byte record) still matches.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:40:31 +13:00
alfalfa-starandClaude Opus 5.5 d31b13f491 fix(agc): take an HTILE fill from a value in memory as a depth fast clear
PPSA01802 (Kena: Bridge of Spirits) clears its depth HTILE every frame
with its own compute kernel: a 9-word dword fill that stores, through
the stride-4 V# in user[0..3], a value loaded from the pointer in
user[4..5]. Neither the DMA_DATA hook nor the fill kernels the driver
recognizes saw it, so the depth kept the first frames' contents and the
base pass and sky failed their depth test almost everywhere.

The kernel is matched exactly when the dispatch is decoded, the value is
read from guest memory, and the range is passed to NoteDepthMetadataFill
like a fill, so the whole-HTILE and ZMask rules apply unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:40:24 +13:00
Dean e6ecece94e Merge pull request #4267 from EagleBearerYS/fix/shader-color-compare-8bit-unorm-zero
fix(shader): return 0 for 8-bit UNORM color comparison
2026-10-13 12:38:49 +13:00
Dean Galvin 90d899d982 fix(agc): first-slice view of depth plane arrays, refuse plane copies of another host format
A 2D-array T# over a depth surface bound to a shader image declared 2D had
no first-layer view, so the descriptor got a null view and the shader read 0.
The depth plane texture now creates the 2D view of its first slice when its
view is a 2D array, for the depth image itself and for the plane copy.

A 16-bit depth surface with stencil may be stored as D24_UNORM_S8_UINT or
D32_SFLOAT_S8_UINT. The plane copy sizes and copies slices by the guest
format, so several slices or an R16_UINT view of such a surface now throw.
2026-10-13 12:18:50 +13:00
MarcZX100 cbd615bb42 fix(agc): return error for unsupported init versions 2026-10-12 23:15:39 +00:00
8a7e1195d4 feat(exports): export the calls PPSA01317 imports
Gran Turismo 7 (PPSA01317) fails to load on unresolved imports and on
two needed libraries that AnyPS5 does not build (#4782).

- sceAppContentDownloadDataFormat empties /download0, as
  sceAppContentTemporaryDataFormat does for /temp0.
- sceNpAuthSetTimeout returns REQUEST_NOT_FOUND for an unknown request
  like the other request calls, and OK otherwise; no request reaches the
  network the timeouts would bound.
- sceNpWebApi2PushEventSetHandleTimeout throws for an unknown library
  context, like sceNpWebApi2GetMemoryPoolStats, and returns OK
  otherwise; push event handles are not tracked and nothing waits on
  one offline.
- sceSslDisableVerifyOption, sceSslGetAlpnSelected, sceSslSetAlpn,
  sceSslSetMinSslVersion, sceAudioOutDeviceIdOpen and the unnamed
  libScePsml NIDs xNZM9Y5lf-M and lcZD9tJraAw are declared without
  parameters and throw; their signatures are unknown.
- libSceUsbStorage and libSceUsbStorageDialog exist with no exports,
  like libSceXml: the title lists both as needed but imports nothing
  from them.

Each assumption is recorded in the library's technical debt file.

Co-authored-by: dawid-swiecicki <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:11:29 +02:00
Michon 086f7d5091 feat(agc): depth planes sampled as 2D arrays, cubes and integer views
A texture over a depth surface could only sample one 2D slice of the
plane's own format; 2D arrays, cubes and the R16_UINT view of a D16
plane were refused ("sampling the depth plane of depth surface ... is
not implemented"). A one-slice 2D array now views the depth image as an
array. Several slices, a cube, or an integer view of a D16 plane are
copied into a DepthPlaneCopy image at every use: each slice from the
depth surface bound at its address (base plus one 64 KiB-block depth
slice per layer), otherwise from guest memory, detiled. A depth-bits
R16_UINT view (a depth swizzle) keeps the depth copy, since the shader
converts the sampled depth to its bits itself (GTA V's compute
0x242d4a200 samples a D16 plane array that way, reported by
@tibzejoker). Such a texture is not kept in resource templates.

Storage-image access to depth surfaces is no longer part of this
change; #4500 implements it.

TechnicalDebt (Depth plane copies) and ARCHITECTURE describe the copy and
what still throws.
2026-10-13 12:11:02 +13:00
Dean 90c683946f Merge pull request #4819 from oneandonlydean/up4/fix-kqueue-test-flake
fix(libkernel): pair the inotify halves of a rename in a watched directory
2026-10-13 12:03:30 +13:00
jagrat Singh ea03a22c7f feat(libkernel): implement sceKernelInternalMemoryGetModuleSegmentInfo 2026-10-13 04:29:25 +05:30
Dean Galvin 59fcdea9c4 fix(libkernel): pair the inotify halves of a rename in a watched directory
inotify queues IN_MOVED_FROM and IN_MOVED_TO of a rename one after the
other. The watcher thread could read the first before the second was
queued and report a rename inside the directory as a move to another
directory (NOTE_WRITE | NOTE_EXTEND instead of NOTE_WRITE), which made
guest_kqueue abort on loaded runners.

The watcher now reads the queue until it is empty and, when a move half
has no partner, calls getdents64 on the directory before reading again:
that takes the directory lock rename holds until both halves are queued.
2026-10-13 11:53:02 +13:00
jagrat Singh 59bd0c1782 feat(libkernel): accept MADV_PROTECT advisory hint in madvise 2026-10-13 04:21:59 +05:30
winstrexandClaude Opus 5.5 44debb29b6 docs(debt): record the sceAgcGetGsPrimPayload search and null pointers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 19:46:20 -03:00
AlxcBTWandClaude Opus 5.5 52c71b837c feat(agc): add APS5_TRACE_SUMMARY_EVERY for summary lines of a long session
APS5_TRACE_SUMMARY_EVERY=<seconds> appends one line to aps5-summary.jsonl
every <seconds> seconds, at a present, from the per-scope totals the trace
threads already keep. No event buffer is allocated unless a window switch is
set as well; then the window records its full trace on top of the intervals
and its own summary line holds only the time inside the window. Each line has
the fields of the window summary line for its interval plus interval_start_s
and interval_end_s.

tools/trace_digest.py prints a summary file with interval lines as one row
per interval with a text sparkline of the frame p99 and the GPU busy time.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:40:52 +02:00
Yunus Shaikh 56d35172f5 fix(libkernel): accept flag 0x8000 in sceKernelMapFlexibleMemory
The libc.prx heap that Animal Well (PPSA22520 01.000.011, SDK 9.04)
bundles maps each arena with sceKernelMapFlexibleMemory(&addr, len, 3,
0x8000). It threw "Unsupported memory mapping flags 0x8000" before the
first frame. The flag is ignored as sceKernelMapNamedFlexibleMemoryInternal
already does; other unknown flags still throw.
2026-10-12 15:38:48 -07:00
MarcZX100 1988607409 test(agc): cover unaligned shader ABI headers 2026-10-12 22:28:55 +00:00
Dean df5108f90e Merge pull request #4530 from babyhuey/feat/libkernel-internal-memory-available-size
feat(libkernel): export sceKernelInternalMemoryGetAvailableSize
2026-10-13 11:16:17 +13:00
Gjon Gojcevic 7ee6e4af20 fix(shader): load the PERSP_SAMPLE and LINEAR_SAMPLE I/J pairs
The pixel entry prologue filled only the center and centroid pairs, so a
shader interpolating through a sample pair read I = J = 0 and every
attribute came out as its P0. Give the sample pairs their SPI_PS_INPUT_ADDR
VGPRs, fill them with the barycentrics of their kind, and classify
attributes read through LINEAR_SAMPLE as NoPerspective for host
interpolation.
2026-10-12 18:05:53 -04:00
p3nicillinandClaude Opus 5.5 1d115b8962 feat(libScePad): apply the angular velocity deadband
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 22:29:57 +01:00
Adrià 584cc4c571 Merge pull request #4761 from p3n1cillin/claude/agc-driver-validation-debug
feat(libSceAgcDriver): answer validation and shader debugging queries as the retail library does
2026-10-12 23:22:01 +02:00
Adrià 55b2b332c3 Merge pull request #4766 from p3n1cillin/claude/libc-heap-report-for-game
feat(libc): report heap backtraces and heap errors requested by the guest heap
2026-10-12 23:21:56 +02:00
p3nicillinandClaude Opus 5.5 e284717ebe feat(libSceAudioOut): list no audio descriptors in sceAudioOutExGetMonitorInfo
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 23:19:02 +02:00
babyhuey ff56dadc0a feat(libkernel): export sceKernelInternalMemoryGetAvailableSize 2026-10-12 17:18:53 -04:00