Commit Graph
5901 Commits
Author SHA1 Message Date
libretroadmin b71fbaeb5c libretro: fix OOB, UAF, data races and control flow in core glue
System_AudioPushSamples converts straight into the output buffer: the
block loop never advanced the source pointer and copied numSamples*2
int16s out of a 2048-sample stack buffer, a stack OOB read for any push
over 1024 frames. Realloc failure drops samples instead of crashing and
log_cb is NULL-checked. retro_serialize refuses to write a state larger
than the frontend's buffer, retro_get_memory_data/size return nothing
until PSP memory is mapped, deferred unserialize no longer leaks the
previous buffer, and the cheat entry points stop leaking a CWCheatEngine
per call.

The emu thread acknowledges a pause with a CAS so it cannot clobber a
concurrent quit request. EmuThreadStop stops and joins from any live
state, so unloading while paused no longer leaves a thread running over
freed state. EmuThreadPause pumps queued frames until the thread parks,
via a new non-blocking GLRenderManager::HasQueuedThreadWork() check,
instead of draining one frame, which deadlocked when the thread was
blocked on a readback sync in the next frame. retro_run resumes a paused
thread and pauses it before check_variables() rewrites g_Config,
retro_reset stops it before PSP_Shutdown(), and the sleep_ms(4) after
resume is gone.
2026-10-13 13:50:05 +02:00
Henrik Rydgård 0af0d86470 Merge pull request #22542 from hrydgard/faster-build
Faster CMake builds: libc++ transitive includes, less glslang/SPIRV-Cross, include cleanup
2026-10-13 12:57:43 +02:00
Henrik RydgårdandClaude Opus 5.5 e602aa1548 Add includes that were only arriving transitively
VertexDecoderRiscV.cpp got <cfloat> through SmallDataConvert.h, and three
headers used malloc/free without <cstdlib>, which libc++ no longer brings in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:36:06 +02:00
Henrik Rydgård 3c25f21bae Merge pull request #22541 from hrydgard/libretro-fork-fixes
Various bugfixes from libretro's experimental fork
2026-10-13 12:26:27 +02:00
Henrik RydgårdandClaude Opus 5.5 a361dfc490 Drop unused Config.h and SmallDataConvert.h includes
Config.h is edited about 100 times a year and each edit recompiled 198
files; now 172. SmallDataConvert.h pulls in arm_neon.h and was included by
headers that don't use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:13:42 +02:00
Henrik Rydgård f8c1e39315 Merge pull request #22535 from hrydgard/tvos-support
Apple tvOS support prototype (and CI)
2026-10-13 10:03:15 +02:00
Henrik RydgårdandClaude Opus 5.5 625db43746 tvOS: Back on the main screen goes to the home screen, like on Android
tvOS only does that with a Back press it gets to see, so the view controller
lets controller events through to UIKit while the top screen is top level
(the new TOP_LEVEL_CHANGED notification), and passes presses that aren't
keyboard keys on to super. Elsewhere Back stays ours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:29:26 +02:00
Henrik RydgårdandClaude Opus 5.5 31918b8636 UI: Arrow key focus moves by beam and edge distance
Replaces the center-to-center scoring, which skipped a wide view between narrow
ones, since its center is far away even when its edge is right there. Now it
works like Android's FocusFinder: only views in the direction of the move are
candidates, ones in the origin's beam beat ones off to the side (going up or
down, unless those are in a nearer row), and otherwise the nearest wins, with
distance along the move weighted 13 times distance across it. Unlike Android,
the distance across is to the candidate's nearest edge rather than its center.

