Skip to content

sync: upstream batch 12 (155 PRs, 467 upstream commits, 5 slices) - #519

Merged
RINNECODER merged 235 commits into
mainfrom
sync/batch-12
Oct 16, 2026
Merged

RINNECODER merged 235 commits into
mainfrom
sync/batch-12

Conversation

@RINNECODER

Copy link
Copy Markdown
Owner

Upstream Sync Batch 12: Comprehensive Summary

Date: 2026-10-16
Upstream Range: d92a8dad3..5d9dcc42d (155 upstream merged PRs, 467 commits)
Fork Base: origin/main (47568ebcb)
Fork Head: sync/batch-12 (6a84f5d70, 235 commits ahead of origin/main)
Worktree: wt/sync-batch-12


1. Executive Summary

Upstream Sync Batch 12 successfully ingests and reconciles all upstream developments from d92a8dad3 to 5d9dcc42d. The sync was partitioned into 5 functional slices and executed cleanly:

Slice Functional Area Commits Head Commit Status Tests Passed
12A Relinker 21 b2cf878ea Complete 213/213 tool tests, Rosetta tests
12B Libkernel & Libc 41 70de20a4d Complete 20/20 CTest, libc suites
12C Small Libs (AudioOut, Ngs2, Fiber, SaveData, Ajm, Dialogs) 44 173f531f2 Complete 20/20 CTest, audio suites
12D Shader Recompiler & SPIR-V Bridge 24 38232e285 Complete 4/4 shader bridge, 62/62 guest replay
12E Shared AGC Logic, State, HTILE, MSAA, & Driver Updates 105 6a84f5d70 Complete 20/20 Rosetta CTest, 62/62 guest replay
Total Full Integrated Tree 235 6a84f5d70 Complete 100% across all suites

2. Key Reconciliations & Technical Adaptations

  1. Relinker Rosetta Compare Hazard (fix(relinker): isolate Rosetta scalar compare hazards boykopovar/AnyPS5#5683 vs Fork relinker: run Rosetta-mistranslated scalar compares out of line #480):
  2. macOS Host Compatibility Fixes Ported from Upstream:
  3. Shader Recompiler Serialization & Specialization (Slice 12D):
  4. Shared AGC Improvements (Slice 12E):

3. Evidence & Verification

A. Rosetta Configuration (build-rosetta)

CTest command: ctest --test-dir wt/sync-batch-12/build-rosetta --output-on-failure

  • Results: 20/20 tests passed (100%, 45.31s real time)
    • rosetta_direct_graphics: Passed
    • rosetta_image_cache: Passed
    • rosetta_direct_host_window: Passed
    • metal_utility_tests: Passed
    • rosetta_launcher_tests: Passed
    • direct_memory_darwin: Passed
    • audio_out2_pacing, audio_out2_timing, audio_out2_port_buffers, audio_out2_port_layouts: Passed
    • rosetta_cpuid: Passed
    • rosetta_runtime_threads, rosetta_runtime_fault, rosetta_launcher_smoke: Passed

B. Guest Replay Configuration (build-guest-replay)

  • Results: 62/62 tests passed (100%)
    • anyps5_metal_agc_host_exports: Passed
    • anyps5_metal_msaa_depth: Passed
    • anyps5_metal_guest_replay: Passed
    • Shader semantics and execution fixtures: Passed

C. Shader Bridge Configuration (build-shader-bridge)

  • Results: 4/4 tests passed (100%)

4. Branch References

All slice branches have been created in wt/sync-batch-12 and are ready for push:

  • sync/batch-12a-relinker (b2cf878ea)
  • sync/batch-12b-core-libs (70de20a4d)
  • sync/batch-12c-small-libs (173f531f2)
  • sync/batch-12d-shader-recompiler (38232e285)
  • sync/batch-12e-agc (6a84f5d70)
  • sync/batch-12 (6a84f5d70 - complete batch)

mariuszkreft and others added 30 commits October 16, 2026 01:16
ComputeExtraBlockVaddr kept the ELF congruence p_vaddr == p_offset (mod 0x1000)
and bumped the result by one page only when it fell below the highest guest
load end as a byte address. When that end is not page aligned and the extra
block's file offset remainder reaches it, the extra RWX PT_LOAD landed in the
same 4 KiB page that holds the tail of the highest guest segment. The kernel
maps each PT_LOAD page by page with MAP_FIXED in program-header order, so the
extra block's file page replaced the guest's .data tail and zero-filled .bss
there.

Round the highest kept PT_LOAD end up to the page before adding the offset
remainder, which is the placement GuestModuleWriter::WriteLinux already uses
for the guest module. Only the overlapping case changes; an end that is page
aligned or a remainder below it yields the same address as before.

The extra PT_LOAD now also spans to the end of its own page in p_memsz, so the
page it takes over is fully covered, and its vaddr is derived in WriteLayout
instead of being taken from the request. The header block load carries the
same flags as before.

(cherry picked from commit 58120ca)
…diagnostics

When a relinked executable fails to load a staged module, the dependency
diagnostics routine maps the same path as an image resource to walk its
imports. If that mapping failed it printed only "FAIL: dependency
diagnostics Windows API failed". The log then did not say whether the
staged module itself (libs\libSceRegMgr.prx in boykopovar#4720) was absent or was
not a Windows image, and a module reached through another module's
imports was not named at all.

The register routine now reads GetLastError when LoadLibraryExW fails.
ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND print "dependency module
not found", ERROR_BAD_EXE_FORMAT prints "dependency module is not a
Windows PE image"; both name the module path, its importer and the
chain from the executable, like the existing missing-module report.
Other errors keep the generic message. An API set contract that
LoadLibraryExA reports as ERROR_MOD_NOT_FOUND now gets the
missing-module report too.

Refs boykopovar#4720

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 4ba4ede)
The executables were written with the default file mode (0644 under a
022 umask). The documented chmod covered app.elf, but not the outputs of
--executable, so RetroArch (PPSA99169) converted with
--executable picker/picker.bin --executable es-de/es-de.bin stopped as
soon as it started its picker:

  sceSystemServiceLoadExec: execv failed: Permission denied

Every executable output now gets execute permission for owner, group and
others after it is written, as --autorun already did for app.elf. With
it RetroArch starts the picker, and the picker starts ES-DE.

(cherry picked from commit ab94ee2)
Keep it for copies that lost their mode, and name the LoadExec error a
missing execute bit gives.

(cherry picked from commit bfc95d2)
Add a unit test for the layout the relinker prints after a conversion:
the fixed header and library entries, extra executables in order, and
module paths merged into one sorted tree with directories marked and
duplicates collapsed.

(cherry picked from commit c740935)
…ess, and entry point analysis

(cherry picked from commit 9dc2ce8)
ElfReader::ReadProgramHeaders checked that a PT_LOAD's file size does
not exceed its memory size, but not that its file range lies inside the
input. The Windows and macOS writers reject such a segment later; the
Linux patcher keeps the original PT_LOADs and appends its own block at
the old end of the file, so a load reaching past the input mapped the
relinker's .dynstr, .dynsym and entry stub into the guest segment.

A PT_SCE_RELRO that no PT_LOAD covers is turned into a PT_LOAD after
the per-header checks, so it skipped them: a file size larger than its
memory size was accepted for Linux, and Windows and macOS reported a
file-range error instead.

Reject a PT_LOAD whose file range exceeds the input, and run the same
two checks on an uncovered PT_SCE_RELRO before converting it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9JfvrCsztJtbkd5SATAzL
(cherry picked from commit d7ebcf7)
…tion

ReadProgramHeaders now rejects a PT_LOAD whose file range exceeds the
input, so TranslateVirtualAddress no longer needs its own check. An
uncovered PT_SCE_RELRO outside the file reports the same "Segment offset
out of bounds" as a PT_LOAD, and a test pins that a load or uncovered
PT_SCE_RELRO ending exactly at the end of the file is still accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9JfvrCsztJtbkd5SATAzL
(cherry picked from commit 063cf48)
DecodeInstruction returned before reading the ModRM of FF /3 and FF /5,
so a far CALL or JMP through a RIP-relative pointer had no RIP-relative
displacement. A stub that moved such a JMP copied the displacement
without relocating it.

The decoder was compared with iced-x86 (AMD decoding) over 3.99 million
encodings: every opcode of the legacy, 0F, 0F38 and 0F3A maps under 34
prefix combinations and the VEX 0F, 0F38 and 0F3A maps, each with 48
ModRM forms. Apart from this, it agrees on length, RIP-relative offset,
control flow kind and branch target for every valid Zen 2 instruction
except near branches with a 66 prefix, recorded as technical debt, and
kernel-only returns, which it treats as sequential.

Add the comparison's metadata as cases: one RIP-relative encoding per
opcode, map and immediate size, every FF /r form, and the branch forms
with their flow kind and target. The existing cases check lengths only;
a loop or jrcxz decoded as an unconditional jump passed the whole suite.

(cherry picked from commit 8e812f4)
…ters and reject zero FDE CIE offset

(cherry picked from commit 7ffb671)
The Rosetta split covered only VEX scalar compares. boykopovar#5642 measured the
same lost load after legacy CMPSS and CMPSD, and the decoder already
hands them to the matcher with the right length and RIP offset.

Recognise F3 or F2, segment overrides and an optional REX before
0F C2 /r ib, with the same predicate rule as the VEX forms. A 66, 67 or
LOCK prefix, or both F2 and F3, keeps the instruction inline as before.

(cherry picked from commit ba4b2db)
…elinked module

A read-only open, stat or reachability check of a missing path listed its
directory twice: once for a case-insensitive match of the name and again for
a case-insensitive match of the relinked <name>.guest.prx (boykopovar#5434). Both
names are now matched in the same listing. Precedence and the ambiguous-name
errors are unchanged.

(cherry picked from commit eac8bfc)
…controls

Morrowind imports rtprio_thread, pthread_setconcurrency and pthread_getconcurrency and stops at start-up. Report every guest thread as normal priority and accept a set without applying it; store the concurrency level as a hint. Recorded in the libkernel debt.

(cherry picked from commit 4091519)
…est socket

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 7e79f36)
meh7an and others added 25 commits October 16, 2026 08:35
…view

Vulkan cannot view a stencil aspect as UNORM, so an 8-bit UNORM view of
a stencil plane threw. Copy the stencil aspect through a buffer into an
R8_UNORM image of the surface's extent and sample that. The copy is kept
on the surface and refreshed when the surface was written since, or while
it is the bound depth target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 47f7118)
Use checked host stdio for BMP output and stop requesting dumps after the first write failure. Keep pixel validation, allocation and non-I/O failures on the existing fatal path.