First/last and page moves keep their scoring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:31:07 +02:00
Henrik RydgårdandClaude Opus 5.5 847625359d HTTP connect: re-arm the select() set on each wait, and skip failed sockets
select() clears the sockets that aren't ready, so after one 0.5 s slice
with no connection the loop waited on an empty set and every connect
slower than that ran out the whole timeout. A socket that turns writable
because its connect failed was also taken as connected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 02:24:05 +02:00
LibretroAdmin 664f6ff5ad D3D11: work on a context that refuses ID3D11DeviceContext1
D3D11DrawContext takes its base context from the deviceContext
argument, and the blend state is bound through the base context, which
accepts an ID3D11BlendState1 as is. ID3D11DeviceContext1 is optional:
RetroArch's threaded video hands v1 cores a deferred-context proxy that
answers ID3D11DeviceContext only, and the core now starts on it.
2026-10-13 02:23:48 +02:00
Henrik RydgårdandClaude Opus 5.5 7c9765d02c Add PPSSPP_PLATFORM(TVOS), skip sigaltstack on tvOS
tvOS doesn't have sigaltstack, which broke the libretro tvOS build. The
exception handler now runs on the faulting thread's stack there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:42:33 +02:00
Henrik Rydgård 4c48f85664 Merge pull request #22527 from hrydgard/vulkan-prerotate-270
Android: Pre-rotate reverse landscape on Vulkan again, fix insets for hidden bars
2026-10-12 19:45:55 +02:00
Henrik RydgårdandClaude Opus 5.5 60c06d4f03 Darwin: Reserve space for the memory views instead of probing for it
On iOS, the base search stepped up from 0x100000000 in 8MB increments,
right through the app's binary and early heap: about 100 failed
vm_remaps (each logged twice) every time a game started. On macOS,
Find4GBBase freed its probe allocation before the views were mapped.

Now the kernel picks a free range of exactly the span the views need,
which stays reserved and inaccessible, and the views are mapped over it
with VM_FLAGS_OVERWRITE. One try, no race, and the gaps between views
fault. Unmasked (macOS), ask for 4GB alignment first, which lets the
ARM64 JIT pointerify. The old search remains as a fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:08:03 +02:00
Henrik RydgårdandClaude Opus 5.5 09e9c0176b Fix the scissor clamp for 90 and 270 degree pre-rotation
With 270 degree pre-rotation, the rotated y runs along the physical
height, but was clamped to the physical width, so scissors on the left
of the screen moved. This was #15773, which got that pre-rotation
disabled. The 90 degree case had the bounds swapped too, but only too
loose there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:59:06 +02:00
Henrik RydgårdandClaude Opus 5.5 0886063fba Vulkan: Pre-rotate reverse landscape again
The 270 degree pre-rotation was disabled in e6b7817cc6 for #15773 (UI
disappearing in reverse landscape on a Poco X3 Pro), which left reverse
landscape to the compositor, and every present returning SUBOPTIMAL. Try
it again: rotation is handled in place now, and the stale extent after a
rotation is fixed, so it needs retesting on Adreno.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:59:06 +02:00
Henrik RydgårdandClaude Opus 5.5 f7ec86c5d5 Android Vulkan: Don't trust a stale surface extent after a rotation
Since rotation is handled in place, the swapchain is recreated right
after surfaceChanged, and the surface can still report the previous
orientation's extent. On a Galaxy S8+ this happened in about one in four
rotations, leaving a portrait swapchain on a landscape window or the
other way around, squashed into half the screen until the next rotation.

If the extent is exactly the window size transposed, use the window size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:22:41 +02:00
Henrik RydgårdandClaude Opus 5.5 08649f0f15 UI: Make switchScreen replace the whole screen stack
It only replaced the top screen, but most callers switch from a dialog:
Play on the game screen, the store, the installers, the framedump
launcher. The screens under it stayed alive, so launching a game from the
game screen and exiting it left [MainScreen, MainScreen], one more each
time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:21:10 +02:00
Henrik RydgårdandClaude Opus 5.5 56580581e0 Android: Check for Java exceptions after content URI calls
ContentUri catches Exception, but an Error got through, and none of the
native wrappers checked. A thrown int call returned 0, which reads as
SUCCESS, and the exception stayed pending, so the next JNI call aborted.
copyDocument/moveDocument are API 24/25 while the folder browser is
offered from 21, so those threw NoSuchMethodError there - now they return
a failure so the callers fall back.

Also convert non-URI names to Java's modified UTF-8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:41:19 +02:00
Henrik RydgårdandClaude Opus 5.5 24d8955531 UI: Handle a caller finishing itself from dialogFinished()
That set dialogFinished_ to the caller, which processFinishDialog() then
deleted while it was still in the stack, leaking the popup. Take the
pointer out first and loop. Nothing does this now (MemStickScreen and
DevMenuScreen work around it), but it's easy to do by accident.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:59 +02:00
Henrik RydgårdandClaude Opus 5.5 a7229ce1c8 UI: Don't let a popup complete twice during its fade-out
ignoreInput_ doesn't stop a tap outside the box or Enter on the default
button, which both call TriggerFinish() again during the lead-out, firing
OnCompleted and the choice's OnChange a second time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:59 +02:00
Henrik RydgårdandClaude Opus 5.5 27899cc875 UI: Give views in lazily created tabs the views requester token
GetRequesterToken() only returns the views token inside CreateViews(),
but tabbed screens create every tab other than the first on demand, and
the persist restore after CreateViews() can create one too. So text
inputs and file choosers there (Networking tab nickname, search filter,
RemoteISO and achievement settings) registered their [this] callbacks
under the screen token, which a recreate doesn't forget. Open the native
input box, rotate, press OK, and the callback wrote through the deleted
view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:49 +02:00
Henrik RydgårdandClaude Opus 5.5 0754544e27 UI: Don't recreate a screen's views while a popup is on top of it
Popups are transparent, so the screen under one still renders, and
render() ran DoRecreateViews(). A RecreateViews() on that screen (a
resize or rotation on DisplayLayoutScreen or TouchControlLayoutScreen,
MainScreen on RECENT_FILES_CHANGED from the recent-files thread, the
achievements login finishing) then deleted the choice that opened the
popup. Closing the popup wrote through it and called its handlers.

Leave the old views in place until the screen is back on top, where
update() recreates them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:38 +02:00
Henrik RydgårdandClaude Opus 5.5 88018255c2 Android: Don't read the screen stack from the UI thread on Back
NativeIsAtTopLevel() made a virtual call on the top screen from the Java
UI thread, while the render thread could be deleting it. Two quick Back
presses could hit that. Cache the flag in ScreenManager::Update()
instead, like passInputToMapper_ (now atomic too).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:29 +02:00
Henrik Rydgård 8d8009840e Merge pull request #22511 from hrydgard/android-inputbox-fixes
Claude code review: Android inputbox fixes
2026-10-12 13:20:25 +02:00
Henrik Rydgård 8c0c848a38 Merge pull request #22518 from hrydgard/input-dropout-fixes
Claude code review: Fix some control input bugs
2026-10-12 13:06:15 +02:00
Henrik RydgårdandClaude Opus 5.5 1467ef24a7 GL: Report readback failure, and convert from the format actually read
CopyFramebufferToMemory always returned true, even when glReadPixels
failed, and then copied out whatever the readback buffer held from before.
Depth was labeled D24_S8 while GL reads it as float, and the conversion
ignored the source format, so only a D32F destination came out right.