Co-Authored-By: Codex <noreply@openai.com>
(cherry picked from commit 6541db0)
…he region that holds it

Since the cached address space keeps a read-only V# that only partly
overlaps its base regions (readsOverBase), a build's own regions can
overlap base regions. UploadPrepare merges overlapping own views, so a
merged region can begin before the base region that holds a view's first
byte. owner() still took whichever candidate began later, so Descriptor
bound such a view through one base region it does not fit:

  guest buffer view 0x1f0494592c+0x1b2190 exceeds its GPU owner
  0x1f04940000-0x1f04950000 (buffer 0, direct 1, mirror 0)

owner() now takes the range's end and prefers the candidate that holds
the whole range. When both or neither do, it keeps the previous rule.
Every caller already knew the end it passes.

(cherry picked from commit d470959)
…s after UploadPrepare

UploadFinish dissolves the cached address space when an import was
retired after the space was built. The space's base regions are then
merged with the build's own regions, which since readsOverBase may
overlap them. owner() searched the merged list for the region with the
greatest begin, a base region of one mapping, so a read-only V# merged
into an own region that began earlier was bound through it again:

  guest buffer view 0x1f0390c1c4+0x10c1cc exceeds its GPU owner
  0x1f03900000-0x1f03910000 (buffer 0, direct 1, mirror 0)

The dissolve now notes when the merged list overlaps, and owner() then
looks back for a region that holds the whole range. The test's third
build retires the imports between UploadPrepare and UploadFinish.

(cherry picked from commit c54854b)
…overlaps the address space

A read-only V# that crosses imports of the cached address space is bound
through a copy of its bytes, and that copy can begin inside an import. The
BDA table listed the copy and the space's ranges by begin, and a shader
takes the last range beginning at or below an address, so the bytes from
the copy's begin to the end of that import resolved to the copy. The copy
is read-only, so a BDA store or atomic into a writable import faulted with
Permission, the GPU side of the rule owner() no longer applies on the CPU.

The table now gives every byte one range: the space's ranges, or after a
dissolve the direct and mirrored regions, keep the bytes they hold, and a
build's copies keep only the bytes nothing live holds.

(cherry picked from commit 9825181)
…the writable import

Two writable 64 KiB pieces and a read-only one, one import window each,
with a read-only V# across the boundary: through the kept address space, a
hit on it and a dissolve after UploadPrepare, the BDA table has no
overlapping ranges, stores up to the boundary resolve to the writable
import and reads past it find the read-only one.

(cherry picked from commit 253fd95)
…, and cross access

The test of two read-only V#s merged over three imports now asserts that
its second build hits the cached address space without a dissolve and that
the third leaves it only for the import change. One crossed piece is
writable, so a join of the crossed run cannot erase the overlap the test is
about.

(cherry picked from commit f3300a0)
… an import

A read-only V# across two imports into unregistered memory, a read-only and
a written V# in that memory: UploadPrepare merges the three into one copy
that begins inside the first import. The written V# maps its own bytes in
that copy, counts as a copied write, and WriteBack lands its store on its
bytes alone.

(cherry picked from commit 6d17a1d)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 5a7f183)
…oykopovar#5791)

agc_driver_mesh_index_cache aborts on the linux job (lavapipe, LLVM 20.1.2:
"LLVM ERROR: Cannot emit physreg copy instruction") on every main push build
since the merge (first red: 38777177302). The PR was merged on a
windows-only run after a linux-red batch was split.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit b8db741)
agc_pending_key_stores cleared only the first 256 bytes of its 64 KiB block and
then asked for the keys of 512 bytes. The other 256 were whatever the heap
held: when they were not all equal the range read as mixed (correctly) and
the check that it is unknown failed, so the test passed or failed with the
allocator's state (main builds after boykopovar#5784).

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit b40d527)
…ykopovar#5791)

Reapplies boykopovar#5791 (reverted by boykopovar#6552). agc_driver_mesh_index_cache now skips
on llvmpipe like agc_driver_mesh does: llvmpipe aborts compiling these mesh
programs (LLVM ERROR: Cannot emit physreg copy), which is what turned main's
linux job red.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit d92ebfa)
…ering

A guest S# with FILTER_MODE min or max and an anisotropic XY filter
threw "combines a min or max reduction with anisotropic filtering",
which stops High on Life (PPSA15388) in its home base. It now decodes
to a Vulkan sampler with both anisotropy and the reduction mode, as a
weighted-average anisotropic S# already does. RADV programs the same
S# for such a Vulkan sampler.

Tamalero's gfx1030 measurement on boykopovar#5156 covers a sample without
derivatives through a 2x anisotropic S# over a single-level texture:
min or max with anisotropic bilinear returns the bilinear minimum or
maximum, and min with anisotropic point the point result. The
execution test checks the bilinear case on the host GPU; the debt
entry records what is not measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 474ec77)
…t mappings

The names hash to the NIDs dbOlWdppb4o and vieBRwlh1Lw that the exports
carried as sceAgcUnknownCreateInterpolantMapping and
sceAgcUnknown_vieBRwlh1Lw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit a0fc988)
…egister defaults version checks

(cherry picked from commit 6ebab0e)
…pixel center

A draw with PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES > 0 and
PA_SC_MODE_CNTL_0.MSAA_ENABLE clear threw. On GFX10 and later the bit
is what makes the rasterizer use the programmed sample locations; with
it clear the draw now keeps the target's sample count with every sample
at the pixel center. Points, lines, a depth target and
alpha-to-coverage still throw.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit c632818)
…nd save without re-reading an unchanged file

The headless device is replaced by the windowed one at window attach and then only
lingers for in-flight workers, but it parsed its own full copy of the cache file.
It now starts empty (it still merges what it compiles into the file). Load reuses
the file buffer as the initial data instead of copying it, and save() writes the
live data directly when the file still carries the header this object loaded or
wrote, skipping the read-back and the merge cache.

(cherry picked from commit d65cc07)
…olds it; test the unseeded double save

(cherry picked from commit e37e5f0)
@coderabbitai

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2b2b8668-7502-4309-b1c6-e68333b0f054
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T16:24:44.280682Z 6a84f5d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a84f5d70e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

#else
entry.events = static_cast<short>(send ? POLLOUT : POLLIN);
const int ready = ::poll(&entry, 1, milliseconds);
if (ready > 0 || (ready < 0 && errno != EINTR)) return 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the timeout active through the socket operation

On a blocking socket with SO_RCVTIMEO or SO_SNDTIMEO, this returns as soon as poll reports readiness, but the subsequent recv/send remains a blocking call with no timeout. If another thread sharing the socket consumes that readiness before the caller reaches the I/O operation, the operation can block indefinitely instead of returning when the configured timeout expires. Perform the actual transfer nonblocking or otherwise keep the deadline enforced through the I/O.

Useful? React with 👍 / 👎.

static_assert(sizeof(VulkanHeader) == 32);
if (data.size() < sizeof(vulkan)) return reject("no Vulkan header");
std::memcpy(&vulkan, data.data(), sizeof(vulkan));
if (vulkan.headerSize < sizeof(vulkan) || vulkan.headerVersion != VK_PIPELINE_CACHE_HEADER_VERSION_ONE || vulkan.vendorID != properties.vendorID || vulkan.deviceID != properties.deviceID || std::memcmp(vulkan.uuid, properties.pipelineCacheUUID, VK_UUID_SIZE) != 0) return reject("made for another device or driver");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Populate the Vulkan header before validating it

The vulkan structure is value-initialized and never filled from data, so headerSize remains zero and every otherwise valid on-disk pipeline cache is rejected as belonging to another device or driver. Consequently initialData is never populated and the cache cannot warm subsequent runs, causing avoidable pipeline recompilation and stutter. Restore the copy from the cache payload before this validation.

Useful? React with 👍 / 👎.

@RINNECODER
RINNECODER merged commit fabda90 into main Oct 16, 2026
1 check passed
@RINNECODER
RINNECODER deleted the sync/batch-12 branch October 16, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.