Record the format and the result of each read, convert from that, and
return it. That also fixes the image readback reusing the aspect of an
earlier framebuffer readback.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 f04d99e952 Vulkan: Reject a delayed readback of the backbuffer
The backbuffer is a different image every frame, so there's no earlier copy
of it to return, and the lookup fell through to the sync readback buffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 b287b0fab5 GL: Fix the pre-4.5 sub-rectangle texture readback
The repack loop used the texture height instead of the row, and the pack
row length was the rect's right edge while glGetTexImage writes whole rows.
Only reachable from the texture debugger.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 d15e094ed6 Vulkan: Key delayed readbacks by position and aspect too
The OLD_DATA_OK readback cache was keyed by framebuffer and size only, so
two equal-size rects of one framebuffer shared a buffer and each read got
whichever was copied last. Add x, y and the aspect to the key.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 ecad07b3b1 D3D11: Fix readback of a rectangle that doesn't start at the origin
Without the shared 512x512 pack texture, the staging texture was made
bw x bh, but the copy lands at bx, by and the read starts there. Depth and
stencil were worse: CopyResource needs the whole size, so nothing was
copied, and the read ran past the end of the mapping and crashed. Only
whole-buffer reads from 0,0 (like the debugger's) worked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik Rydgård f79bb0a802 Merge pull request #22517 from eraycep/fix-vulkan-profiler-resize
Vulkan: Preserve active frame profiling queries when stopping threads
2026-10-12 11:48:46 +02:00
Eray Cepni 4158f114d0 Vulkan: Preserve active frame profiling queries when stopping threads
StopThreads is called inside the
FramebufferManagerCommon::NotifyRenderResized. Issue is, StopThreads is
called inside an active frame, then clears that active frame's timestamp
descriptions. Rendering resumes, and QueueRunner uses the empty list’s
size to select query 0, which was already written.

Fix this by preserving timestamp descriptions for the current frame
when insideFrame_ is true while retaining the cleanup for other frames.
2026-10-12 11:52:03 +03:00
Henrik RydgårdandClaude Opus 5.5 7678336e28 Android/VR input: Lock the VR key state, fix device tracking and release
pspKeys and pspAxis were written from the input thread and the render
thread without a lock. Entering VR camera adjust "released" held keys by
sending PSP button codes as keycodes, which released nothing; use
ControlMapper::ReleaseAll instead.

Input devices are now matched by ID. InputDevice objects are replaced after
device changes, so reference comparison registered the same device again.
Removing a device now releases what it was holding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 01:56:32 +02:00
Henrik RydgårdandClaude Opus 5.5 468b83a738 Android: Fix JNI string encoding, thread safety, password in debug log
GetJavaString() returned Java's modified UTF-8, so input like emoji
reached C++ as invalid UTF-8. Commands to Java now get converted the other
way. Request IDs are made on several threads, and the permissions map was
written on the Java UI thread and read on the render thread. The frame
command debug log no longer prints params, which could hold a password.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:37:19 +02:00
Henrik RydgårdandClaude Opus 5.5 e2cda3d8f0 UI: Forget the views' pending requests when recreating them
WipeRequesterToken() only reset the screen's token, after CreateViews() had
already handed it to the new views, so nothing was ever forgotten - not even
in ~Screen(), which saw a token of -1. A text input dialog open across a
RecreateViews() (on the RetroAchievements screen, a slow login failing) would
then write through a deleted PopupTextInputChoice, possibly into the field
that took its place: #21708.

Requests made while creating views now get their own token, forgotten
before the views are deleted. Screen-level requests keep the screen's token.

RequestManager: ForgetRequestsWithToken() now locks, and also drops
responses that arrived but weren't processed yet. ProcessRequests() calls
the callbacks one at a time without holding the lock, so a callback that
closes a screen drops the rest of that screen's responses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:29:47 +02:00
Henrik Rydgård ed48dd53fa Merge pull request #22504 from hrydgard/sdl-wayland-text-input-fallback
Fix text input in the ImDebugger on Linux SDL
2026-10-11 18:51:33 +02:00
Henrik RydgårdandClaude Opus 5.5 b4d5d53b8a ImDebugger: Enable text input while an imgui text field is active
Since db8ff43, a leftover local shadowed lastImguiEnabled_ in runImDebugger,
so TEXT_GOTFOCUS was never sent and SDL never started text input for imgui.
Drive it from io.WantTextInput instead, so it's only on while editing.

The regular UI and the debugger now say independently whether they want text
input, and the platform only gets TEXT_LOSTFOCUS once neither does, so leaving
an imgui field doesn't break type-to-search on the screen underneath.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 18:08:00 +02:00
Henrik Rydgård e46bd61e2e When taking a screenshot, clear all notifications except achievements. 2026-10-11 17:40:01 +02:00
Henrik RydgårdandClaude Opus 5.5 9f1278b5d6 iOS: Link MoltenVK statically in sideload builds too, raise target to 15.0
Sideload builds used to dlopen a bundled libMoltenVK.dylib, which was
only worth having while they could still fall back to OpenGL. Now both
variants link the static MoltenVK from ios/MoltenVK and call Vulkan
directly. PPSSPP_VK_STATIC replaces the IOS_APP_STORE checks in the
Vulkan loader (the iOS libretro core still loads at runtime).

The static MoltenVK needs iOS 15.0, so that's now the deployment target
for all iOS builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:13:28 +02:00
Henrik RydgårdandClaude Opus 5.5 5704b972e7 iOS: Remove OpenGL support from the app
The app now always uses the Metal view controller with Vulkan (MoltenVK),
for both the App Store and sideload builds. The GL view controller is gone,
and Common/GPU/OpenGL (except GLFeatures, used by the shader generators) and
GPU/GLES are no longer compiled for it. PPSSPP_API_ANY_GL is now off for
all of iOS except the libretro core, which still uses GLES.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:13:28 +02:00
Henrik Rydgård f70df399ab Merge pull request #22494 from hrydgard/jit-shadow-block-map
JIT shadow block map: Keep JIT block entries and replacement hooks out of PSP memory
2026-10-11 12:46:42 +02:00
Henrik Rydgård 7572ac05ca Screenshot code cleanup, fix issue where the notification would be in a second fast screenshot
Fixes #22497
2026-10-11 10:56:43 +02:00
Henrik RydgårdandClaude Opus 5.5 6d122f416e Keep JIT block entries and replacement hooks out of PSP memory
The JITs used to find a block by overwriting its first instruction with an "emuhack" holding
the offset into the code space, and replacement functions installed their own emuhack the same
way. Anything that read code (savestates, the debugger, memory dumps, cheats, the function
hasher, games reading their own code) had to translate them back.

Blocks now live in a block shadow: one u32 per guest instruction, indexed by the PC masked with
BLOCK_SHADOW_MASK (1GB on 64-bit, folding the kernel and uncached mirrors; 256MB on 32-bit, iOS
and Switch, where address space is short), with the low bits cleared so a misaligned PC can't
read across two entries. Only the ranges under memory views are committed, so a bad PC still
faults in the dispatcher, and the shadow is reserved before the memory map so it can't land in
a gap of the 4GB window. Entries hold full 32-bit offsets, lifting the 16MB limit. The
dispatchers on every backend, and the IR interpreter's loop, look blocks up there.

A hooked instruction without a compiled block gets the JIT's hook value in its entry: the offset
of the dispatcher's compile path (1 for the interpreters, the IR arena keeping that offset
empty), so dispatching there compiles a block, and the frontends substitute the hook. Compiling
replaces the entry with the block's, and destroying the block puts the hook value back. The hook
value is rewritten when the JIT changes or regenerates its dispatcher.

Hooks live in a map keyed by the masked address, and are dropped when the game overwrites the
hooked instruction, or when an icache invalidation finds the function's hash (immediates masked,
as when matching it) changed. Those checks run when queued invalidations are processed, since
cheats and the debugger queue them before writing. Installing and removing hooks invalidates
deferred, as it happens in HLE calls that can run inside a block. The cache instruction goes
through MIPSState, so it drops changed hooks too.

With clean memory, the save/clear/restore around savestates, memory reads and dumps goes away,
as do the source-range invalidations in the memcpy replacements, sceDmac and the cheats.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:33:30 +02:00
Henrik RydgårdandClaude Opus 5.5 6cf4872e78 Android: Hand microphone input over on the CPU thread, like the other hosts
The Oboe input callback used to call Microphone::addAudioData directly,
writing PSP memory from the audio thread. Now it only pushes samples
into a SampleRing, and pollRecording drains it on the CPU thread.
Starting and stopping still go through Java, which asks for permission.

Every host with a microphone polls now, so sceUsbMic drops what only the
push path needed: QueueBuf's recursive mutex, restarting the mic on a
device change, and the startMic parameter nobody read. Also removes the
unused System_AudioRecordingState and Microphone::isNeedInput.

The Java microphone_command branch didn't return true, so every command
logged "processCommand failed".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 18:49:21 +02:00
Henrik RydgårdandClaude Opus 5.5 1e5a54e7b5 Move the microphone's lock-free sample ring to Common/Audio/SampleRing.h
Android is about to need the same one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 18:49:21 +02:00
Henrik RydgårdandClaude Opus 5.5 b4ec29111b Microphone: Let the host say whether it wants polling, rather than checking for SDL
The CPU-thread polling added for SDL was keyed off defined(SDL), which
headless and Core are built with too, hence the extra headless check.
Ask the host instead, with SYSPROP_MICROPHONE_NEEDS_POLLING, so other
hosts can hand their input over the same way.

startMic now sends the same startRecording command for every non-Win32
host, taking the rate from curSampleRate like the SDL path did. The
Android path read it from param, which leaked, and which is null when
coming from onMicDeviceChange.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:20:48 +02:00
Henrik Rydgård 7b716e6f33 Merge pull request #22459 from chriopter/sdl-microphone
SDL: Add microphone capture and device selection
2026-10-10 17:01:04 +02:00
Henrik Rydgård bd3e55a104 Merge pull request #22487 from hrydgard/android-lifecycle-fixes
Android lifecycle fixes, file sharing support (unused)
2026-10-10 16:43:58 +02:00
Henrik RydgårdandClaude Opus 5.5 77a6abfe6e Add System_ShareFile, for handing a file to another app
Offers a file through the system share sheet, for things like sending a
zipped savestate to a friend. Android for now (SYSPROP_SUPPORTS_SHARE_FILE):
content:// paths from a picked folder are shared as they are, and plain paths
through a FileProvider. Either way the receiving app can read just that file.
With no MIME type given, it's guessed from the extension.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 15:59:42 +02:00
Henrik Rydgård 6779143827 Merge pull request #22486 from hrydgard/softgpu-x86-opt
SoftGPU: Do an optimization pass on x86-64 too
2026-10-10 15:48:04 +02:00